Bevezetés a programozásba 11. Előadás: Esettanulmány
ISMÉTLÉS Függvényhívás #include #include <iostream> <iostream> #include #include <cmath> <cmath> using using namespace namespace std; std; double double terulet(double terulet(double a, a, double double b, b, double double c) c) double double s = (a+b+c)/2.0; (a+b+c)/2.0; return return sqrt((s-a)*(s-b)*(s-c)*s); sqrt((s-a)*(s-b)*(s-c)*s); int int main() main() double double ha,hb,hc; ha,hb,hc; cin cin >> >> ha ha >> >> hb hb >> >> hc; hc; double double t = terulet(ha,hb,hc); terulet(ha,hb,hc); cout cout "terulet: "terulet: " t endl; endl; return return 0; 0;
ISMÉTLÉS Függvények double double terulet(double terulet(double a, a, double double b, b, double double c) c) Szignatúra: Visszatérési típus (a függvény típusának is nevezik) Függvény neve Zárójelben Paraméter 1, ha van Paraméter 2, ha van.. A szignatúrából minden kiderül arról, hogyan kell használni a függvényt
ISMÉTLÉS Strukturált programozás Programtervezési elv: a feladatot osszuk részfeladatokra, és függvényekben csoportosítsuk azokat dekompozíció, redukció int nagyonnehézfeladat(p1 P2 P3..) egyikkicsitkönnyebb(p2 P4..); másikkicsitkönnyebb(p1 P2..);... Top-down vagy Bottom-up felépítés 80-as évekig nagy szoftvereknél egyeduralkodó
ISMÉTLÉS PLanG: STL vector C++ [semmi] VÁLTOZÓK : t:egész[10] t[0] := 1 [ilyet PLanG-ban nem lehet csinálni] #include <vector> vector<int> t(10); vagy vector<int> t(10,0); t[0]=1 int osszeg(vector<int> t) int sum=0; for (int i=0;i<t.size() ;i++) sum+=t[i]; return sum; osszeg(t)
ISMÉTLÉS Érték szerinti paraméterátadás #include #include <iostream> <iostream> using using namespace namespace std; std; Másolat készül void void fv(double fv(double a) a) a=0; a=0; int int main() main() double double d; d; d=1; d=1; fv(d); fv(d); cout cout "eredmeny: "eredmeny: " d endl; endl; return return 0; 0; Az eredmény: 1
Referencia szerinti paraméterátadás ISMÉTLÉS #include #include <iostream> <iostream> using using namespace namespace std; std; Másolat készül void void fv(double fv(double & a) a) a=0; a=0; int int main() main() double double d; d; d=1; d=1; fv(d); fv(d); cout cout "eredmeny: "eredmeny: " d endl; endl; return return 0; 0; Az eredmény: 0
ISMÉTLÉS struct #include <iostream> using using namespace std; std; struct koord koord double x,y; x,y; ; ; int int main() koord koord k; k; k.x=1.0; k.y=1.0; cout cout "[" "[" k.x k.x "," "," k.y k.y "]" "]" endl; endl; return 0; 0;
ISMÉTLÉS struct structban struct ember string nev; string lakcim; int szuletesi_ev; ; ; struct diak ember e; e; vector<int> jegyek; ; ;
ISMÉTLÉS struct és függvények struct struct pont pont double double x,y; x,y; string string nev; nev; ; ; void void kiir(pont p) p) cout cout "[" "[" p.x p.x "," "," p.y p.y "," "," p.nev p.nev "]" "]" endl; endl; int int main() main() pont pont p; p;...... kiir(p); kiir(p); return return 0; 0;
ISMÉTLÉS Operátorok struct struct pont pont double double x,y; x,y; ; ; bool bool operator==(pont a, a, pont pont b) b) return return a.x==b.x a.x==b.x && && a.y a.y == == b.y; b.y; int int main() main() pont pont a=1.0,1.0, b=0.0,0.0; cout cout (a==b); (a==b); return return 0; 0;
ISMÉTLÉS Operátorok Megvalósítható operátorok: @a alakú: + - * &! ~ ++ -- operator@(a).. a@ alakú: ++ -- operator@(a, int).. a@b alakú : + - * / % ^ & < > ==!= <= >= >> &&, operator@(a,b).. Az operátorok szerepét illik a nevükhöz és a szokásos jelentésükhöz igazodva használni. Alaptípusokra nem bírálhatjuk felül az operátort
ISMÉTLÉS Tervezési kérdések struct struct pont pont double double x,y; x,y; ; ; double double tav(pont tav(pont a, a, pont pont b) b) return return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); pont pont legtavolabbi(pont legtavolabbi(pont a, a, vector<pont> vector<pont> v) v) pont pont b=v[0]; b=v[0]; double double max=tav(a,b); max=tav(a,b); for for (int (int i=1;i<v.size();i++) i=1;i<v.size();i++) if if (tav(a,v[i])>max) (tav(a,v[i])>max) b=v[i]; b=v[i]; max=tav(a,b); max=tav(a,b); return return b; b;
ISMÉTLÉS Tervezési kérdések struct struct pont pont double double x,y,z; x,y,z; ; ; double double tav(pont tav(pont a, a, pont pont b) b) return return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+ sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+ (a.z-b.z)*(a.z-b.z)); (a.z-b.z)*(a.z-b.z)); pont pont legtavolabbi(pont legtavolabbi(pont a, a, vector<pont> vector<pont> v) v) pont pont b=v[0]; b=v[0]; double double max=tav(a,b); max=tav(a,b); for for (int (int i=1;i<v.size();i++) i=1;i<v.size();i++) if if (tav(a,v[i])>max) (tav(a,v[i])>max) b=v[i]; b=v[i]; max=tav(a,b); max=tav(a,b); return return b; b;
ISMÉTLÉS Tagfüggvény struct struct koord koord double double x,y; x,y; void void olvas(istream &be) &be) be be >> >> x >> >> y; y; ; ; int int main() main() koord koord a; a; a.olvas(cin); cout cout a.x a.x "," "," a.y a.y endl; endl; return return 0; 0;
Gyakorlatban Nézzünk meg egy példát Feladat: szöveges labirintusos játék A játékban helyszínek vannak, amikről a felhasználó rövid leírást kap Minden helyszín összeköttetésben állhat más helyszínekkel, amerre tovább lehet menni A felhasználó minden helyszínen megadhatja, hogy merre megy tovább Ha megérkezik a célba, nyer
Ahogy azt régen csináltuk volna #include <iostream> #include <iostream> using namespace std; using namespace std; int main() int main() int h=1; int h=1; while (h!=4) while (h!=4) if (h==1) if (h==1) cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; if (h==2) if (h==2) cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; if (h==3) if (h==3) cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cin >> h; cin >> h; cout "Megérkeztél a suliba, éljen." endl; cout "Megérkeztél a suliba, éljen." endl;
Ahogy azt régen csináltuk volna #include <iostream> #include <iostream> using namespace std; using namespace std; Gyanúsan repetitív kód int main() int main() int h=1; int h=1; while (h!=4) while (h!=4) if (h==1) if (h==1) cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; if (h==2) if (h==2) cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; if (h==3) if (h==3) cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cin >> h; cin >> h; cout "Megérkeztél a suliba, éljen." endl; cout "Megérkeztél a suliba, éljen." endl; Lehet csalni
1.1 #include <iostream> #include <iostream> using namespace std; using namespace std; int main() int main() int h=1; int h=1; while (h!=4) while (h!=4) if (h==1) if (h==1) cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; if (h==2) if (h==2) cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; if (h==3) if (h==3) cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; int hova; int hova; cin >> hova; cin >> hova; if (h==1 && (hova==2 hova==3) if (h==1 && (hova==2 hova==3) h==2 && (hova==1 hova==4) h==2 && (hova==1 hova==4) h==3 && (hova==1 hova==4)) h==3 && (hova==1 hova==4)) h=hova; h=hova; else else cout "Arra nem lehet menni innen." endl; cout "Arra nem lehet menni innen." endl; cout "Megérkeztél a suliba, éljen." endl; cout "Megérkeztél a suliba, éljen." endl;
1.1 #include <iostream> #include <iostream> using namespace std; using namespace std; Ez még mindig int main() int main() int h=1; repetitív int h=1; while (h!=4) while (h!=4) if (h==1) if (h==1) cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; cout "Otthon vagy. Mehetsz a parkba, vagy a bolthoz." endl; if (h==2) if (h==2) cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; cout "A parkban vagy. Mehetsz a suliba, vagy haza." endl; if (h==3) if (h==3) cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "A boltnál vagy. Mehetsz a suliba, vagy haza." endl; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; cout "Hova mész? (1:haza, 2:park, 3:bolt, 4:suli) : "; int hova; int hova; cin >> hova; cin >> hova; if (h==1 && (hova==2 hova==3) if (h==1 && (hova==2 hova==3) Nehéz változtatni h==2 && (hova==1 hova==4) h==2 && (hova==1 hova==4) h==3 && (hova==1 hova==4)) a térképet, ez túl h==3 && (hova==1 hova==4)) h=hova; bonyolult h=hova; else else cout "Arra nem lehet menni innen." endl; cout "Arra nem lehet menni innen." endl; cout "Megérkeztél a suliba, éljen." endl; cout "Megérkeztél a suliba, éljen." endl;
1.2 #include <iostream> #include <iostream> #include <vector> #include <vector> using namespace std; using namespace std; int main() int main() vector<string> terkep(4); vector<string> terkep(4); terkep[0]="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[0]="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[1]="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[1]="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[2]="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[2]="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[3]="megérkeztél a suliba, éljen."; terkep[3]="megérkeztél a suliba, éljen."; int h=0; int h=0; cout terkep[h] endl; cout terkep[h] endl; while (h!=3) while (h!=3) cout "Hova mész? (0:haza, 1:park, 2:bolt, 3:suli) : "; cout "Hova mész? (0:haza, 1:park, 2:bolt, 3:suli) : "; int hova; int hova; cin >> hova; cin >> hova; if ( if ( h==0 && (hova==1 hova==2) h==0 && (hova==1 hova==2) h==1 && (hova==0 hova==3) h==1 && (hova==0 hova==3) h==2 && (hova==0 hova==3) h==2 && (hova==0 hova==3) ) ) h=hova; h=hova; else else cout "Arra nem lehet menni innen." endl; cout "Arra nem lehet menni innen." endl; cout terkep[h] endl; cout terkep[h] endl;
#include <iostream> #include <iostream> #include <vector> #include <vector> using namespace std; using namespace std; 1.2 int main() int main() vector<string> terkep(4); vector<string> terkep(4); terkep[0]="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[0]="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[1]="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[1]="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[2]="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[2]="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[3]="megérkeztél a suliba, éljen."; terkep[3]="megérkeztél a suliba, éljen."; int h=0; int h=0; cout terkep[h] endl; cout terkep[h] endl; while (h!=3) while (h!=3) cout "Hova mész? (0:haza, 1:park, 2:bolt, 3:suli) : "; cout "Hova mész? (0:haza, 1:park, 2:bolt, 3:suli) : "; int hova; int hova; cin >> hova; cin >> hova; if ( if ( h==0 && (hova==1 hova==2) h==0 && (hova==1 hova==2) h==1 && (hova==0 hova==3) h==1 && (hova==0 hova==3) h==2 && (hova==0 hova==3) h==2 && (hova==0 hova==3) ) ) h=hova; h=hova; else else cout "Arra nem lehet menni innen." endl; cout "Arra nem lehet menni innen." endl; cout terkep[h] endl; cout terkep[h] endl; Ez még mindig túl merev szerkezet
Bedrótozott adat Azt nevezzük bedrótozott -nak, ami a programkódban fixen le van írva, pedig jobb lenne, ha nem így lenne Adott esetben egy olyan program, ami a térképet fájlból olvasná be Általában cél, hogy a végleges programban már ne legyen olyan bedrótozott adat, ami a feladatban megváltozhat Ez viszont sokszor nem túl egyszerű, kicsit gondolkodni kell hozzá
Jön a struct Azt láttuk, hogy ha szeretnénk kiemelni a bedrótozott adatot, akkor kezelni kell a következőket tájékoztató szöveg kiírása az egyes helyszíneken az összeköttetések a helyszínek között esetleg a helyszínek neve Ezek közül az összeköttetések kezelése a legnehezebb
std::vector Azon túl, hogy a primitív tömbnél jobb paraméterátadásnál kezdeti értékben méretnek változót is kaphat, nem csak konstanst Néhány további hasznos szolgáltatás push_back(elem) : a tömb végére új elemet tehetünk resize(újméret) : átméretezhető bármikor
A helyszín reprezentációja struct hely hely string nev; nev; string leiras; vector<int> hova; ; ; A név és a leírás szöveges változóval megoldható Az összeköttetéseket tömbben reprezentáljuk, aminek az elemei az innen elérhető helyszínek kódjai
2.0 #include <iostream> #include <iostream> #include <vector> #include <vector> using namespace std; using namespace std; struct hely struct hely string nev; string nev; string leiras; string leiras; vector<int> hova; vector<int> hova; ; ; int main() int main() vector<hely> terkep(4); vector<hely> terkep(4); terkep[0].nev="otthon"; terkep[0].nev="otthon"; terkep[0].leiras="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[0].leiras="otthon vagy. Mehetsz a parkba, vagy a bolthoz."; terkep[0].hova.push_back(1); terkep[0].hova.push_back(1); terkep[0].hova.push_back(2); terkep[0].hova.push_back(2); terkep[1].nev="park"; terkep[1].nev="park"; terkep[1].leiras="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[1].leiras="a parkban vagy. Mehetsz a suliba, vagy haza."; terkep[1].hova.push_back(0); terkep[1].hova.push_back(0); terkep[1].hova.push_back(3); terkep[1].hova.push_back(3); terkep[2].nev="bolt"; terkep[2].nev="bolt"; terkep[2].leiras="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[2].leiras="a boltnál vagy. Mehetsz a suliba, vagy haza."; terkep[2].hova.push_back(0); terkep[2].hova.push_back(0); terkep[2].hova.push_back(3); terkep[2].hova.push_back(3); terkep[3].nev="suli"; terkep[3].nev="suli"; terkep[3].leiras="megérkeztél a suliba, éljen."; terkep[3].leiras="megérkeztél a suliba, éljen.";
2.0 terkep[3].nev="suli"; terkep[3].nev="suli"; terkep[3].leiras="megérkeztél a suliba, éljen."; terkep[3].leiras="megérkeztél a suliba, éljen."; int h=0; int h=0; cout terkep[h].leiras endl; cout terkep[h].leiras endl; while (h!=3) while (h!=3) cout "Hova mész?" endl; cout "Hova mész?" endl; for (int i=0;i<terkep[h].hova.size();i++) for (int i=0;i<terkep[h].hova.size();i++) cout i+1 ":" terkep[terkep[h].hova[i]].nev endl; cout i+1 ":" terkep[terkep[h].hova[i]].nev endl; int melyik; int melyik; cin >> melyik; cin >> melyik; if (melyik > 0 && melyik <= terkep[h].hova.size()) if (melyik > 0 && melyik <= terkep[h].hova.size()) h=terkep[h].hova[melyik-1]; h=terkep[h].hova[melyik-1]; else else cout "Hibás válasz." endl; cout "Hibás válasz." endl; cout terkep[h].leiras endl; cout terkep[h].leiras endl;
2.0 terkep[3].nev="suli"; terkep[3].nev="suli"; terkep[3].leiras="megérkeztél a suliba, éljen."; terkep[3].leiras="megérkeztél a suliba, éljen."; int h=0; int h=0; cout terkep[h].leiras endl; cout terkep[h].leiras endl; while (h!=3) while (h!=3) cout "Hova mész?" endl; cout "Hova mész?" endl; for (int i=0;i<terkep[h].hova.size();i++) for (int i=0;i<terkep[h].hova.size();i++) cout i+1 ":" terkep[terkep[h].hova[i]].nev endl; cout i+1 ":" terkep[terkep[h].hova[i]].nev endl; int melyik; int melyik; menü cin >> melyik; cin >> melyik; if (melyik > 0 && melyik <= terkep[h].hova.size()) if (melyik > 0 && melyik <= terkep[h].hova.size()) h=terkep[h].hova[melyik-1]; h=terkep[h].hova[melyik-1]; else else cout "Hibás válasz." endl; cout "Hibás válasz." endl; cout terkep[h].leiras endl; cout terkep[h].leiras endl;
2.0 értékelés Sikeresen szeparáltuk a konkrét adatokat az általános működéstől Felkészültünk arra, hogy fájlból töltsük be a konkrét adatokat Ezt azzal értük el, hogy azonosítható helyszíneket használtunk a helyszínek tulajdonságainak összetartozását is kifejeztük Így végül a főprogram lényegi része független lett az aktuális térképtől
2.1 adatok.txt otthon otthon Otthon Otthon vagy. vagy. Mehetsz Mehetsz a parkba, parkba, vagy vagy a bolthoz. bolthoz. 2 1 2 park park A parkban parkban vagy. vagy. Mehetsz program Mehetsz a suliba, suliba, vagy vagy haza. haza. 2 0 3 bolt bolt void void betolt(ifstream betolt(ifstream &be, &be, hely hely & mit) mit) A boltnál boltnál vagy. vagy. Mehetsz Mehetsz be be >> a >> suliba, ws; suliba, ws; vagy vagy haza. haza. 2 0 3 getline(be, getline(be, mit.nev); mit.nev); suli suli getline(be, getline(be, mit.leiras); mit.leiras); Megérkeztél Megérkeztél a suliba, suliba, int int éljen. éljen. lsz,h; lsz,h; 0 be be >> >> lsz; lsz; for for (int (int i=0;i<lsz;i++) i=0;i<lsz;i++) be be >> >> h; h; mit.hova.push_back(h); mit.hova.push_back(h);
2.1 adatok.txt otthon otthon Otthon Otthon vagy. vagy. Mehetsz Mehetsz a parkba, parkba, vagy vagy a bolthoz. bolthoz. 2 1 2 park park A parkban parkban vagy. vagy. Mehetsz program Mehetsz a suliba, suliba, vagy vagy haza. haza. 2 0 3 bolt bolt Ha esetleg void void betolt(ifstream betolt(ifstream &be, &be, hely hely & mit) mit) A boltnál még boltnál vagy. az előző vagy. Mehetsz Mehetsz be be >> a >> suliba, ws; suliba, ws; vagy vagy haza. haza. 2 0 3 sor végén getline(be, getline(be, mit.nev); állunk mit.nev); suli suli getline(be, getline(be, mit.leiras); mit.leiras); Megérkeztél Megérkeztél a suliba, suliba, int int éljen. éljen. lsz,h; lsz,h; 0 be be >> >> lsz; lsz; for for (int (int i=0;i<lsz;i++) i=0;i<lsz;i++) be be >> >> h; h; mit.hova.push_back(h); mit.hova.push_back(h);
2.1 int int main() main() ifstream ifstream f("adatok.txt"); f("adatok.txt"); int int hsz, hsz, cel; cel; f f >> >> hsz hsz >> >> cel; cel; vector<hely> vector<hely> terkep(hsz); terkep(hsz); for for (int (int i=0;i<hsz;i++) i=0;i<hsz;i++) betolt(f,terkep[i]); betolt(f,terkep[i]); int int h=0; h=0; cout cout terkep[h].leiras terkep[h].leiras endl; endl; while while (h!=cel) (h!=cel) cout cout "Hova "Hova mész?" mész?" endl; endl; for for (int (int i=0;i<terkep[h].hova.size();i++) i=0;i<terkep[h].hova.size();i++) cout cout i+1 i+1 ":" ":" terkep[terkep[h].hova[i]].nev terkep[terkep[h].hova[i]].nev endl; endl; int int melyik; melyik; cin cin >> >> melyik; melyik; if if (melyik (melyik > > 0 0 && && melyik melyik <= <= terkep[h].hova.size()) terkep[h].hova.size()) h=terkep[h].hova[melyik-1]; h=terkep[h].hova[melyik-1]; else else cout cout "Hibás "Hibás válasz." válasz." endl; endl; cout cout terkep[h].leiras terkep[h].leiras endl; endl;
További lehetőségek A Térkép fogalmának bevezetése fájlnévből teljes térkép betöltés összeköttetések kezelése Néhány lehetséges változás a feladatban tárgyak kezelése, pl. csak akkor lehet egy összeköttetést használni, ha van nálunk kulcs Tárgy és Összeköttetés típusok bevezetésével, a főprogram ciklusának érintése nélkül megoldható grafikus megjelenítés A Hely mezőinek kibővítésével megoldható egyes helyszínek eltérő képe
Áttekintés Egy átlagos játékprogramon kevés programozó dolgozik, és nagyon sok designer Nem lehet bedrótozni semmit Szét kell választani a konkrét adatokat az általános működéstől Az általános működés megfogalmazásához jó, ha magasabb szintű fogalmakat használhatunk Megoldástér Problématér Ebben segít a struct és a függvények......vagyis a saját típusaink, és azok műveletei