4. týždeň

Úloha 3 - Tvoríme jednoduché konzolové rozhranie

Motivácia

Pri programovaní hier, ale aj iných softvérových systémov, je veľmi dôležité porozumieť tomu, ako bude používateľ aplikáciu používať, ako s ňou bude interagovať. V prípade hier je určite potrebné identifikovať fázy herného cyklu, akcie, ktoré môže vyvolať používateľ, a efekty, ktoré môžu mať tieto akcie na hru. Na tieto kľúčové úlohy sa zameriate pri implementácii konzolového používateľského rozhrania.

Pre implementáciu konzolového používateľského rozhrania hry je v prípade dlaždicových hier potrebné implementovať nasledujúce tri metódy:

  • play(Field field) - herná slučka, ktorá kombinuje vypisovanie textovej podoby herného poľa na výstup a dialóg s používateľom
  • show() - slúži na výpis textovej podoby herného poľa, volá sa vždy po jednom "ťahu" hry
  • handleInput() - spracuje používateľský vstup a vykoná príslušnú akciu s hrou

Ciele

  1. Implementovať hernú slučku, v ktorej bude hra prebiehať.
  2. Implementovať výpis textovej podoby herného poľa.
  3. Implementovať spracovanie používateľského vstupu a komunikáciu hry s používateľom.

Postup

Krok 1

Úloha 1.1

Implementujte metódu s funkcionalitou hernej slučky, napr. play(Field field), v triede predstavujúcej konzolové používateľské rozhranie, napr. ConsoleUI.

Metóda by mala vykonávať nasledujúce akcie:

  • inicializácia privátnej premennej pre herné pole field, ktorá sa využije ako vnútorný model hry,
  • v cykle:
    • výpis textovej reprezentácie herného poľa do konzoly pomocou metódy show(),
    • načítanie a spracovanie používateľského vstupu pomocou metódy handleInput(),
    • reakcia na zmenu stavu hry (FAILED, SOLVED a i.).

Poznámka

Pri implementácii podľa potreby rozdeľte zdrojový kód aj na prípadné pomocné privátne metódy.

Príklad implementácie metódy play pre hru Minesweeper :

public void play(Field field) {
    this.field = field;
    do {
        show();
        handleInput();
    } while(field.getState() == GameState.PLAYING);

    show();

    if(field.getState() == GameState.SOLVED) {
        System.out.println("Solved!");
    } else if(field.getState() == GameState.FAILED){
        System.out.println("Failed!");
    }
}

Krok 2

Na zobrazovanie herného poľa na štandardný výstup sú v prípade hry Minesweeper kladené nasledujúce požiadavky:

  • Riadky sú označované veľkými písmenami zoradenými podľa abecedy (A, B, ..., I).
  • Stĺpce sú označované číslicami (0, 1, ... , 8).
  • Pre vykreslenie odkrytej dlaždice (OPEN) typu mína (Mine) sa používa znak X.
  • Pre vykreslenie dlaždice v stave (OPEN) typu pomoc pri hľadaní (Clue) sa používa číslo reprezentujúce hodnotu dlaždice.
  • Pre vykreslenie označenej dlaždice (MARKED) sa používa znak M.
  • Pre vykreslenie neoznačenej dlaždice (CLOSED) sa používa znak -.

Obr. 1

V prípade dlaždicových hier odporúčame postupovať podobným spôsobom, teda definovať si, akým spôsobom bude vykresľované herné pole (dvojrozmerné pole v matici, jednorozmerné pole horizontálne alebo vertikálne, kartové hry rozložené podľa pozície hráčov resp. kariet). Následne definovať kódovanie jednotlivých políčok resp. kariet písmenami alebo špeciálnymi znakmi podobne ako u hry Minesweeper: M, -, a čísla pre nápovedu.

Údaje pre zobrazenie jednotlivých dlaždíc získate z hernej logiky (u nás objekt triedy Field).

Úloha 2.1

Implementujte vykreslenie herného poľa v metóde void show() v triede ConsoleUI.

Poznámka

Pre zobrazenie formátovaného výstupu (napríklad pri zobrazení označenia riadkov) môžete použiť napr. metódu System.out.printf(...), ktorá napr. dokáže formátovať výstup na preddefinovaný počet znakov, napr.: System.out.printf("%3d", 4) vypíše číslo 4 na 3 znaky. Pre viac informácií si túto metódu vyhľadajte v dokumentácii Javadoc.

Poznámka

Aby ste mohli na štandardný výstup jednoduchým spôsobom vypísať textovú podobu herného poľa, zadefinujte textovú reprezentáciu jednotlivých tried dlaždíc (napr. triedy Mine a Clue) prekrytím štandardnej metódy toString(). Napríklad:

public class Mine {
    @Override
    public String toString() {
        return "*";
    }
}

Krok 3

Úloha 3.1

Implementujte metódu handleInput() v triede ConsoleUI, ktorá má slúžiť na spracovanie používateľského vstupu.

V hre Minesweeper metóda handleInput() vykonáva nasledujúce akcie:

  • Vypíše požiadavku na zadanie vstupu so vzorom očakávaného vstupu od používateľa: X – ukončenie hry, jednotlivé ťahy - napr. MA1 – označenie dlaždice v riadku A a stĺpci 1, OB4 – odkrytie dlaždice v riadku B a stĺpci 4.
  • Načíta vstupnú požiadavku od používateľa (nextLine()).
  • Overí správnosť vstupného reťazca. Na overenie správnosti vstupu využíva regulárne výrazy.
  • V prípade požiadavky od používateľa, ktorá nie je v požadovanom tvare si vyžiada od používateľa opätovné zadanie vstupu.
  • Na základe identifikácie akcie od používateľa vykoná požadovanú operáciu (označenie dlaždice, odkrytie dlaždice, ukončenie programu).

Poznámka

Pre definíciu vzoru vstupu pomocou regulárneho výrazu vytvorte objekt triedy Pattern (napr. statická metóda Pattern.compile("O([A-I])([0-8])") pre vstup v tvare OA9 pre otvorenie dlaždice). To, či zadaný vstup zodpovedá vzoru, overte pomocou objektu triedy Matcher. Objekt triedy Matcher je možné získať pomocou metódy Matcher matcher(CharSequence input) vytvoreného objektu typu Pattern. Na overenie vstupov použite metódy boolean matches() a String group(int group) definované v triede Matcher.

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ť.

Doplňujúce úlohy

Úloha A.1

Pre zlepšenie použiteľnosti akceptujte používateľský vstup veľkými aj malými písmenami (napr. v hre Minesweeper oa9 aj OA9).

Úloha A.2

Implementujte podporu začatia novej hry po výhre alebo prehre:

Gratulujeme, vyhrali ste!
Prajete si začatie novej hry (A/N)? _

Zdroje

  1. Java Tutoriál venovaný regulárnym výrazom