3. diel - Hracia kocka vo VB.NET - konštruktory a náhodné čísla

Unicorn College Tento obsah je dostupný zadarmo v rámci projektu IT ľuďom. Vydávanie, hosting a aktualizácie umožňujú jeho sponzori.

V minulej lekcii, Prvý objektová aplikácie vo VB.NET - Hello object world , 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. Dnes vo VB.NET tutoriálu začneme pracovať na sľúbené aréne, v ktorej budú proti sebe bojovať dvaja bojovníci. Boj bude ťahový (napřeskáč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ú konzolovú aplikáciu a pomenujte ju Arena. 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 .NET framework, ktorý na tieto účely obsahuje triedu Random. Naša trieda bude mať teraz 2 atribúty: pocetSten typu Integer a random typu Random, kde bude generátor náhodných čísel. 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 VB.NET 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:

''' <summary>
''' Třída reprezentuje hrací kostku
''' </summary>
Public Class Kostka
    ''' <summary>
    ''' Generátor náhodných čísel
    ''' </summary>
    Private random As Random
    ''' <summary>
    ''' Počet stěn kostky
    ''' </summary>
    Private pocetSten As Integer
End Class

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 Module1.vb vytvorili takto:

Dim kostka As Kostka = New Kostka()

Práve Kocka () je konštruktor. Pretože v našej triede žiadny nie je, VB.NET 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 musí mať meno New. V konstruktoru nastavíme počet stien na pevnú hodnotu a vytvoríme inštanciu triedy Random. Konštruktor bude vyzerať nasledovne:

Public Sub New()
    pocetSten = 6
    random = New Random()
End Sub

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). VB.NET má na tento účel ešte ďalšie konštrukcie, ale tým sa zatiaľ nebudeme zaoberať. Nová metóda bude vyzerať asi takto:

''' <summary>
''' Vrátí počet stěn kostky
''' </summary>
''' <returns>Počet stěn kostky</returns>
Public Function VratPocetSten() As Integer
    Return pocetSten
End Function

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

Dim kostka As Kostka = New Kostka()
Console.WriteLine(kostka.VratPocetSten())
Console.ReadKey()

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 Sub New(aPocetSten As Integer)
    pocetSten = aPocetSten
    random = New Random()
End Sub

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 VB.NET by to zmiatlo. Vráťme sa k Module1.vb a zadajte tento parameter do konstruktoru:

Dim kostka As Kostka = New Kostka(10) ' v tuto chvíli se zavolá konstruktor s par. 10
Console.WriteLine(kostka.VratPocetSten())
Console.ReadKey()
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. VB.NET 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 Sub New()
    pocetSten = 6
    random = New Random()
End Sub

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

Dim sestistenna As Kostka = New Kostka()
Dim desetistenna As Kostka = New Kostka(10)
Console.WriteLine(sestistenna.VratPocetSten())
Console.WriteLine(desetistenna.VratPocetSten())
Console.ReadKey()

výstup:

Konzolová aplikácia
6
10

VB.NET 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 New (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. Visual Studio nám preťaženie pri metódach prehľadne ponúka (vo chvíli, keď za názov metódy napíšeme ľavú zátvorku), variantmi metódy si môžeme listovať pomocou šípok. Zopakujem že tohto pomocníka nazval Microsoft IntelliSense. V ponuke vidíme naše 2 konštruktory:

Pomoc IntelliSense k preťaženým metódam v C #

Mnoho metód v .NET má hneď niekoľko preťaženie, skúste sa pozrieť napr. Na metódu Remove () na STRING. Je dobré si u metód prejsť ich preťaženie, aby ste neprogramoval niečo, čo už niekto urobil pred vami. Napríklad metóda WriteLine (), ktorú poznáte pre vypisovanie do konzoly, má hneď 18 variantov.

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 Sub New(pocetSten As Integer)
    pocetSten = pocetSten
    random = New Random()
End Sub

VB.NET nevie, ktorú z premenných myslíme, či parameter alebo atribút. V tomto prípade priraďujeme do parametra znova ten istý parameter. VS 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 Me. Využitie si môžeme predstaviť napr. Keby kocka mala metódu DejHraci (Hrac hrac) a tam by volala hrac.SeberKostku (Me). Tu by sme hráči pomocou Me 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 Sub New(PocetSten As Integer)
    Me.pocetSten = PocetSten
    random = New Random()
End Sub

Pomocou Me sme špecifikovali, že ľavá premenná pocetSten náleží inštanciu, pravú VB.NET 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 Integer. Náhodné číslo získame tak, že na generátore zavoláme metódu Next (). Tá má niekoľko preťaženie:

  • Next (): Variant bez parametra vracia náhodné číslo v celom rozsahu dátového typu int;
  • Next (Do): Vracia nezáporné čísla menšie ako medza Do. random.Next (100) teda vráti číslo od 0 do 99.
  • Next (Od, Do): Vráti náhodné číslo v zadanej medzi, pričom Od do intervalu patrí a Do už nie. Teda náhodné číslo od 1 do 100 by bolo random.Next (1, 101);

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

''' <summary>
''' Vykoná hod kostkou
''' </summary>
''' <returns>Číslo od 1 do počtu stěn</returns>
Public Function Hod() As Integer
    Return random.Next(1, pocetSten + 1)
End Function

Dajte si pozor, aby ste netvorili náhodný generátor 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 Next () 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 vo VB.NET funguje implicitné konverzie, akonáhle teda budeme chcieť do konzoly vypísať číslo alebo ktorýkoľvek iný objekt, VB.NET 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 VB.NET 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:

Console.WriteLine(sestistenna)

Do konzoly sa vypíše iba cesta k našej triede, teda Arena.Kostka. Metódu nemôžeme len tak definovať, pretože je už definovaná (v ďalších dieloch zistíme prečo). Musíme ju teda prepísať, resp. prekryť. Tým sa opäť nebudeme teraz podrobne zaoberať, však chcem, aby sme už teraz vedeli toString () používať. K prekrytie použijeme kľúčové slovo Overrides:

''' <summary>
''' Vrací textovou reprezentaci kostky
''' </summary>
''' <returns>Textová prezentace kostky</returns>
Public Overrides Function ToString() As String
    Return String.Format("Kostka s {0} stěnami", pocetSten)
End Function

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í
Dim sestistenna As Kostka = New Kostka
Dim desetistenna As Kostka = New Kostka(10)
' hod šestistěnou
Console.WriteLine(sestistenna)
For i As Integer = 0 To 9
    Console.Write(sestistenna.hod() & " ")
Next

' hod desetistenou
Console.WriteLine(vbCrLf)
Console.WriteLine(desetistenna)
For i As Integer = 0 To 9
    Console.Write(desetistenna.hod() & " ")
Next
Console.ReadKey()
' Pokud budete spouštět kód přes náš online kompiler, výsledek
' je udržován v mezipaměti a budou padat stále ta samá čísla.
' S jakoukoli změnou v kódu (např. i přidání komentáře) vyvoláte
' novou kompilace a tedy i vygenerování nových čísel.
Public Class Kostka
    Private random As Random
    Private pocetSten As Integer

    Public Sub New()
        pocetSten = 6
        random = New Random()
    End Sub

    Public Sub New(PocetSten As Integer)
        Me.pocetSten = PocetSten
        random = New Random()
    End Sub

    Public Function Hod() As Integer
        Return random.Next(1, pocetSten + 1)
    End Function

    Public Function VratPocetSten() As Integer
        Return pocetSten
    End Function

    Public Overrides Function ToString() As String
        Return String.Format("Kostka s {0} stěnami", pocetSten)
    End Function

End Class

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, Cvičenia k 3. lekcii OOP v VB .NET , si povieme niečo o odlišnostiach medzi referenčnými dátovými typmi (objekty) a hodnotovými (napr. Integer). :)


 

Stiahnuť

Stiahnuté 322x (63.4 kB)
Aplikácia je vrátane zdrojových kódov v jazyku VB

 

 

Článok pre vás napísal Michal Žůrek - misaz
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Predchádzajúci článok
Prvý objektová aplikácie vo VB.NET - Hello object world
Všetky články v sekcii
Objektovo orientované programovanie vo Visual Basic .NET
Miniatúra
Nasledujúci článok
Cvičenia k 3. lekcii OOP v VB .NET
Aktivity (1)

 

 

Komentáre

Avatar
Jaroslav Trojan
Redaktor
Avatar
Jaroslav Trojan:28.6.2016 10:23

Vytvořil jsem si 14ti stěn. Z krychle s 8 vrcholy ...do každého vrcholu vnořit stěnu- 8 stěn + 6 stěn původní krychle a je 14ti stěn. Kostka má víc možností.

Odpovedať
28.6.2016 10:23
statik
Avatar
Jaroslav Trojan
Redaktor
Avatar
Jaroslav Trojan:3.7.2016 11:44

kód pro Kostku jsem zachoval.
Kód v Modele1 je upraven takto:

'budeme kostkami házet
Dim krychle As Kostka=New Kostka()
Dim ctrnactisten As Kostka=New Kostka(14)
'hod krychlí
Console.Write­Line("Kostka s {0} stěnami",krychle­.VratPocetSten)
For i= 1 To 9
Console.Write(krychle­.hod() & " ")
Next
Console.WriteLine()
Console.WriteLine()

'hod 14ti stěnem
Console.Write­Line("Kostka s {0} stěnami",ctrnac­tisten.VratPo­cetSten)
For i=1 To 9
Console.Write(ctrnac­tisten.hod() & " ")
Next
Console.ReadKey()
......
.....
u větší kostky je více možností pádu čísel

Odpovedať
3.7.2016 11:44
statik
Avatar
Tomáš Slanina:24.7.2017 10:05

Tady jde spíš o to jaké číslo tě napadne můžeš si vytvořit třeba stostěn aby tam bylo víc možností :D

 
Odpovedať
24.7.2017 10:05
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
Jan Záruba
Člen
Avatar
Jan Záruba:9.12.2018 20:39

Mám pár dotazů:

  1. když do třídy píšeme 2x metodu Public Sub New(), tak to je jen z důvodu, abychom měli pevně stanovený počet stěn a nebo počet stěn variabilní? Protože když definuji počet stěn přímo u proměnné na začátku, tak to funguje i bez nich. Samozřejmě jen pevně stanovený počet stěn.
  2. proč definujeme do této metody proměnnou random=New Random()? Bez toho to také funguje

Děkuji za vysvětlení

 
Odpovedať
9.12.2018 20:39
Avatar
Odpovedá na Jan Záruba
Michal Žůrek - misaz:9.12.2018 22:09

1.) píšeme to proto že chceme mít 2 varianty jak vytvořit kostku. Tu standardní 6 bokou a pak chceme mít možnost vytvořit nějakou speciální kostku, která bude mít libovolný počet stěn, takový jaký si tam uživatel zadá.

2.) bez toho to nejde. Je to objekt, který budeme používat ke generování náhodných čísel.

 
Odpovedať
9.12.2018 22:09
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.

Zobrazené 5 správy z 5.