Ciele
- Vytvoriť triedy podľa návrhu jadra hry z minulého cvičenia.
- Implementovať základnú logiku hry na základe návrhov z minulého cvičenia.
- Vytvoriť unit testy pre otestovanie inicializácie herného poľa a metód hernej logiky.
Postup
Krok 1
Úloha 1.1
Vytvorte triedy jadra hry v jazyku Java podľa návrhu, ktorý ste vypracovali za uplynulý týždeň.
Dbajte na vhodné pomenovania tried, metód, premenných a pod., udržiavajte patričné odsadenia kódu a čleňte zdrojový kód s ohľadom na princípy OOP.
Poznámka
Pri implementácii podľa možností využite návrhové vzory, s ktorými ste sa už mohli oboznámiť na predmete Objektovo-orientované programovanie.
Váš zdrojový kód organizujte do vhodných balíkov. Pre hru Minesweeper by bol hlavným balíkom napr. sk.tuke.kpi.kp.minesweeper
umiestnený v adresári src
.
Pre reprezentáciu herného poľa vašej hry zvážte vhodnú údajovú štruktúru. V prípade hry Minesweeper sa ako vhodné javí dvojrozmerné pole typu Tile[][]
. Pre rôzne typy dlaždíc odporúčame využiť viaceré triedy, ktoré dedia od všeobecnej triedy Tile
.
Poznámka
Pred začatím implementácie návrh môžete prekonzultovať s cvičiacim.
Úloha 1.2
Vygenerujte konvenčné metódy get, set a konštruktory podľa pravidiel zapuzdrenia v objektovo-orientovanom programovaní.
V prostredí IntelliJ Idea je možné get a set metódy generovať na základe už deklarovaných atribútov triedy, výberom možnosti Refactor -> Encapsulate Fields ...
z ponuky kontextového alebo hlavného menu.
Následne je možné v zobrazenom dialógovom okne vybrať metódy, ktoré sa majú vygenerovať.
Konštruktory je v prostredí IntelliJ Idea možné vygenerovať výberom možnosti Generate...
z ponuky kontextového menu alebo Code -> Generate...
z hlavného menu a následne výberom možnosti Constructor
z menu zobrazeného nad zdrojovým kódom.
Následne je možné v zobrazenom dialógovom okne vybrať atribúty, ktoré majú byť konštruktorom inicializované.
Generovanie kódu je možné kedykoľvek vyvolať aj klávesovou skratkou Alt+Insert
.
Krok 2
Implementujte základy hernej logiky na základe vášho návrhu z uplynulého týždňa. Pre pripomenutie, ide konkrétne o:
- Spôsob generovania herného poľa, jeho inicializáciu.
- Spôsob overovania stavov hry po každom ťahu hráča - či je hra vyhratá, prehratá alebo prebieha.
- Spôsob prechodu medzi stavmi dlaždíc, ťahy hráča.
Ak sa vám to podarí, na konci tohto modulu by ste mali mať pripravené všetko potrebné na vytvorenie konzolového rozhrania hry.
Krok 3
Keďže ešte nemáme hotové používateľské rozhranie hry, je na mieste otestovať vytvorené metódy.
Úloha 3.1
Vytvorte jednotkové (unit) testy pomocou JUnit 5 pre otestovanie:
- správnej inicializácie herného poľa a stavov hry či dlaždíc,
- správneho generovania herného poľa,
- správnej funkcionality metód hernej logiky - overovanie stavov hry a dlaždíc, prechody medzi stavmi a pod.
Poznámka:
Pre písanie testov budete potrebovať knižnicu JUnit, so stiahnutím ktorej vám môže pomôcť priamo vyvojové prostredie IntelliJ IDEA. Pri označení testovacej metódy s anotáciou @Test
bude táto pravdepodobne vyznačená červenou farbou. Presunutím kurzora na anotáciu a použitím klávesovej skratky Alt+Enter
vyvoláte kontextové menu s akciami, medzi ktorými bude aj možnosť pridať potrebnú knižnicu JUnit do projektu.
Poznámka:
Zdrojový kód pre testy umiestňujte do osobitného adresára, napríklad test
(vedľa adresára src
) a taktiež ho patrične čleňte do balíkov (napríklad pre hru Minesweeper by bol hlavný balík sk.tuke.kpi.kp.minesweeper
).
Triedy s kódom testov pomenovávajte podľa tried, ktoré testujete, s tým, že za názov pripojte ešte slovo Test. Napríklad, trieda s testami overujúcimi funkcionalitu triedy herného poľa Field
by sa nazývala FieldTest
.
Jednotlivé testovacie metódy, ktoré budú overovať základné jednotky funkcionality, označte anotáciou @Test
.
Testovacia trieda FieldTest
s ukážkou niekoľkých testov by mohla vyzerať napríklad nasledovne:
package sk.tuke.kpi.kp.minesweeper;
import org.junit.jupiter.api.Test;
import sk.tuke.gamestudio.game.mines.myname.core.Field;
import sk.tuke.gamestudio.game.mines.myname.core.Mine;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.*;
public class FieldTest {
private Random randomGenerator = new Random();
private Field field;
private int rowCount;
private int columnCount;
private int minesCount;
public FieldTest() {
rowCount = randomGenerator.nextInt(10) + 5;
columnCount = rowCount;
minesCount = Math.max(1, randomGenerator.nextInt(rowCount * columnCount));
field = new Field(rowCount, columnCount, minesCount);
}
@Test
public void checkMinesCount() {
int minesCounter = 0;
for (int row = 0; row < rowCount; row++) {
for (int column = 0; column < columnCount; column++) {
if (field.getTile(row, column) instanceof Mine) {
minesCounter++;
}
}
}
assertEquals(minesCount, minesCounter, "Field was initialized incorrectly - " +
"a different amount of mines was counted in the field than amount given in the constructor.");
}
@Test
public void fieldWithTooManyMines() {
Field fieldWithTooManyMines = null;
int higherMineCount = rowCount * columnCount + randomGenerator.nextInt(10) + 1;
try {
fieldWithTooManyMines = new Field(rowCount, columnCount, higherMineCount);
} catch (Exception e) {
// field with more mines than tiles should not be created - it may fail on exception
}
assertTrue((fieldWithTooManyMines == null) || (fieldWithTooManyMines.getMineCount() <= (rowCount * columnCount)));
}
// ... dalsie testy
}
Úloha 3.2
Overte vašu implementáciu jadra hry spustením jednotkových testov, ktoré ste implementovali v predošlej úlohe.
V prípade, že niektorý z testov neprejde, vyhľadajte chyby vo vašej implementácii a opravte ich. Postup opakujte, kým nebude váš zdrojový kód fungovať správne.
Krok 4
Úloha 4.1
Nahrajte vašu implementáciu do vášho repozitára na GitLab-e. Projekt môžete ďalej priebežne aktualizovať. Pred ďalším cvičením sa uistite, že máte v repozitári vaše aktuálne súbory. Zároveň si pripravte otázky, ktoré by ste na cvičení chceli vyriešiť.
Zdroje
- JUnit 5
- Príklad JUnit testu pre Minesweeper.
- Dokumentácia pre tvorbu JUnit testov v prostredí IntelliJ IDEA.
- JUnit 5 používateľská príručka