This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
laboratoare:old-exercises [2019/12/02 15:55] Adriana Draghici |
laboratoare:old-exercises [2020/01/04 12:19] (current) Adriana Draghici [Singleton, Observer, Factory] |
||
---|---|---|---|
Line 138: | Line 138: | ||
== Clase interne == | == Clase interne == | ||
- | | ||
- | |||
| | ||
Implementați un terminal bash simplu pornind de la {{ :laboratoare:old-exercises:clase-interne-skel.zip |scheletul de cod}}. Comenzile pe care va știi să le execute sunt: **echo, cd, ls și history**. Bash-ul va citi comenzi de la tastatură până când va primi comanda **exit** când se va închide (programul se termină). | Implementați un terminal bash simplu pornind de la {{ :laboratoare:old-exercises:clase-interne-skel.zip |scheletul de cod}}. Comenzile pe care va știi să le execute sunt: **echo, cd, ls și history**. Bash-ul va citi comenzi de la tastatură până când va primi comanda **exit** când se va închide (programul se termină). | ||
Line 255: | Line 253: | ||
== Colecții == | == Colecții == | ||
- | - (**1p**) Instanţiati o colecţie care sǎ **nu** permitǎ introducerea elementelor duplicate, folosind o implementare corespunzǎtoare din bibliotecă. La introducerea unui element existent, semnalaţi eroare. Colecţia va reţine ''String''-uri şi va fi parametrizatǎ. | + | - Instanţiati o colecţie care sǎ **nu** permitǎ introducerea elementelor duplicate, folosind o implementare corespunzǎtoare din bibliotecă. La introducerea unui element existent, semnalaţi eroare. Colecţia va reţine ''String''-uri şi va fi parametrizatǎ. |
- | - (**2p**) Creaţi o clasǎ ''Student''. | + | - Creaţi o clasǎ ''Student''. |
- Adǎugaţi urmǎtorii membri: | - Adǎugaţi urmǎtorii membri: | ||
* **câmpurile** ''nume'' (de tip ''String'') şi ''medie'' (de tip ''float'') | * **câmpurile** ''nume'' (de tip ''String'') şi ''medie'' (de tip ''float'') | ||
Line 265: | Line 263: | ||
* În ''Student'' suprascrieți metoda ''equals'' astfel încât să se ţină cont de câmpurile clasei, şi încercaţi din nou. Ce observaţi? | * În ''Student'' suprascrieți metoda ''equals'' astfel încât să se ţină cont de câmpurile clasei, şi încercaţi din nou. Ce observaţi? | ||
* //Hint:// [[http://docs.oracle.com/javase/8/docs/api/java/util/Set.html#add(E)|Set.add]], [[http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals(java.lang.Object)|Object.equals]], [[http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode()|Object.hashCode]] | * //Hint:// [[http://docs.oracle.com/javase/8/docs/api/java/util/Set.html#add(E)|Set.add]], [[http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals(java.lang.Object)|Object.equals]], [[http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode()|Object.hashCode]] | ||
- | - (**2p**) Plecând de la implementarea exerciţiului anterior, realizaţi urmǎtoarele modificǎri: | + | - Plecând de la implementarea exerciţiului anterior, realizaţi urmǎtoarele modificǎri: |
* Supraîncǎrcaţi, în clasa ''Student'', metoda ''equals'', cu o variantǎ care primeşte un parametru ''Student'', şi care întoarce întotdeauna ''false''. | * Supraîncǎrcaţi, în clasa ''Student'', metoda ''equals'', cu o variantǎ care primeşte un parametru ''Student'', şi care întoarce întotdeauna ''false''. | ||
- | * Testaţi comportamentul prin crearea unei colecţii ce conţine instanţe de ''Student'' şi iteraţi prin această colecţie, afişând la fiecare pas ''element.equals(element)'' şi ''((Object)element).equals(element)'' (unde ''element'' este numele de variabilă ales pentru fiecare element al colecţiei). Cum explicaţi comportamentul observat? Dacă folosiţi un iterator, acesta va fi şi el **parametrizat**. | + | * Testaţi comportamentul prin crearea unei colecţii ce conţine instanţe de ''Student'' şi iteraţi prin această colecţie, afişând la fiecare pas ''element.equals(element)'' şi ''%%((Object)element).equals(element)%%'' (unde ''element'' este numele de variabilă ales pentru fiecare element al colecţiei). Cum explicaţi comportamentul observat? Dacă folosiţi un iterator, acesta va fi şi el **parametrizat**. |
- | - (**3p**) Creați clasa ''Gradebook'', de tip ''Map'', pentru reţinerea studenţilor dupǎ medie: cheile sunt mediile și valorile sunt liste de studenți. Gradebook va menţine cheile **ordonate descrescǎtor**. Extindeţi o implementare potrivitǎ a interfeţei ''Map'', care sǎ permitǎ acest lucru. | + | - Creați clasa ''Gradebook'', de tip ''Map'', pentru reţinerea studenţilor dupǎ medie: cheile sunt mediile și valorile sunt liste de studenți. Gradebook va menţine cheile **ordonate descrescǎtor**. Extindeţi o implementare potrivitǎ a interfeţei ''Map'', care sǎ permitǎ acest lucru. |
- Caracteristicile clasei definite sunt: | - Caracteristicile clasei definite sunt: | ||
- Cheile pot avea valori de la 0 la 10 (corespunzǎtoare mediilor posibile). Verificați acest lucru la adăugare. | - Cheile pot avea valori de la 0 la 10 (corespunzǎtoare mediilor posibile). Verificați acest lucru la adăugare. | ||
Line 278: | Line 276: | ||
- iteraţi pe Gradebook şi sortaţi alfabetic fiecare listǎ de studenţi pentru fiecare notă. Pentru a sorta, se va folosi metoda [[https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-|Collections.sort]], iar clasa Student va implementa o interfață care specifică modul în care sunt comparate elementele. | - iteraţi pe Gradebook şi sortaţi alfabetic fiecare listǎ de studenţi pentru fiecare notă. Pentru a sorta, se va folosi metoda [[https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-|Collections.sort]], iar clasa Student va implementa o interfață care specifică modul în care sunt comparate elementele. | ||
* clasa ''Student'' va implementa interfaţa [[http://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html|Comparable]], suprascriind metoda [[http://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#compareTo(T)|compareTo]]. | * clasa ''Student'' va implementa interfaţa [[http://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html|Comparable]], suprascriind metoda [[http://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#compareTo(T)|compareTo]]. | ||
- | - (**2p**) Creaţi o clasǎ care moşteneşte ''HashSet<Integer>''. | + | - Creaţi o clasǎ care moşteneşte ''HashSet<Integer>''. |
* Definiţi în aceastǎ clasǎ o variabilǎ membru care reţine numǎrul total de elemente adǎugate. Pentru a contoriza acest lucru, suprascrieți metodele ''add'' şi ''addAll''. Pentru adǎugarea efectivǎ a elementelor, folosiţi implementǎrile din clasa pǎrinte (''HashSet''). | * Definiţi în aceastǎ clasǎ o variabilǎ membru care reţine numǎrul total de elemente adǎugate. Pentru a contoriza acest lucru, suprascrieți metodele ''add'' şi ''addAll''. Pentru adǎugarea efectivǎ a elementelor, folosiţi implementǎrile din clasa pǎrinte (''HashSet''). | ||
* Testaţi, folosind atât ''add'' cât şi ''addAll''. Ce observaţi? Corectaţi dacǎ este cazul. | * Testaţi, folosind atât ''add'' cât şi ''addAll''. Ce observaţi? Corectaţi dacǎ este cazul. | ||
Line 293: | Line 291: | ||
== Design Patterns == | == Design Patterns == | ||
- | === Singleton, Observer, Strategy === | + | === Singleton, Observer, Factory === |
- | Acest laborator și [[laboratoare:design-patterns2|următorul]] au ca temă comună a exercițiilor realizarea unui joc controlat din consolă. Jocul constă dintr-o lume (aka hartă) în care se plimbă eroi de trei tipuri, colectează comori și se bat cu monștri. În acestă săptămână trebuie să implementați o parte din funcționalitățile jocului folosind patternurile //Singleton//, //Factory// și //Observer//, urmând ca la laboratorul următor să terminați implementarea folosind pattern-urile studiate atunci. | + | Exercițiile din această secțiune și din urmatoarea au ca temă comună realizarea unui joc controlat din consolă. Jocul constă dintr-o lume (aka hartă) în care se plimbă eroi de trei tipuri, colectează comori și se bat cu monștri. În acestă secțiune trebuie să implementați o parte din funcționalitățile jocului folosind patternurile //Singleton//, //Factory// și //Observer//, urmând ca în secțiunea următoare să terminați implementarea. |
+ | |||
+ | Schelet: {{.:design-patterns:design-patterns1-skel.zip|Schelet}} | ||
Detalii joc: | Detalii joc: | ||
* //Harta// | * //Harta// | ||
- | * reprezentată printr-o matrice. Fiecare element din matrice reprezintă o zonă care poate fi liberă, poate conține obstacole sau poate conține o comoară (în laboratorul următor poate conține și monștrii). | + | * reprezentată printr-o matrice. Fiecare element din matrice reprezintă o zonă care poate fi liberă, poate conține obstacole sau poate conține o comoară (în secțiunea următoare poate conține și monștrii). |
* este menținută în clasa ''World''. | * este menținută în clasa ''World''. | ||
* //Eroii// | * //Eroii// | ||
Line 330: | Line 330: | ||
- Notificați observatorii lui ''World'' când eroii execută o acțiune. Aveți două ''TODO''-uri în clasa ''Hero''. | - Notificați observatorii lui ''World'' când eroii execută o acțiune. Aveți două ''TODO''-uri în clasa ''Hero''. | ||
* Începeți rezolvarea prin implementarea claselor pentru eroi și implementarea design pattern-ului factory pentru crearea lor. Pentru a putea vizualiza harta trebuie să implementați partea de observare a stării jocului. ''World'' trebuie să fie observabilă și să notifice pe observatorii săi atunci când a început jocul și când se schimbă ceva (e.g. s-a mutat un erou). | * Începeți rezolvarea prin implementarea claselor pentru eroi și implementarea design pattern-ului factory pentru crearea lor. Pentru a putea vizualiza harta trebuie să implementați partea de observare a stării jocului. ''World'' trebuie să fie observabilă și să notifice pe observatorii săi atunci când a început jocul și când se schimbă ceva (e.g. s-a mutat un erou). | ||
- | * Urmăriți todo-urile din scheletul de cod (pentru a le vizualiza mai ușor pe toate puteți să folosiți view-ul pt ele din IDE, de exemplu în eclipse aveți //Window -> Show View -> Tasks//) | + | * Urmăriți **todo**-urile din scheletul de cod (pentru a le vizualiza mai ușor pe toate puteți să folosiți view-ul pt ele din IDE, de exemplu în eclipse aveți //Window -> Show View -> Tasks//) |
<imgcaption exercitii|> | <imgcaption exercitii|> | ||
{{:laboratoare:design-patterns:exercitiu.png|Componentele jocului}}</imgcaption> | {{:laboratoare:design-patterns:exercitiu.png|Componentele jocului}}</imgcaption> | ||
+ | === Strategy, Command === | ||
+ | Această secțiune și cea precedentă au ca temă comună a exercițiilor realizarea unui joc controlat din consolă. Jocul constă dintr-o lume (aka hartă) în care se plimbă eroi de trei tipuri, colectează comori și se bat cu monștrii. În acestă secțiune terminam jocul inceput in cea precedenă folosind pattern-urile //Strategy// și //Command//. | ||
+ | Detalii joc: | ||
+ | * //Harta// | ||
+ | * reprezentată printr-o matrice. Fiecare element din matrice reprezintă o zonă care poate fi liberă, poate conține obstacole, monștrii sau o comoară | ||
+ | * este menținută în clasa ''GameState''. | ||
+ | * //Eroii// | ||
+ | * sunt reprezentați prin clase de tip ''Hero'' și sunt de trei tipuri: //Mage//, //Warrior//, //Priest//. | ||
+ | * puteți adăuga oricâți eroi doriți pe hartă (cât vă permite memoria :)) | ||
+ | * într-o zonă pot fi mai mulți eroi | ||
+ | * acțiunile pe care le pot face: | ||
+ | * ''move'' - se mută într-o zonă învecinată | ||
+ | * ''attack'' - ataca un monstru cand se afla pe aceeasi pozitie cu el | ||
+ | * ''collect'' - eroul ia comoara găsită în zona în care se află | ||
+ | * Entry-point-ul în joc îl consitituie clasa ''Main''. | ||
+ | * Folosiți design pattern-ul //Command// pentru a implementa functionalitatea de undo si redo la comanda ''move''. | ||
+ | * Momentan, aveti erori de compilare in clasele Main si GameState. Dupa ce veti implementa acest exercitiu, se vor rezolva, nu modificati in mod direct acolo. | ||
+ | * Va trebui sa completati clasa ''MoveCommand'' care implementeaza interfata ''Command''. Urmariti //TODO-urile// din aceasta clasa. | ||
+ | * //__Hint__//: Pentru Undo, de exemplu, daca v-ati deplasat la dreapta, ar trebui sa va deplasati la stanga. Creati-va o metoda ajutatoare care trateaza astfel de cazuri. | ||
+ | * Precum si clasa ''CommandManager'' care va tine evidenta comenzilor si ordinea lor. | ||
+ | * //__Hint__//: Amintiti-va de la cursul de Structuri de Date cum se implementează operatiile Redo si Undo. Folositi doua stive. | ||
+ | * Folosiți design pattern-ul //Strategy// pentru a implementa logica de atac a unui monstru. | ||
+ | * Pentru acest exercitiu va trebui sa implementati 2 strategii: **AttackStrategy** si **DefenseStrategy**. Ambele vor implementa Strategy si metodele aferente. Fiecare din aceste Strategy, va retine o referinta interna la un Hero. Abordarea este urmatoarea: | ||
+ | * Exista 3 clase Hero, fiecare cu cate un DamageType aferent: Warrior - Blunt, Mage - Magic, Priest - Poison | ||
+ | * Fiecare monstru are un weakness (slabiciune la atacurile de tip Blunt, Magic sau Poison) | ||
+ | * **AttackStrategy**: In metoda attack(), veti itera prin inventory-ul eroului si veti verifica daca exista un obiect Treasure care are DamageType-ul identic cu cel al eroului. Daca da, atunci damage-ul pe care il veti da unui obiect Monster este **3 x damage-ul treasure-ului**. Daca nu aveti un astfel de Treasure, atunci cautati un Treasure cu un DamageType identic cu cel al mob-ului (mobul poate fi vulnerabil la Magic, de ex.). Daca gasiti un astfel de Treasure, damage-ul pe care il veti imprima mob-ului este **2 x damage-ul treasure-ului**. Daca nu, veti scade din HP-ul mob-ului rezultatul apelului metodei getBaseDamage() asupra Hero-ului. | ||
+ | * **DefenseStrategy**: In metoda attack(), veti itera prin inventory-ul eroului si veti verifica, la fel, daca exista un obiect Treasure care are DamageType-ul identic cu cel al eroului. Daca da, atunci veti da un boost de HP egal cu treasure.getBoostHp() + getBaseHpBoost() eroului (getBaseHpBoost este implementata in clasa Hero). Daca nu, veti da doar un boost egal cu ce va intoarce getBaseHpBoost(). Damage-ul imprimat mobului va fi, de asemenea, egal cu ce va intoarce getBaseDamage(). Adaugati log-uri in clasa DefenseStrategy, pentru a va asigura ca i se mareste viata eroului. | ||
+ | * Urmariti si TODO-urile din cele doua clase | ||
+ | * Implementati metoda //attack// din clasa **Hero** astfel incat, daca eroul are mai mult de **50HP**, folositi strategia **AttackStrategy**. Altfel, folositi **DefenseStrategy**. Urmariti TODO-urile din cod. | ||
+ | * Implementați coliziunile cu obstacolele de pe hartă | ||
+ | * Va trebui sa creati un nou obiect ''Obstacle'' precum si un ''ObstacleObserver'' | ||
+ | * Cand eroul ajunge pe un obstacol se va printa un mesaj ''Can't move there !'' si se va apela automat undo pe ultima comanda de move pentru a reveni in pozitia anterioara coliziunii. Acest feature de wall collision va fi implementat in ''ObstacleObserver'' |