Pagina Modulului 5
Ora 36 - Modulul 5

Implementare mișcare

Program complet cu tratarea cazurilor speciale și simulare pas cu pas

45min teorie + 15min probleme PbInfo + exerciții practice
Competențele 4.1, 5.1
Săptămâna 5
Sigla liceului
TEORIE - 45 minute

Ce vei învăța astăzi?

Trecem de la formulă la un program complet: tratăm toate cazurile speciale, adăugăm validare și facem o simulare pas cu pas a mișcării.

Program complet cu toate cazurile
Tratare: viteze egale, t negativ
Simulare pas cu pas (afișare per secundă)
Meniu interactiv cu do-while
Conversie unități (km/h ↔ m/s)

Dicționar: Matematică ↔ C++ (Simulare)

Concept matematicCum se citeșteÎn C++Observație
x(t) = x₀ + v·t„poziția la momentul t"pos = x0 + v * t;formula de bază MRU
v₀ (viteza inițială MRUV)„v zero"double v0;viteza la momentul t=0
a (accelerația)„a m/s"double a;a < 0 = decelerare (frânare)
t (timpul la pătrat)„t pătrat"t * tNU t^2 (^=XOR în C++)
|x₁ - x₂| (distanța)„modul diferență"abs(pos1 - pos2)include <cmath>
≈ 0 (aproape zero)„aproximativ zero"dist < 0.01prag de detecție întâlnire
do-while (repetare)„execută... cât timp"do { } while(cond);minim 1 execuție
setw(n), setprecision(p)„lățime n, p zecimale"#include <iomanip>formatare tabelar

Analogie: De la formulă la program

GPS-ul din mașină

Un GPS face exact ce noi facem acum: primește pozițiile (x₀) și vitezele (v) vehiculelor, apoi simulează mișcarea pas cu pas pentru a prezice unde va fi fiecare. Cazurile speciale? Dacă două mașini merg cu aceeași viteză pe aceeași bandă — nu se întâlnesc niciodată (sau merg mereu împreună)!

Formule MRU: x(t) = x₀ + v · t  |  t_întâlnire = (x₂₀ - x₁₀) / (v₁ - v₂)  |  1 km/h = 1/3.6 m/s
x(t) = x₀ + v·t  |  t = (x₂₀ − x₁₀) / (v₁ − v₂)  |  1 km/h = 1/3.6 m/s
x = x0 + v*t;  |  t = (x20-x10)/(v1-v2);  |  v / 3.6
„poziție, timp de întâlnire, conversie — cele 3 formule fundamentale MRU"

Tratarea tuturor cazurilor

Un program robust trebuie să gestioneze toate situațiile posibile, nu doar cazul fericit.

CazCondiție matematicăCe se întâmplăCod C++
Normalv₁ ≠ v₂ și t ≥ 0Se întâlnesc la momentul tt = (x20-x10)/(v1-v2)
Merg împreunăv₁ = v₂ și x₁₀ = x₂₀Mereu în aceeași pozițieif(v1==v2 && x10==x20)
Paralelev₁ = v₂ și x₁₀ ≠ x₂₀Nu se întâlnesc niciodatăif(v1==v2 && x10!=x20)
Trecutt < 0S-au depărtat dejaif(t < 0)
Trace: x₁₀=0, v₁=5, x₂₀=100, v₂=10

t = (100-0)/(5-10) = 100/(-5) = -20 → t negativ! Mobilele se îndepărtează. Mobilul 2 era la 100 și merge mai repede (v₂=10 > v₁=5), deci fuge de mobilul 1.

Împărțire la zero: Dacă v₁ = v₂, formula (x20-x10)/(v1-v2) face împărțire la 0! Verifică ÎNTÂI dacă v1 == v2 înainte de a calcula t.

Simulare pas cu pas

Ideea simulării: În loc să calculăm doar momentul întâlnirii, afișăm pozițiile ambelor mobile la fiecare secundă — ca un tabel de valori. Verificăm vizual rezultatele.

// Pseudocod: Simulare pas cu pas cu detecție întâlnire READ x10, v1, x20, v2, tmax gasit FALSE FOR t 0 TO tmax pos1 x10 + v1 * t pos2 x20 + v2 * t dist abs(pos1 - pos2) PRINT t, pos1, pos2, dist IF dist < 0.01 AND NOT gasit THEN PRINT "INTALNIRE!" gasit TRUE END IF END FOR
Simulare pas cu pas cu detecție întâlnire
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
    double x10, v1, x20, v2;
    int tmax;
    
    cout << "Mobil 1 (x0, v): "; cin >> x10 >> v1;
    cout << "Mobil 2 (x0, v): "; cin >> x20 >> v2;
    cout << "Simulare pana la t = "; cin >> tmax;
    
    cout << left << setw(6) << "t"
         << setw(12) << "Pos_M1"
         << setw(12) << "Pos_M2"
         << setw(12) << "Distanta" << endl;
    cout << "--------------------------------------" << endl;
    
    bool gasit = false;
    for (int t = 0; t <= tmax; t++) {
        double pos1 = x10 + v1 * t;
        double pos2 = x20 + v2 * t;
        double dist = abs(pos1 - pos2);
        
        cout << setw(6) << t
             << setw(12) << fixed << setprecision(1) << pos1
             << setw(12) << pos2
             << setw(12) << dist;
        
        if (dist < 0.01 && !gasit) {
            cout << "  << INTALNIRE!";
            gasit = true;
        }
        cout << endl;
    }
    
    if (!gasit) cout << "\nNu s-au intalnit in intervalul [0, " << tmax << "]." << endl;
    
    return 0;
}

De ce folosim <iomanip> aici? Nu este pentru calcule. Este doar pentru aspectul tabelului: setw(12) lasă spațiu pentru o coloană, iar fixed << setprecision(1) afișează pozițiile cu o zecimală, de exemplu 50.0. Dacă nu vrei tabel aliniat, poți afișa simplu cu cout << pos1.

Exemplu (x10=0, v1=10, x20=100, v2=5):

t     Pos_M1      Pos_M2      Distanta
--------------------------------------
0     0.0         100.0       100.0
5     50.0        125.0       75.0
10    100.0       150.0       50.0
15    150.0       175.0       25.0
20    200.0       200.0       0.0  << INTALNIRE!

Conversie unități de viteză

În fizică se folosește m/s, dar în viața reală km/h. Conversia: 1 km/h = 1000m / 3600s = 1/3.6 m/s.

km/hm/sExemplu real
5≈ 1.39Pas rapid
3610Bicicletă
50≈ 13.89Mașină în oraș
130≈ 36.11Autostradă
Funcții de conversie
double kmh_to_ms(double v) { return v / 3.6; }
double ms_to_kmh(double v) { return v * 3.6; }

// Exemplu de utilizare:
double v_auto = 90;  // km/h
cout << v_auto << " km/h = " << kmh_to_ms(v_auto) << " m/s";
// Afiseaza: 90 km/h = 25 m/s

Program complet cu meniu

// Pseudocod: Meniu interactiv Laboratorul de Fizică DO PRINT "1=Pozitie 2=Intalnire 3=Simulare 4=Conversie 0=Iesire" READ optiune IF optiune == 1 THEN READ x0, v, t PRINT x0 + v * t ELSE IF optiune == 2 THEN // calcul punct de întâlnire cu tratare cazuri ELSE IF optiune == 3 THEN // simulare pas cu pas ELSE IF optiune == 4 THEN // conversie km/h ↔ m/s END IF WHILE optiune != 0
Meniu interactiv - Laboratorul de Fizică
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
    int optiune;
    do {
        cout << "\n=== LABORATORUL DE FIZICA ===" << endl;
        cout << "1. Calculeaza pozitia unui mobil" << endl;
        cout << "2. Punct de intalnire (2 mobile)" << endl;
        cout << "3. Simulare pas cu pas" << endl;
        cout << "4. Conversie km/h <-> m/s" << endl;
        cout << "0. Iesire" << endl;
        cout << "Optiune: "; cin >> optiune;
        
        if (optiune == 1) {
            double x0, v, t;
            cout << "x0, v, t: "; cin >> x0 >> v >> t;
            cout << "Pozitia: " << x0 + v * t << " m" << endl;
        }
        else if (optiune == 2) {
            double x10, v1, x20, v2;
            cout << "Mobil1 (x0, v): "; cin >> x10 >> v1;
            cout << "Mobil2 (x0, v): "; cin >> x20 >> v2;
            if (v1 == v2) {
                if (x10 == x20)
                    cout << "Merg mereu impreuna!" << endl;
                else
                    cout << "Nu se intalnesc (viteze egale)." << endl;
            } else {
                double t = (x20 - x10) / (v1 - v2);
                if (t < 0)
                    cout << "Nu se intalnesc (t=" << t << " < 0)." << endl;
                else
                    cout << "Se intalnesc la t=" << t 
                         << "s, x=" << x10+v1*t << "m" << endl;
            }
        }
        else if (optiune == 3) {
            double x10, v1, x20, v2;
            int tmax;
            cout << "Mobil1 (x0, v): "; cin >> x10 >> v1;
            cout << "Mobil2 (x0, v): "; cin >> x20 >> v2;
            cout << "Simuleaza pana la t="; cin >> tmax;
            
            for (int t = 0; t <= tmax; t++) {
                double d = abs((x10+v1*t)-(x20+v2*t));
                cout << "t=" << setw(3) << t 
                     << " M1=" << setw(8) << x10+v1*t
                     << " M2=" << setw(8) << x20+v2*t
                     << " d=" << d;
                if(d < 0.01) cout << " *** INTALNIRE ***";
                cout << endl;
            }
        }
        else if (optiune == 4) {
            double v;
            int sub;
            cout << "1=km/h->m/s  2=m/s->km/h: "; cin >> sub;
            cout << "Viteza: "; cin >> v;
            if(sub == 1) cout << v << " km/h = " << v/3.6 << " m/s" << endl;
            else cout << v << " m/s = " << v*3.6 << " km/h" << endl;
        }
    } while (optiune != 0);
    
    cout << "La revedere!" << endl;
    return 0;
}

Compararea double-urilor: if(v1 == v2) funcționează bine aici deoarece valorile vin direct de la citire. Dar în general, pentru double-uri calculate, e mai sigur: if(abs(v1-v2) < 0.0001).

Extensie: Mișcarea cu accelerație (MRUV)

Dacă viteza se schimbă uniform, avem MRUV: x(t) = x₀ + v₀·t + a·t/2, unde a = accelerația.

MRUV: x(t) = x₀ + v₀·t + a·t/2  |  v(t) = v₀ + a·t  |  v = v₀ + 2·a·Δx
x(t) = x₀ + v₀·t + a·t/2  |  v(t) = v₀ + a·t
x = x0 + v0*t + a*t*t/2.0;  |  v = v0 + a*t;
„atenție: t*t (nu t^2!) și /2.0 (nu /2, pentru double)"
Exemplu: frânare

O mașină la v₀=20 m/s frânează cu a=-5 m/s. Când se oprește? v(t)=0 → 0 = 20 + (-5)·t → t = 4 secunde. Distanța de frânare: x = 20·4 + (-5)·16/2 = 80 - 40 = 40 m.

Trace: Simulare MRUV (frânare v₀=20, a=-5)
tv = v₀+a·tC++: v0+a*tx = x₀+v₀·t+a·t/2C++: x0+v0*t+a*t*t/2.0
02020+(-5)*0=2000+20*0+(-5)*0*0/2=0
11520+(-5)*1=1517.50+20*1+(-5)*1/2=17.5
21020+(-5)*2=10300+20*2+(-5)*4/2=30
3520+(-5)*3=537.50+20*3+(-5)*9/2=37.5
4020+(-5)*4=040OPRIT la 40m
Simulare MRUV
double x0 = 0, v0 = 20, a = -5; // franare
for(int t = 0; t <= 5; t++){
    double v = v0 + a*t;
    double x = x0 + v0*t + a*t*t/2.0;
    if(v < 0) { cout << "Oprit la t=" << -v0/a << "s"; break; }
    cout << "t=" << t << " v=" << v << " x=" << x << endl;
}

Verificare cunoștințe

1. Ce se întâmplă dacă v1=v2=10, x10=5, x20=5?

2. În simulare, cum detectăm întâlnirea?

3. De ce folosim do-while pentru meniu?

4. Cum convertim 90 km/h în m/s?

5. Dacă t_întâlnire < 0, ce înseamnă?

6. În MRUV, ce face termenul a·t/2?

Întrebări frecvente (FAQ)

De ce nu folosim switch în loc de if-else?

Putem folosi switch pentru meniu! Dar logica din fiecare opțiune e complexă, deci e mai clar cu if-else. Ambele funcționează — switch e mai elegant pentru selecții simple.

Ce se întâmplă dacă utilizatorul scrie litere în loc de numere?

cin intră în stare de eroare și nu mai citește nimic. Soluție avansată: cin.clear(); cin.ignore(1000,'\n'); după fiecare citire eșuată.

Cum știu dacă rezultatul simulării e corect?

Verifică cu valori calculate manual. Ex: x10=0, v1=10, x20=100, v2=5 → t = 100/(10-5) = 20s, x = 0+10×20 = 200m. Simularea trebuie să arate INTALNIRE la t=20.

abs() funcționează pentru double?

Cu #include <cmath>, da — abs() funcționează pentru double. Fără cmath, abs() din cstdlib e doar pentru int! Alternativă sigură: fabs() din cmath.

PROBLEME PBINFO - 15 minute

PbInfo - Pozitia dupa timp

x=x0+v*t

Enunț:

Cerință: Se citesc x0, v si t. Afiseaza pozitia mobilului.

Date de intrare:

x0 v t.

Date de ieșire:

Pozitia x.

Exemplu:

Intrare:

10 3 4

Ieșire:

22

Explicație: 10+3*4=22.

Cum gândim soluția:
  1. Citim datele.
  2. Aplicam x=x0+v*t.
  3. Afisam x.

Tip: Formula este directa, fara bucla.

Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int main() {
    double x0, v, t;
    cin >> x0 >> v >> t;
    cout << x0 + v * t;
}

PbInfo - Punctul de intalnire

Doua mobile

Enunț:

Cerință: Se citesc x1, v1, x2, v2. Afiseaza timpul intalnirii daca este pozitiv.

Date de intrare:

x1 v1 x2 v2.

Date de ieșire:

Timpul intalnirii sau mesaj.

Exemplu:

Intrare:

0 5 20 1

Ieșire:

5

Explicație: Cele doua mobile se intalnesc dupa 5 secunde.

Cum gândim soluția:
  1. Daca vitezele sunt egale, tratam separat.
  2. Calculam t=(x2-x1)/(v1-v2).
  3. Verificam t>=0.

Tip: Daca t este negativ, intalnirea a fost in trecut.

Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int main() {
    double x1, v1, x2, v2;
    cin >> x1 >> v1 >> x2 >> v2;
    if (v1 == v2)
        cout << "Nu se intalnesc";
    else {
        double t = (x2 - x1) / (v1 - v2);
        if (t >= 0)
            cout << t;
        else cout << "Timp negativ";
    }
}

PbInfo - Pozitia la intalnire

Timp si spatiu

Enunț:

Cerință: Se citesc doua miscari. Afiseaza timpul si pozitia intalnirii.

Date de intrare:

x1 v1 x2 v2.

Date de ieșire:

t si pozitia.

Exemplu:

Intrare:

0 5 20 1

Ieșire:

5 25

Explicație: La t=5, pozitia este 25.

Cum gândim soluția:
  1. Calculam t.
  2. Daca t>=0, calculam x=x1+v1*t.
  3. Afisam t si x.

Tip: Pozitia poate fi calculata cu oricare dintre cele doua mobile.

Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int main() {
    double x1, v1, x2, v2;
    cin >> x1 >> v1 >> x2 >> v2;
    if (v1 == v2) {
        cout << "Nu";
        return 0;
    }
    double t = (x2 - x1) / (v1 - v2);
    if (t < 0)
        cout << "Nu";
    else cout << t << " " << x1 + v1 * t;
}
EXERCIȚII PRACTICE - 2 sarcini / 20 minute

Exercițiul Practic: Implementare mișcare

Consolidează implementarea mișcării prin validare, simulare text și folosirea formulelor în programe complete. Poți păstra programele mici la început; meniul este doar o organizare mai mare.

Atenție la semnul vitezei: în fizică, o viteză negativă poate însemna mers în sens opus. În această sarcină de validare tratăm v ca „viteză ca mărime”, deci cerem v >= 0. Dacă vrei să permiți mersul înapoi, validezi doar timpul, nu și viteza.

Sarcina 1: Validare date de intrare

Adaugă validare: viteza trebuie să fie ≥ 0, iar timpul ≥ 0. Dacă nu, cere din nou cu do-while.

Pași de rezolvare
  1. Citește x0
  2. Citește v cu do-while: repetă dacă v < 0
  3. Citește t cu do-while: repetă dacă t < 0
  4. FOR i = 0..t: afișează x0 + v*i
do { citește v } while(v < 0) — repetare validare
do { cin >> v; } while(v < 0);
„repetă citirea cât timp valoarea e invalidă (negativă); fizic, viteza și timpul NU pot fi negative în MRU"
// Pseudocod: Validare date MRU CITEȘTE x0 REPETĂ CITEȘTE v DACĂ v < 0 ATUNCI SCRIE "Viteza negativa!" CÂT TIMP v < 0 REPETĂ CITEȘTE t CÂT TIMP t < 0 PENTRU i 0 LA t SCRIE "t=", i, " x=", x0 + v·i SFÂRȘIT PENTRU

De ce funcționează? Validarea cu do-while garantează intrare corectă — bucla se repetă cât timp condiția e falsă. Fizic, viteza și timpul nu pot fi negative în MRU.

#include <iostream>
using namespace std;

int main(){
    double x0, v;
    cout << "x0: "; cin >> x0;        // pozitia initiala (poate fi orice)
    do {
        cout << "v (>=0): "; cin >> v; // viteza trebuie >= 0
        if(v < 0) cout << "Viteza negativa! Reincearca." << endl;
    } while(v < 0);                     // repeta pana citim v valid
    int t;
    do {
        cout << "t (>=0): "; cin >> t; // timpul trebuie >= 0
    } while(t < 0);                     // do-while = se executa cel putin o data
    for(int i=0; i<=t; i++)
        cout << "t=" << i << " x=" << x0+v*i << endl; // formula MRU
    return 0;
}
Sarcina 2: Animație text

Afișează pe o linie de 50 caractere pozițiile celor 2 mobile cu 'A' și 'B'. La poziții egale afișează 'X'. Afișează la fiecare secundă.

Pași de rezolvare
  1. Definește constantele: x10=0, v1=3, x20=40, v2=1
  2. FOR t = 0..15: calculează p1, p2 (int)
  3. Creează o linie de 50 puncte, pune 'A' la p1, 'B' la p2
  4. Dacă p1 == p2: pune 'X' (coliziune)
  5. Afișează linia cu t= prefix
p = (int)(x₀ + v·t) — poziția convertită la index de array
int p1 = (int)(x10 + v1*t);
„convertim poziția reală (double) în index de coloană (int); dacă doi indici coincid → coliziune"
// Pseudocod: Animație text cu 2 mobile x100, v13, x2040, v21 PENTRU t 0 LA 15 p1 (int)(x10 + v1·t) p2 (int)(x20 + v2·t) linie "." × 50 // 50 puncte DACĂ p1 = p2 ATUNCI linie[p1] 'X' // coliziune ALTFEL linie[p1] 'A', linie[p2] 'B' SCRIE "t=", t, " |", linie, "|" SFÂRȘIT PENTRU

De ce funcționează? Convertim pozițiile reale (double) în indici de array (int). Fiecare rând de 50 caractere = o „fotografie" la momentul t. Dacă doi indici coincid → 'X' (coliziune).

#include <iostream>
using namespace std;

int main(){
    double x10=0, v1=3, x20=40, v2=1; // date initiale: 2 mobile
    for(int t=0; t<=15; t++){
        int p1 = (int)(x10 + v1*t);    // pozitia mobil A (coloana)
        int p2 = (int)(x20 + v2*t);    // pozitia mobil B (coloana)
        if(p1<0)p1=0; if(p1>49)p1=49; // limitam la 0..49
        if(p2<0)p2=0; if(p2>49)p2=49;
        char linie[51];
        for(int i=0;i<50;i++) linie[i]='.'; // umplem cu puncte
        linie[50]='\0';             // terminatorul de sir
        linie[p1]='A';             // punem mobilul A
        if(p1==p2) linie[p1]='X';  // intalnire: afisam X
        else linie[p2]='B';        // altfel: punem si mobilul B
        cout << "t=" << t << " |" << linie << "|" << endl;
    }
    return 0;
}

Descarcă toate exercițiile și soluțiile