Οντοκεντρικός Προγραμματισμός ΙΙ (C++) Κληρονομικότητα - Πολυμορφισμός Αςκιςεισ Φροντιςτθρίου (19/11/2012) Επικουρικό Ζργο: Κωνςταντίνοσ Κόβασ E-mail: kobas@ceid.upatras.gr
Στο προθγοφμενο Φροντιςτιριο Δθμιουργία Κλάςθσ Διαχωριςμόσ Δθλϊςεων - Υλοποίθςθσ Δθμιουργία αντικειμζνων με δυναμικι ανάκεςθ μνιμθσ (new, delete) Διλωςθ Παραγόμενθσ Κλάςθσ Method Overloading Method Overriding Operator overloading
Στο προθγοφμενο Φροντιςτιριο Hero o print() Warrior Method Overloading o attack(hero&, int) o attack(warrior&, int) Mage o castspell(hero&, int) BloodMage Method Overriding o castspell(hero&, int)
Τροποποιιςεισ Χριςθ αναφοράσ για το πζραςμα αντικειμζνων ϊσ παραμζτρουσ μεκόδων ΠΧ: μζκοδοσ castspell: void Mage::castSpell( Hero& X, int Damage){ if (Mana>Damage){ Mana-=Damage; X-Damage; cout <<getname() <<" deals "<< Damage << " damage to "<< X.getName() <<endl; else cout <<getname() <<" has not enough mana "<<endl; Για να τθν καλζςουμε ςτθν main: Warrior* warrior1= new Warrior("Warrior1",0,100,4); Mage* mage1= new Mage ("Mage1",0,80,100); mage1->castspell(*warrior1,40);
Άςκθςθ 1 Προςκζςτε ςτα αρχεία τθσ κλάςθσ Hero, μια ςυνάρτθςθ με όνομα levelup. Η διλωςθ τθσ να γίνει εκτοσ τθσ διλωςθσ τθσ κλάςθσ Hero (δεν κα είναι μζκοδοσ μζλοσ) Η ςυνάρτθςθ κα παίρνει ςαν όριςμα ζνα αντικείμενο Hero (με αναφορά) και κα αυξάνει τθν τιμι Level κατα 1. Επίςθσ κα κζτει τιμι ςτθν Life : 100*Level. Κάντε τισ απαραίτθτεσ δθλϊςεισ ωςτε να ζχει άμεςα πρόςβαςθ ςτισ private μεταβλθτζσ Life και Level του αντικειμζνου που δζχκθκε ςαν παράμετρο. Δοκιμάςτε τθν ςυνάρτθςθ ςτθν main ωςτε να ελζγξετε τθν λειτουργία τθσ.
Άςκθςθ 1 Hero.h #ifndef HERO_H #define HERO_H class Hero{ void friend levelup (Hero& ); public:... ; private:... void levelup (Hero& ); #endif
Άςκθςθ 1 Hero.cpp void levelup (Hero& X){ X.Level++; X.Life=100*X.Level; cout<<x.name<< " has gained a level!"<<endl; Δεν δθλϊνουμε scope μπροςτά απο το όνομα τθσ ςυνάρτθςθσ! Hero::levelUp *Δεν είναι μζλοσ τθσ Hero] Χριςθ του τελεςτι ++ που ορίςαμε ςτο προθγοφμενο φροντιςτιριο. Ζχουμε απευκείασ πρόςβαςθ ςτισ private μεταβλθτζσ τθσ Hero: Level και Life λόγω τθσ διλωςθσ ωσ friend Αν είχαμε ορίςει τθν ςυνάρτθςθ ωσ friend τθσ παραγόμενθσ κλάςθσ Warrior κα είχαμε πάλι απευκείασ πρόςβαςθ ςτισ Life και Level ; ΟΧΙ: Η friend ςυνάρτηςη δεν ζχει πρόςβαςη ςε Private μζλη τησ κλάςησ βάςησ.
Άςκθςθ 2 Δθμιουργιςτε μια κλάςθ με όνομα Weapon και μεταβλθτζσ Name, MinDamage, MaxDamage, TH (boolean) Δθμιουργιςτε μια μζκοδο getdamagevalue θ οποία κα επιςτρζφει με τυχαίο τρόπο ζναν αρικμό μεταξφ MinDamage και MaxDamage Προςκζςτε ςτθν κλάςθ Warrior δυο μεταβλθτζσ (Left και Right) τφπου δείκτθ ςε αντικείμενα Weapon που αναπαριςτοφν τα χζρια του πολεμιςτι. Προςκζςτε ςτθν κλάςθ Warrior μια μζκοδο equip θ οποία κα παίρνει ϊσ παράμετρο με αναφορά ζνα αντικείμενο Weapon και κα το ανακζτει ςτα χζρια του πολεμιςτι. Συγκεκριμζνα αν το όπλο είναι OneHanded (TH==false) κα το ανακζτει ςε ζνα απο τα δφο χζρια του πολεμιςτι εφόςον είναι άδειο. Αν το όπλο είναι TwoHanded (TH==true) και τα χζρια είναι άδεια, κα το ανακζτει και ςτα δυο χζρια.
Άςκθςθ 2 Δθμιουργιςτε μια κλάςθ με όνομα Weapon και μεταβλθτζσ Name, MinDamage, MaxDamage, TH (boolean) o Δθμιουργιςτε μια μζκοδο getdamagevalue θ οποία κα επιςτρζφει με τυχαίο τρόπο ζναν αρικμό μεταξφ MinDamage και MaxDamage Weapon.h class Weapon{ public: Weapon (char* ="noname",int =5,int =5,bool =false); int getdamagevalue() const; bool getth() const; char* getname() const; private: char* Name; int MinDamage; int MaxDamage; bool TwoHanded; ;
Άςκθςθ 2 Δθμιουργιςτε μια κλάςθ με όνομα Weapon και μεταβλθτζσ Name, MinDamage, MaxDamage, TH (boolean) o Δθμιουργιςτε μια μζκοδο getdamagevalue θ οποία κα επιςτρζφει με τυχαίο τρόπο ζναν αρικμό μεταξφ MinDamage και MaxDamage Weapon::Weapon(char* N, int Min,int Max,bool H) :Name(N),MinDamage(Min),MaxDamage(Max),TwoHanded(H) { int Weapon::getDamageValue() const{ srand( time( 0 ) ); return( MinDamage + rand()%(maxdamage-mindamage) ); char* Weapon::getName() const { return Name; bool Weapon::getTH()const { return TwoHanded; Weapon.cpp
Άςκθςθ 2 Προςκζςτε ςτθν κλάςθ Warrior δυο μεταβλθτζσ (Left και Right) τφπου δείκτθ ςε αντικείμενα Weapon που αναπαριςτοφν τα χζρια του πολεμιςτι. Προςκζςτε ςτθν κλάςθ Warrior μια μζκοδο equip θ οποία κα παίρνει ϊσ παράμετρο με αναφορά ζνα αντικείμενο Weapon και κα το ανακζτει ςτα χζρια του πολεμιςτι. class Warrior : public Hero { public: Warrior (char* ="Unknown", int =1, int =120, int=2); void attack( Hero&,int ); void attack( Warrior&,int ); int equip( Weapon&); int getarmor() const ; void setarmor ( int ); Warrior.h Weapon *Right; Weapon *Left; private: int Armor; ;
Άςκθςθ 2 Warrior::Warrior(char* N, int LVL, int L, int A) :Hero(N,LVL,L),Armor(A) { Left=0; Right=0; Warrior.cpp int Warrior::equip( Weapon& W){ if (W.getTH()==true && Left==0 && Right==0){ Left=&W; Right=&W; cout <<getname() <<" equips "<< Left->getName()<<endl; return 1; if (W.getTH()==false && Left==0){ Left=&W; cout <<getname() <<" equips "<< Left->getName()<<endl; return 1 ; if (W.getTH()==false && Right==0){ Right=&W; cout <<getname() <<" equips "<< Right->getName()<<endl; return 1; return 0;
Άςκθςθ 2 main.cpp Warrior* warrior1= new Warrior("Warrior2",1,40,2); Warrior* warrior2= new Warrior("Warrior1",1,100,4); Weapon* w1=new Weapon("G3A3",30,45,true); Weapon* w2=new Weapon("ToSfyri",12,15,false); Weapon* w3=new Weapon("Screwdriver",8,15,false); warrior2->equip(*w1); // equip TwoHanded Weapon warrior2->equip(*w2); // equip Weapon - FAILS warrior1->equip(*w2); // equip OneHanded Weapon warrior1->equip(*w3); // equip Second OneHanded Weapon
Άςκθςθ 3 Προςκζςτε ςυνάρτθςθ attack ςτθν Hero που κα (αντικείμενο Ήρωα) και κα προκαλεί ηθμιά: 5*Level παίρνει μια παράμετρο Μετανομάςτε τισ ςυνάρτθςεισ castspell ςε attack και τροποποιιςτε τισ ωςτε να παίρνουν μία παράμετρο (Ήρωα). Η τιμι Damage κα υπολογίηεται ωσ εξισ: Για τθν κλάςθ Mage: 40*Level Για τθν κλάςθ Bloodmage: 20*Level Τροποποιείςτε τισ attack τθσ κλάςθσ Warrior ωςτε να παίρνουν μόνο μια παράμετρο (το αντικείμενο Ήρωα ι Πολεμιςτι). Η τιμι Damage κα υπολογίηεται ωσ εξισ Αν δεν κρατάει όπλο : 5*Level Αν κρατάει 1 TwoHanded ι 1 OneHanded: τιμι τθσ getdamagevalue Αν κρατάει 2 OneHanded : Συνδιαςμόσ των τιμϊν getdamagevalue των δυο όπλων (Left+Right/2) Τζλοσ τροποποιιςτε όλεσ τισ attack ωςτε να εμφανίηουν μινυμα ςτο οποίο να αναφζρεται ςτθν αρχι ποιασ κλάςθσ θ μζκοδοσ κλικθκε: ΠΧ ςτθν attack του Hero να εμφανίηεται μφνθμα Hero Attack ενϊ ςτθν attack του Mage να εμφανίηεται μινυμα Mage Attack Στθν main δοκιμάςτε τισ επικζςεισ attack ωςτε να ελζγξετε ποια καλείται κάκε φορά.
Άςκθςθ 3 Hero o attack(hero&) Warrior o attack(hero&) o attack(warrior&) Mage o attack(hero&) BloodMage o attack(hero&)
Άςκθςθ 3 void Hero::attack( Hero& X){ int Damage=5*Level; X-Damage; cout <<"HERO ATTACK: "<<getname() <<" deals "<< Damage << " damage to hero "<< X.getName() <<endl; Sleep(1000); hero.cpp
void Warrior::attack( Hero& X){ int Damage=0; if ( Right==0 && Left==0){ Damage+= getlevel() * 5; else { if ( Right==0) Damage += Left->getDamageValue(); else if ( Left==0) Damage += Right->getDamageValue(); else if (Left->getTH()) Damage += Left->getDamageValue(); else Damage += (Left->getDamageValue() + Right->getDamageValue()/2 ); X-Damage; cout <<"WARRIOR ATTACK: "<<getname() <<" deals "<< Damage << " damage to hero "<< X.getName() <<endl; Sleep(1000); warrior.cpp void Warrior::attack( Warrior& X){... X- (Damage/Armor); cout <<"WARRIOR ATTACK: "<<getname() <<" deals "<< Damage/Armor << " damage to warrior "<< X.getName() <<endl;
mage.cpp void Mage::attack( Hero& X){ int Damage=40*getLevel(); if (Mana>Damage){ Mana-=Damage; X-Damage; cout <<"MAGE ATTACK: "<<getname() <<" deals "<< Damage<< " damage to << X.getName() <<endl; Sleep(1000); else cout <<"MAGE ATTACK: "<<getname() <<" has not enough mana "<<endl; Sleep(1000); void Bloodmage::attack( Hero &X){ int Damage=20*getLevel(); if (getmana()>damage){ int newmana=getmana()-damage; setmana(newmana); else{ int Rest= Damage-getMana(); setmana(0); setlife( getlife() - Rest ); X-Damage; cout <<"BLOODMAGE ATTACK: "<<getname() <<" deals "<< Damage << " damage to "<< X.getName() <<endl; Sleep(1000); bloodmage.cpp
Άςκθςθ 3 hero1->attack(*warrior1); warrior2->attack(*bloodmage1); bloodmage1->attack(*hero1); Mage* bloodmage1d_mage=bloodmage1; bloodmage1d_mage->attack(*warrior2); warrior1->attack(*warrior2);
Άςκθςθ 4 Δθμιουργείςτε μια ςυνάρτθςθ duel ςτα αρχεία τθσ κλάςθσ Hero αλλα εκτόσ τθσ διλωςθσ τθσ κλάςθσ. Η ςυνάρτθςθ κα παίρνει ϊσ παραμζτρουσ δυο αντικείμενα Hero με αναφορά. Στο ςϊμα τθσ κα επιτίκεται διαδοχικά ο ζνασ ιρωασ ςτον άλλο. Στθν main δοκιμάςτε τθν duel με διάφορα ορίςματα. Καλοφνται οι μεκόδοι Attack που κα περιμζνατε; Αν όχι υπάρχει τρόποσ να διορκϊςουμε το πρόβλθμα;
Άςκθςθ 4 #ifndef HERO_H #define HERO_H class Hero{ hero.h hero.cpp public:... private:... void duel(hero& A,Hero& B){ A.attack(B); B.attack(A); ; void duel(hero&,hero& ); #endif
duel(*mage1,*warrior1); duel(*hero1,*bloodmage1); duel(*warrior2,*warrior1); class Hero{ public:... void virtual attack( Hero&);... private:... ; Δεν καλείται θ attack(warrior&) αλλα θ attack(hero&)
Άςκθςθ 4 Hero o attack(&hero) Warrior o attack(&hero) o attack(&warrior) Mage o attack(&hero) BloodMage o attack(&hero) Η χριςθ τθσ virtual για τθν attack(&hero) μασ διαςφαλίηει οτι θ κλιςθ τθσ κα γίνει με βάςθ το είδοσ αντικειμζνου που τθν καλλεί ανεξαρτιτωσ το είδοσ τθσ μεταβλθτισ ι δείκτθ ςτο οποίο τθν ζχουμε περάςει. Η ςυνάρτθςθ attack(&warrior) τθσ κλάςθσ Warrior εξαρτάται απο τον τφπο τθσ μεταβλθτισ που παίρνει ωσ παράμετρο (πρζπει να είναι τφπου Warrior).
Άςκθςθ 5 Στθν main ςυνάρτθςθ δθμιουργιςτε ζναν πίνακα με δείκτεσ ςε αντίκεινα Hero. Ανακζςτε ςτα πεδία του πίνακα αντικείμενα διαφόρων ειδϊν θρϊων που ζχετε προθγουμζνωσ δθμιουργιςει. Δθμιουργιςτε μια δομι for ωςτε να επιτεκεί ο κάκε ιρωασ του πίνακα ςε όλουσ τουσ υπόλοιπουσ. Δοκιμάςτε τθν εκτζλεςθ δυο φορζσ Τθν πρϊτθ χωρίσ να ζχετε ορίςει τθν attack μζκοδο τθσ Hero ωσ virtual Τθν δεφτερθ αφοφ τθν ζχετε ορίςει virtual Παρατθρείτε κάποιο πρόβλθμα ςτθν κλιςθ τθσ attack τθσ Warrior;
Άςκθςθ 5 Hero* HerosArray[10]; int HerosArray_num=0; main.cpp HerosArray[HerosArray_num++] = hero1; HerosArray[HerosArray_num++] = warrior1; HerosArray[HerosArray_num++] = warrior2; HerosArray[HerosArray_num++] = mage1; HerosArray[HerosArray_num++] = bloodmage1; for(int i=0;i<herosarray_num;i++) for(int j=0;j<herosarray_num;j++) if (i!=j) HerosArray[i]->attack(*HerosArray[j]);
void attack( Hero&); void virtual attack( Hero&);
Δεν καλείται θ attack(warrior&) αλλα θ attack(hero&)
Άςκθςθ 6 Στθν ςυνάρτθςθ duel, βρείτε τρόπο ωςτε να καλείται όποτε πρζπει θ ςυνάρτθςθ attack(warrior&) τθσ κλάςθσ Warrior αντί τθσ attack(hero&). Εφαρμϊςτε τον τρόπο που βρικατε ςτθν υλοποίθςθ τθσ attack(hero&) τθσ Warrior ωςτε να καλεί θ ίδια τθν attack(warrior&) όταν πρζπει. Στθν main, ελζγξτε τον πίνακα θρϊων ωςτε να διαπιςτϊςετε οτι αξιοποιεί τισ αλλαγζσ που κάνατε.
Άςκθςθ 6 Στθν ςυνάρτθςθ duel, βρείτε τρόπο ωςτε να καλείται όποτε πρζπει θ ςυνάρτθςθ attack(warrior&) τθσ κλάςθσ Warrior αντί τθσ attack(hero&). o Με χρήςη τησ static_cast void duel(hero& A,Hero& B){ hero.cpp char* n1=a.getname(); char* n2=b.getname(); n1[0]=='w' && n2[0]=='w' if ( ){ Warrior *w1= static_cast<warrior*>(&a); Warrior *w2= static_cast<warrior*>(&b); w1->attack(*w2); w2->attack(*w1); else{ A.attack(B); B.attack(A); H static_cast δεν κάνει ζλεγχο οπότε πρζπει να διαςφαλίςουμε πρϊτα οτι μπορεί να γίνει θ μετατροπι, δθλαδι οτι το αντικείμενο είναι όντωσ τφπου Warrior. Εδϊ κάνουμε παραδοχι οτι τα ονόματα των Warrior ξεκινάνε απο W και χρθςιμοποιοφμε τθν πλθροφορία για να ελζγξουμε αν μπορεί να γίνει μετατροπι.
Άςκθςθ 6 Στθν ςυνάρτθςθ duel, βρείτε τρόπο ωςτε να καλείται όποτε πρζπει θ ςυνάρτθςθ attack(warrior&) τθσ κλάςθσ Warrior αντί τθσ attack(hero&). o Με χρήςη τησ dynamic_cast void duel(hero& A,Hero& B){ hero.cpp Warrior *w1= dynamic_cast<warrior*>(&a); Warrior *w2= dynamic_cast<warrior*>(&b); if (w1!=0 &&w2!=0){ w1->attack(*w2); w2->attack(*w1); else{ A.attack(B); B.attack(A); Η dynamic_cast επιςτρζφει 0(null) αν δεν γίνεται θ μετατροπι, δθλαδι αν δεν είναι τφπου Warrior.
Άςκθςθ 6 Εφαρμϊςτε τον τρόπο που βρικατε ςτθν υλοποίθςθ τθσ attack(hero&) τθσ Warrior ωςτε να καλεί θ ίδια τθν attack(warrior&) όταν πρζπει. void Warrior::attack( Hero& X){ Warrior *w1= dynamic_cast<warrior*>(&x); if(w1==0){ warrior.cpp... else attack(*w1);
Άςκθςθ 7 Προςκζςτε ςτθ κλάςθ Hero, δυο μεταβλθτζσ Χ,Υ που αναπαριςτοφν τισ ςυντεταγμζνεσ του ιρωα ςτον χάρτθ. Προςκζςτε ςυνάρτθςθ setxy που κζτει τιμζσ ςτισ παραπάνω μεταβλθτζσ. Στθν main ορίςτε ζναν διςδιάςτατο πίνακα χαρακτιρων που κα αναπαριςτά τον χάρτθ του κόςμου. Ο πίνακασ να είναι global και το μζγεκοσ του να προςδιορίηεται απο τθν τιμι μιασ μεταβλθτισ const. Στθν main προςκζςτε δυο ςυναρτιςεισ: printworld: εκτυπϊνει τον πίνακα ςτθν οκόνθ clearworld: κζτει όλεσ τισ τιμζσ του πίνακα ςε Στο ςϊμα τθσ main: δϊςτε αρχικζσ ςυντεταγμζνεσ ςτουσ ιρωεσ Τοποκετιςτε τουσ ιρωεσ (του πίνακα θρϊων) ςτον χάρτθ αναπαριςτϊντασ τουσ με τον πρϊτο χαρακτιρα του ονόματοσ τουσ Εκτυπϊςτε τον χάρτθ με τθν printworld Μετακινιςτε τουσ ιρωεσ με τυχαίο τρόπο κατα μία κζςθ ελζγχοντασ οτι μζνουν ςτα όρια του χάρτθ Εκτυπϊςτε τον χάρτθ ξανά Εκτυπϊςτε τθν κατάςταςθ των θρϊων με τθν print
Άςκθςθ 7 Προςκζςτε ςτθ κλάςθ Hero, δυο μεταβλθτζσ Χ,Υ που αναπαριςτοφν τισ ςυντεταγμζνεσ του ιρωα ςτον χάρτθ. Προςκζςτε ςυνάρτθςθ setxy που κζτει τιμζσ ςτισ παραπάνω μεταβλθτζσ. class Hero{ ;... void setxy(int,int); int X; int Y; int X; int Y;... void Hero::setXY(int Xin,int Yin){ X=Xin; Y=Yin;
Άςκθςθ 7 Στθν main ορίςτε ζναν διςδιάςτατο πίνακα χαρακτιρων που κα αναπαριςτά τον χάρτθ του κόςμου. Ο πίνακασ να είναι global και το μζγεκοσ του να προςδιορίηεται απο τθν τιμι μιασ μεταβλθτισ const. const int DIMENSION=5; char WORLD[DIMENSION][DIMENSION]; Στθν main προςκζςτε δυο ςυναρτιςεισ: printworld: εκτυπϊνει τον πίνακα ςτθν οκόνθ clearworld: κζτει όλεσ τισ τιμζσ του πίνακα ςε void printworld(){ for(int i=0;i<dimension;i++){ cout<<endl; for(int j=0;j<dimension;j++) cout<<world[i][j]; cout<<endl; void clearworld(){ for(int i=0;i<dimension;i++) for(int j=0;j<dimension;j++) WORLD[i][j]=' ';
Άςκθςθ 7 srand( time( 0 ) ); hero1->setxy(0,0); warrior1->setxy(1,1); warrior2->setxy(3,3); mage1->setxy(2,2); bloodmage1->setxy(4,4); clearworld(); for(int i=0;i<herosarray_num;i++){ char* name=herosarray[i]->getname(); char f=name[0]; int x= HerosArray[i]->X; int y= HerosArray[i]->Y; WORLD[x][y]=f; printworld(); Στο ςϊμα τθσ main: o δϊςτε αρχικζσ ςυντεταγμζνεσ ςτουσ ιρωεσ o Τοποκετιςτε τουσ ιρωεσ (του πίνακα θρϊων) ςτον χάρτθ αναπαριςτϊντασ τουσ με τον πρϊτο χαρακτιρα του ονόματοσ τουσ o Εκτυπϊςτε τον χάρτθ με τθν printworld o Μετακινιςτε τουσ ιρωεσ με τυχαίο τρόπο κατα μία κζςθ ελζγχοντασ οτι μζνουν ςτα όρια του χάρτθ o Εκτυπϊςτε τον χάρτθ ξανά o Εκτυπϊςτε τθν κατάςταςθ των θρϊων με τθν print
Άςκθςθ 7 clearworld(); for(int i=0;i<herosarray_num;i++){ int x= HerosArray[i]->X; int y= HerosArray[i]->Y; char* name=herosarray[i]->getname(); char f=name[0]; int move= rand()%4 ; if (move==0 && x-1>-1 && x-1<dimension ) x--; else if (move==1 && x+1>-1 && x+1<dimension ) x++; else if (move==2 && y-1>-1 && y-1<dimension ) y--; else if (move==3 && y+1>-1 && y+1<dimension ) y++; HerosArray[i]->setXY(x,y); WORLD[x][y]=f; printworld(); Στο ςϊμα τθσ main: o δϊςτε αρχικζσ ςυντεταγμζνεσ ςτουσ ιρωεσ o Τοποκετιςτε τουσ ιρωεσ (του πίνακα θρϊων) ςτον χάρτθ αναπαριςτϊντασ τουσ με τον πρϊτο χαρακτιρα του ονόματοσ τουσ o Εκτυπϊςτε τον χάρτθ με τθν printworld o Μετακινιςτε τουσ ιρωεσ με τυχαίο τρόπο κατα μία κζςθ ελζγχοντασ οτι μζνουν ςτα όρια του χάρτθ o Εκτυπϊςτε τον χάρτθ ξανά o Εκτυπϊςτε τθν κατάςταςθ των θρϊων με τθν print
Άςκθςθ 7 for(int i=0;i<herosarray_num;i++){ cout<<herosarray[i]->x<<","<<herosarray[i]->y<<" "; HerosArray[i]-> print(); Στο ςϊμα τθσ main: o δϊςτε αρχικζσ ςυντεταγμζνεσ ςτουσ ιρωεσ o Τοποκετιςτε τουσ ιρωεσ (του πίνακα θρϊων) ςτον χάρτθ αναπαριςτϊντασ τουσ με τον πρϊτο χαρακτιρα του ονόματοσ τουσ o Εκτυπϊςτε τον χάρτθ με τθν printworld o Μετακινιςτε τουσ ιρωεσ με τυχαίο τρόπο κατα μία κζςθ ελζγχοντασ οτι μζνουν ςτα όρια του χάρτθ o Εκτυπϊςτε τον χάρτθ ξανά o Εκτυπϊςτε τθν κατάςταςθ των θρϊων με τθν print
Άςκθςθ 8 Δθμιουργιςτε μια δομι επανάλθψθσ ωςτε ςε κάκε επανάλθψθ να μετακινοφνται οι ιρωεσ, ανανεϊνοντασ τθν κατάςταςθ του χάρτθ και να εμφανίηεται θ κατάςταςθ τουσ. Η προςομοίωςθ κα ςταματάει μετά απο ςυγκεκριμζνο αρικμό επαναλιψεων Δοκιμάςτε να γίνεται θ μετάβαςθ ςε επόμενθ επανάλθψθ αυτόματα (αμζςωσ ι μετά απο λίγα δευτερόλεπτα) και χειροκίνθτα (αφοφ πατιςει ο χριςτθσ ζνα κουμπί)
Άςκθςθ 8 int T=0; while(t<30){ T++; main.cpp system("cls"); printworld(); clearworld(); --- ΜΕΣΑΚΙΝΗΕΙ ΗΡΩΩΝ --- system("cls"); printworld(); --- ΕΚΣΤΠΩΗ ΚΑΣΑΣΑΗ ΗΡΩΩΝ --- Sleep(1000); ή system("pause");
Άςκθςθ 9 Προςκζςτε ςτον κϊδικα τθσ προςωμείωςθσ κϊδικα ωςτε αφοφ ολοκλθρωκοφν οι τυχαίεσ μετακινιςεισ των θρϊων, να ελζγχει ο κακζνασ αν υπάρχει άλλοσ ιρωασ ςτθν ίδια κζςθ και αν υπάρχει να του επιτίκεται.
Άςκθςθ 9 main.cpp for(int i=0;i<herosarray_num;i++){ for(int j=0;j<herosarray_num;j++){ if (i==j) continue; if ( (HerosArray[i]->X == HerosArray[j]->X) && (HerosArray[i]->Y == HerosArray[j]->Y) ) HerosArray[i]->attack(*HerosArray[j]);
Άςκθςθ 10 Επεκτείνεται το προθγοφμενο ερϊτθμα ωςτε αν μετά απο μία επίκεςθ θ ηωι (Life) ενόσ ιρωα ζχει τιμι κάτω απο 0 να διαγράφεται το αντικείμενο απο τθν μνιμθ. Πϊσ επθρεάηει θ διαγραφι τον πίνακα θρϊων; Τι αλλαγζσ πρζπει να κάνουμε για να διαςφαλίςουμε τθν ομαλι λειτουργία του προγράμματοσ.
Άςκθςθ 10 if ((HerosArray[i]->X == HerosArray[j]->X) && (HerosArray[i]->Y == HerosArray[j]->Y) ){ HerosArray[i]->attack(*HerosArray[j]); if (HerosArray[j]->getLife() <0 ){ char* name=herosarray[i]->getname(); char f=name[0]; WORLD[HerosArray[i]->X][HerosArray[i]->Y]=f; levelup(*herosarray[i]); delete (HerosArray[j]); HerosArray[j]=0; PLAYERS--; Sleep(2000); main.cpp Η delete απλά αποδεςμεφει τθν κζςθ μνιμθσ τθσ μεταβλθτισ ςτθν οποία δείχνει το HerosArray[j]. Το περιεχόμενο τθσ μνιμθσ δεν τροποποιείται και θ προςπζλαςθ του HerosArray[j] γίνεται αρχικά κανονικά. Ενδζχεται κάποια ςτιγμι όμωσ το πρόγραμμα να δεςμεφςει τθν μνιμθ και θ προςπζλαςθ του HerosArray[j] να οδθγιςει ςε κατάρευςθ του προγράμματοσ. Θζτουμε τον δείκτθ HerosArray[j] ςτο 0 (null) ωςτε να μποροφμε να ελζγξουμε τθν περίπτωςθ.
Άςκθςθ 10 for(int i=0;i<herosarray_num;i++){ if (HerosArray[i]==0) continue;... Κάκε φορά που διαπερνάμε τα ςτοιχεία του πίνακα κα πρζπει να ελζγχουμε αν το αντικείμενο ςτο οποίο δείχνουν ζχει διαγραφεί.
Άςκθςθ 11 Τροποποιιςτε το πρόγραμμα ϊςτε αντί για απλό πίνακα array να κρατάτε τουσ ιρωεσ ςε πίνακα vector
Άςκθςθ 11 #include <vector> vector <Hero*> HerosArray; HerosArray.push_back(hero1); HerosArray.push_back(warrior1); HerosArray.push_back(warrior2); HerosArray.push_back(mage1); HerosArray.push_back(bloodmage1); for(int i=0;i<herosarray.size();i++){ HerosArray[i]-> print(); Δεν χρειάηεται να δθλϊςουμε μζγεκοσ. Αυξάνεται και μειϊνεται δυναμικά όποτε προςκζτουμε ι αφαιροφμε ςτοιχεία. Διαπζραςθ των ςτοιχείων με απλό for και χριςθ τθσ size() for(vector<hero*>::iterator it=herosarray.begin(); it!=herosarray.end() ;it++){ (*it)->print(); Διαπζραςθ των ςτοιχείων με χριςθ iterator random_shuffle( HerosArray.begin(), HerosArray.end() ); Ανακάτεμα των ςτοιχείων του
Άςκθςθ 11 if ((HerosArray[i]->X == HerosArray[j]->X) && (HerosArray[i]->Y == HerosArray[j]->Y) ){ HerosArray[i]->attack(*HerosArray[j]); if (HerosArray[j]->getLife() <0 ){ char* name=herosarray[i]->getname(); char f=name[0]; WORLD[HerosArray[i]->X][HerosArray[i]->Y]=f; levelup(*herosarray[i]); delete (HerosArray[j]); HerosArray.erase (HerosArray.begin()+j); Sleep(2000); Το μζγεκοσ του vector πίνακα αλλάηει δυναμικά, προςκζτοντασ και αφαιρϊντασ ςτοιχεία. Εδϊ απλά διαγράφουμε το ςτοιχείο, δεν χρειάηεται να κζςουμε ςε null και να ελζγχουμε μετά όπωσ ςτθν προθγοφμενθ άςκθςθ.
Άςκθςθ 12 Προςκικθ δυνατότθτασ παφςθσ τθσ προςομοίωςθσ όταν ο χριςτθσ πατάει κάποιο κουμπί (πχ το P )
Virtual-Key Code for P key if (GetAsyncKeyState(0x50)){ system("pause"); H GetAsyncKeyState(int vkey) (Βιβλιοκικθ <windows.h>) επιςτρζφει: Μθδζν αν δεν ζχει πατθκεί το κουμπί από τθν τελευταία κλιςθ τθσ GetAsyncKeyState Μθ μθδενικό αρικμό αν το πλικτρο ζχει πατθκεί από τθν τελευταία κλιςθ Αν ο αρικμόσ είναι κετικόσ τότε τθν χρονικι ςτιγμι τθσ κλιςθσ τθσ GetAsyncKeyState το πλικτρο ιταν πατθμζνο από τον χριςτθ.