Slevový týden - Březen C# týden
Využij náš slevový týden a získej až 30 % bodů navíc zdarma! Zároveň také probíhá C# týden se slevou na e-learning až 80 %
Hledáme fulltime programátora do ITnetwork týmu -100% homeoffice, 100% časově flexibilní #bezdeadlinu Mám zájem!

3. diel - Hracia kocka v Jave - konštruktory a náhodné čísla

V predchádzajúcom cvičení Riešené úlohy k 2. lekcii OOP v Jave sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Riešené úlohy k 2. lekcii OOP v Jave , sme si naprogramovali prvú objektovú aplikáciu. Už vieme tvoriť nové triedy a vkladať do nich atribúty a metódy s parametrami a návratovú hodnotou. V dnešnom tutoriále začneme pracovať na sľúbené aréne, v ktorej budú proti sebe bojovať dvaja bojovníci. Boj bude ťahový (na preskáčku) a bojovník vždy druhému uberie život na základe sily jeho útoku a obrany druhého bojovníka. Simulujeme v podstate stolný hru, budeme teda simulovať aj hraciu kocku, ktorá dodá hre prvok náhodnosti. Začnime zvoľna a vytvorme si dnes práve túto hraciu kocku. Zároveň sa naučíme ako definovať vlastné konštruktor.

Vytvorme si nový projekt a pomenujte ho TahovyBoj. K projektu si pridajme novú class s názvom Kocka. Zamyslime sa nad atribúty, ktoré kocke dáme. Iste by sa hodilo, keby sme si mohli zvoliť počet stien kocky (klasicky 6 alebo 10 stien, ako je zvykom u tohto typu hier). Ďalej bude kocka potrebovať tzv. Generátor náhodných čísel. Ten nám samozrejme poskytne Java, ktorá na tieto účely obsahuje triedu Random. Aby sme ju mohli používať, použijeme import java.util.Random. Import napíšeme hore, ako sme zvyknutí z používania Scannera. Naša trieda bude mať teraz 2 atribúty:

  • pocetSten typu int
  • random typu Random, kde bude náhodný generátor.

Minule sme kvôli jednoduchosti nastavovali všetky atribúty našej triedy ako public, teda ako verejne prístupné. Väčšinou sa však skôr nechce, aby sa dali zvonku modifikovať a používa sa modifikátor private. Atribút je potom viditeľný len vnútri triedy a zvonku sa Java tvári, že vôbec neexistuje. Pri návrhu triedy teda nastavíme všetko na private a v prípade, že niečo bude naozaj potrebné vystaviť, použijeme public. Naša trieda teraz vyzerá asi takto:

import java.util.Random;

/** Třída reprezentuje hrací kostku */
public class Kostka {
    /** Generátor náhodných čísel */
    private Random random;
    /** Počet stěn kostky */
    private int pocetSten;
}

Konštruktory

Až doteraz sme nevedeli zvonku nastaviť iné atribúty ako public, pretože napr. Private nie sú zvonku viditeľné. Už sme si hovorili niečo málo o konstruktoru objektu. Je to metóda, ktorá sa zavolá vo chvíli vytvorenia inštancie objektu. Slúži samozrejme k nastavenie vnútorného stavu objektu a na vykonanie prípadnej inicializácia. Kocku by sme teraz v TahovyBoj.java vytvorili takto:

Kostka kostka = new Kostka();

Práve Kocka () je konštruktor. Pretože v našej triede žiadny nie je, Java si dogeneruje prázdnu metódu. My si však teraz konštruktor do triedy pridáme. Deklaruje sa ako metóda, ale nemá návratový typ a musia mať rovnaké meno ako je meno triedy (začína teda na rozdiel od ostatných metód veľkým písmenom), v našom prípade teda Kostka. V konstruktoru nastavíme počet stien na pevnú hodnotu a vytvoríme inštanciu triedy Random. Konštruktor bude vyzerať nasledovne:

public Kostka() {
    pocetSten = 6;
    random = new Random();
}

Ak kocku teraz vytvoríme, bude mať v atribúte pocetSten 6 a v random bude vytvorená inštancia generátora náhodných čísel. Vypíšme si počet stien do konzoly, nech vidíme, že tam hodnota naozaj je. Nie je dobré atribút nastaviť na public, pretože nebudeme chcieť, aby nám niekto mohol už u vytvorenej kocky meniť počet stien. Pridáme do triedy teda metódu vratPocetSten (), ktorá nám vráti hodnotu atribútu pocetSten. Docielili sme tým v podstate toho, že je atribút read-only (atribút nie je viditeľný a možno ho len čítať metódou, zmeniť ho nemožno). Nová metóda bude vyzerať asi takto:

/**
 * Vrátí počet stěn hrací kostky
 * @return      počet stěn hrací kostky
 */
public int vratPocetSten() {
    return pocetSten;
}

Presuňme sa do TahovyBoj.java a vyskúšajme si vytvoriť kocku a vypísať počet stien:

    Kostka kostka = new Kostka(); // v tuto chvíli se zavolá konstruktor
    System.out.println(kostka.vratPocetSten());
import java.util.Random;

výstup:

Konzolová aplikácia
6

Vidíme, že sa konštruktor naozaj zavolal. My by sme ale chceli, aby sme mohli pri každej kocky pri vytvorení špecifikovať, koľko stien budeme potrebovať. Dáme teda kostruktoru parameter:

public Kostka(int aPocetSten) {
    pocetSten = aPocetSten;
    random = new Random();
}

Všimnite si, že sme pred názov parametra metódy pridali znak "a", pretože inak by mal rovnaký názov ako atribút a Javu by to zmiatlo. Vráťme sa k TahovyBoj.java a zadajte tento parameter do konstruktoru:

    Kostka kostka = new Kostka(10); // v tuto chvíli se zavolá konstruktor s par. 10
    System.out.println(kostka.vratPocetSten());
import java.util.Random;
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!

výstup:

Konzolová aplikácia
10

Všetko funguje, ako sme očakávali. Java nám už v tejto chvíli nevygeneruje prázdny (tzv. Bezparametrický konštruktor), takže kocku bez parametra vytvoriť nedá. My to však môžeme umožniť, vytvorme si ďalší konštruktor a tentoraz bez parametra. V ňom nastavíme počet stien na 6, pretože takú hodnotu asi užívateľ našej triedy u kocky očakáva ako predvolený:

public Kostka() {
    pocetSten = 6;
    random = new Random();
}

Skúsme si teraz vytvoriť 2 inštancie kocky, každú iným konstruktoru (v TahovyBoj.java):

    Kostka sestistenna = new Kostka();
    Kostka desetistenna = new Kostka(10);
    System.out.println(sestistenna.vratPocetSten());
    System.out.println(desetistenna.vratPocetSten());
import java.util.Random;

výstup:

Konzolová aplikácia
6
10

Jave nevadí, že máme 2 metódy s rovnakým názvom, pretože ich parametre sú rôzne. Hovoríme o tom, že metóda Kostka (teda tu konštruktor) má preťaženia (overload). Toho môžeme využívať aj u všetkých ďalších metód, nielen u konstruktoru. NetBeans nám prehľadne ponúka všetky preťaženia metódy vo chvíli, keď zadáme jej názov. V ponuke vidíme naše 2 konštruktory:

Pomoc k preťaženým metódam v Jave

Mnoho metód v Jave má hneď niekoľko preťaženie, skúste sa pozrieť napr. Na metódu indexOf () na triede String. Je dobré si u metód prejsť ich preťaženie, aby ste neprogramoval niečo, čo už niekto urobil pred vami.

Ukážeme si ešte, ako ide obísť nepraktický názov atribútu u parametrického konstruktoru (v našom prípade aPocetSten) a potom konstruktory opustíme. Problém je samozrejme v tom, že keď napíšeme:

public Kostka(int pocetSten) {
    pocetSten = pocetSten;
    random = new Random();
}

Java nevie, ktorú z premenných myslíme, či parameter alebo atribút. V tomto prípade priraďujeme do parametra znova ten istý parameter. NetBeans nás na túto skutočnosť dokonca upozorní. Vnútri triedy sa máme možnosť odkazovať na jej inštanciu, je uložená v premennej this. Využitie si môžeme predstaviť napr. Keby kocka mala metódu dejHraci (Hrac hrac) a tam by volala hrac.seberKostku (this). Tu by sme hráči pomocou this odovzdali seba samého, teda tú konkrétnu kocku, s ktorou pracujeme. My sa tým tu nebudeme zaťažovať, ale využijeme odkazu na inštanciu pri nastavovaní atribútu:

public Kostka(int pocetSten) {
    this.pocetSten = pocetSten;
    random = new Random();
}

Pomocou this sme špecifikovali, že ľavá premenná pocetSten náleží inštanciu, pravú Java chápe ako z parametra. Máme teda 2 konštruktory, ktoré nám umožňujú tvoriť rôzne hracie kocky. Prejdime ďalej.

Náhodné čísla

Definujme na kocke metódu hod (), ktorá nám vráti náhodné číslo od 1 do počtu stien. Je to veľmi jednoduché, metóda bude public (pôjde volať zvonku) a nebude mať žiadny parameter. Návratová hodnota bude typu int. Náhodné číslo získame tak, že na generátore zavoláme metódu nextInt (). Tá má 2 preťaženie:

  • nextInt (): Variant bez parametra vracia náhodné číslo v celom rozsahu dátového typu int;
  • nextInt (Do): Vracia nezáporné čísla menšie ako medza Do. random.nextInt (100) teda vráti číslo od 0 do 99.

Pre naše účely sa najlepšie hodia druhej preťaženie, píšeme teda:

/**
* Vykoná hod kostkou
* @return Číslo od 1 do počtu stěn
*/
public int hod() {
    return random.nextInt(pocetSten) + 1;
}

Dajte si pozor, aby ste netvorili generátor náhodných čísel v metóde, ktorá má náhodné číslo vracať, teda že by sa pre každé náhodné číslo vytvoril nový generátor. Výsledná čísla potom nie sú takmer náhodná alebo dokonca vôbec. Vždy si vytvorte jednu zdieľanú inštanciu generátora (napr. Do privátneho atribútu pomocou konstruktoru) a na tej potom metódu nextInt () volajte.

Prekrývanie metódy toString ()

Kocka je takmer hotová, ukážme si ešte jednu užitočnú metódu, ktorú ju pridáme a ktorú budeme hojne používať aj vo väčšine našich ďalších objektov. Reč je o metóde toString (), o ktorej sme sa už zmienili a ktorú obsahuje každý objekt, teda aj teraz naše kocka. Metóda je určená na to, aby vrátila tzv. Textovú reprezentáciu inštancie. Hodí sa vo všetkých prípadoch, kedy si inštanciu potrebujeme vypísať alebo s ňou pracovať ako s textom. Túto metódu majú napr. Aj čísla. Už vieme, že v Jave funguje implicitné konverzie, akonáhle teda budeme chcieť do konzoly vypísať objekt, Java na ňom zavolá metódu toString () a vypíše jej výstup. Ak si robíme vlastný triedu, mali by sme zvážiť, či sa nám takáto metóda nehodí. Nikdy by sme si nemali robiť vlastnú metódu, napr. Niečo ako vypis (), keď máme v Jave pripravenú cestu, ako toto riešiť. U kocky nemá toString () vyšší zmysel, ale u bojovníka bude určite vracať jeho meno. My si ju ku kocke rovnako pridáme, bude vypisovať, že sa jedná o kocku a vráti aj počet stien. Najprv si skúsme vypísať do konzoly našu inštanciu kocky:

    System.out.println(sestistenna);
import java.util.Random;

Do konzoly sa vypíše iba cesta k našej triede, teda tahovyboj.Kostka a tzv. Hash kód objektu. V mojom prípade bol vypísaný tento reťazec:

Konzolová aplikácia
[email protected]

Metódu už jednoducho nedefinujeme, ale pretože už exituje, musíme ju prepísať, resp. prekryť. Tým sa opäť nebudeme teraz podrobne zaoberať, však chcem, aby sme už teraz vedeli toString () používať. Pre prehľadné prekrytie označíme metódu anotácií @Override:

    /**
     * Vrací textovou reprezentaci kostky
     * @return Textová reprezentace kostky
     */
    @Override
    public String toString() {
    return String.format("Kostka s %s stěnami", pocetSten);
    }

Teraz opäť skúsime do konzoly vypísať priamo inštanciu kocky.

výstup:

Konzolová aplikácia
Kostka s 6 stěnami

Ešte si naše kocky vyskúšame. Skúsime si v programe s našimi dvoma kockami v cykloch hádzať a pozrieme sa, či fungujú tak, ako sa očakáva:

    // vytvoření
    Kostka sestistenna = new Kostka();
    Kostka desetistenna = new Kostka(10);

    // hod šestistěnnou
    System.out.println(sestistenna);
    for (int i = 0; i < 10; i++) {
        System.out.print(sestistenna.hod() + " ");
    }

    // hod desetistěnnou
    System.out.println("\n\n" + desetistenna);
    for (int i = 0; i < 10; i++) {
        System.out.print(desetistenna.hod() + " ");
    }

Výstup môže vyzerať nejako takto:

Konzolová aplikácia
Kostka s 6 stěnami
3 6 6 1 6 3 6 2 6 3

Kostka s 10 stěnami
5 9 9 2 10 4 9 3 10 5

Máme hotovú celkom peknú a nastaviteľnou triedu, ktorá reprezentuje hraciu kocku. Bude sa nám hodiť v našej aréne, ale môžete ju použiť aj kdekoľvek inde. Vidíme, ako OOP umožňuje znovupoužívat komponenty. V budúcej lekcii, Riešené úlohy k 3. lekcii OOP v Jave , si povieme niečo o odlišnostiach medzi referenčnými dátovými typmi (objekty) a typy hodnotovými (napr. Int). :)

V nasledujúcom cvičení Riešené úlohy k 3. lekcii OOP v Jave si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Stiahnuť

Stiahnuté 1868x (18.8 kB)
Aplikácia je vrátane zdrojových kódov v jazyku java

 

 

Článok pre vás napísal David Čápka
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sa informačné technológie naučil na Unicorn College - prestížnej súkromnej vysokej škole IT a ekonómie.
Predchádzajúci článok
Riešené úlohy k 2. lekcii OOP v Jave
Všetky články v sekcii
Objektovo orientované programovanie v Jave
Miniatúra
Nasledujúci článok
Riešené úlohy k 3. lekcii OOP v Jave
Aktivity (1)

 

 

Komentáre

Avatar
Jiří Satora:29.12.2018 16:56

Asi té metodě random. Četl jsem sice o javě knížku ale tohle tam nebylo. Taky je pravda že včera jsem byl už unavený a tolik jsem se na to nesoustředil, takže to bude asi i tím. :D

 
Odpovedať
29.12.2018 16:56
Avatar
Marcel Mares
Člen
Avatar
Marcel Mares:18.7.2019 11:41

Dobrý den, já mám takový nedůležitý dotaz, proč se v : return String.format("Kos­tka s %s stěnami", pocetSten) nepoužije místo %s radši %d, když pocetSten je int, to znamená že obsahuje jen celá čísla a v základech Java jsem se učil, že %s se používá pro řetězce String, %d pro celá čísla a %f pro desetinná čísla...předem děkuji za odpověď...

 
Odpovedať
18.7.2019 11:41
Avatar
Marcel Mares
Člen
Avatar
Odpovedá na Marcel Mares
Marcel Mares:19.7.2019 12:18

tak jsem si dosadil všechny 3 typy, v případě %f program proběhl, ale konzole vypsala chybu, že se nejedná o desetinná čísla, při %d vše proběhlo v pořádku a obě kostky generovaly 10 náhodných čísel, stejně jako za použití %s, znamená to tedy, že v javě dochází k automatické skryté konvezi celých čísel na řetězec pomocí String.valueOf, proč to ale také ta konverze nefunguje pro ty desetinné čísla ...

 
Odpovedať
19.7.2019 12:18
Avatar
Branislav Budoš:21. januára 10:16

Pekný deň prajem. Nejde mi do hlavy jedna vec a to:
musí byť vo finálnom programe v triede tento kód? Pretože podla mňa nie. A keď ho vymažem pokusne z triedy tak program pekne zbehne.

public int vratPocetSten() {
    return pocetSten;
    }

Ďakujem za odpoveď.

 
Odpovedať
21. januára 10:16
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovedá na Branislav Budoš
Petr Štechmüller:21. januára 11:47

Není dobré atribut nastavit na public, protože nebudeme chtít, aby nám někdo mohl již u vytvořené kostky měnit počet stěn. Přidáme do třídy tedy metodu vratPocetSten(), která nám vrátí hodnotu atributu pocetSten. Docílili jsme tím v podstatě toho, že je atribut read-only (atribut není viditelný a lze ho pouze číst metodou, změnit ho nelze).

Odpovedať
21. januára 11:47
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
Jan Béňa
Člen
Avatar
Jan Béňa:29. januára 18:21

Ahoj všem.
Asi bych potřeboval poradit. Snažil jsem se udělat program, který by vygeneroval mezi sebou dvě náhodné čísla a ty pak porovnal mezi sebou. Pokud by jedno bylo větší přičetl by +1 do proměnné třeba a v opačném případě do b. při rovnosti nic. Snažil jsem se to naprogramovat pomocí OOP a vše funguje jak jsem popsal. Ovšem když to dám do cyklu tak to vygeneruje jednou náhodně a pak to vezme první náhodné generování. Nějak nemůžu docílit toho, aby to vždycky vygenerovalo nové čísla do cyklu tak že mám vždy jen tři výsledky.(1:0,0:1 nebo 0:0). Myslím že pokud jsem došel sem, měl bych to zvládnout, akorát už se s tím lámu týden a pořád nic. Mohl by mi když tak nějaký zkušený borec dát nějaký tip aby mě nasměroval. Děkuji mockrát.

 
Odpovedať
29. januára 18:21
Avatar
Odpovedá na Jan Béňa
Matúš Olejník:29. januára 20:14

Ahoj, prihoď sem aj tvoj kód, so vstupom a požadovaným výstupom. Najlepšie by však bolo keby vytvoríš nové vlákno vo fóre pre Javu kde môžme viacej písať. Keď už sa s tým se#ieš týždeň nech to dokončíš :D

Odpovedať
29. januára 20:14
/* I am not sure why this works but it fixes the problem */
Avatar
Jan Béňa
Člen
Avatar
Odpovedá na Matúš Olejník
Jan Béňa:29. januára 20:17

Ok zkusím vytvořit vlákno na fóru.

 
Odpovedať
29. januára 20:17
Avatar
Gemy
Člen
Avatar
Gemy:25. marca 15:58

Jak dokáže stroj generovat náhodná čísla? Odkud je matematicky bere?

Odpovedať
25. marca 15:58
Peníze neznamenají úspěch.
Avatar
Alesh
Člen
Avatar
Odpovedá na Gemy
Alesh:25. marca 18:45

Nejedná se o náhodná čísla, ale o pseudonáhodná, protože jak správně tušíš, stroj nemůže "vymyslet" náhodné číslo. Laicky vysvětleno to funguje tak, že se vezme systémový čas, ten se vynásobí velkým prvočíslem a dále se to upravuje tak, aby vypadlo číslo z požadovaného intervalu.
Odborné vysvětlení najdeš na netu, třeba na Wikipedii, viz Generátor náhodných čísel.

Editované 25. marca 18:46
 
Odpovedať
25. marca 18:45
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!