Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

5. diel - Bojovník do arény

V minulej lekcii, Kvíz - Úvod, konštruktory, metódy, dátové typy v VB.NET OOP , sme si vysvetlili rozdiely medzi referenčnými a hodnotovými dátovými typy. Už teda vieme, ako fungujú referencie a ako môžeme s objektmi zaobchádzať. Bude sa nám to hodiť dnes aj nabudúce. Tento a budúci VB.NET tutoriál budú totiž venované dokončenie našej arény. Hracie kocku už máme, ešte nám chýba ďalšie 2 objekty: bojovník a samotná aréna. Dnes sa budeme venovať bojovníkovi. Najprv si popíšme, čo má bojovník vedieť, potom sa pustíme do písania kódu.

Atribúty

Bojovník sa bude nejako menovať a bude mať určitý počet hp (teda života, napr. 80hp). Budeme uchovávať jeho maximálnej život (bude sa líšiť u každej inštancie) a jeho súčasný život, teda napr. Zranený bojovník bude mať 40HP z 80tich. Bojovník má určitý útok a obranu, oboje vyjadrené opäť v hp. Keď bojovník útočí s útokom 20HP na druhého bojovníka s obranou 10hp, uberie mu 10hp života. Bojovník bude mať referenciu na inštanciu objektu Kostka. Pri útoku či obrane si vždy hodí kockou a k útoku / obrane pripočíta padlých číslo. (Samozrejme by mohol mať každý bojovník svoju kocku, ale chcel som sa priblížiť stolové podobe hry a ukázať, ako OOP naozaj simuluje realitu. Bojovníci teda budú zdieľať jednu inštanciu kocky.) Kockou dodáme hre prvok náhody, v realite sa jedná vlastne o šťastie, ako sa útok alebo obrana vydarí. Konečne budeme chcieť, aby bojovníci podávali správy o tom, čo sa deje, pretože inak by z toho užívateľ nič nemal. Správa bude vyzerať napr. "Zalgoren útočí s úderom za 25HP.". Správami sa zatiaľ nebudeme zaťažovať a vrátime sa k nim až nakoniec.

Už vieme, čo budeme robiť, poďme na to! :) K projektu aréna si pridajme triedu Bojovnik a dodajme ju patričné atribúty. Všetky budú privátne:

Class Bojovnik
    ''' <summary>
    ''' Jméno bojovníka
    ''' </summary>
    Private jmeno As String
    ''' <summary>
    ''' Život v HP
    ''' </summary>
    Private zivot As Integer
    ''' <summary>
    ''' Maximální zdraví
    ''' </summary>
    Private maxZivot As Integer
    ''' <summary>
    ''' Útok v HP
    ''' </summary>
    Private utok As Integer
    ''' <summary>
    ''' Obrana v HP
    ''' </summary>
    Private obrana As Integer
    ''' <summary>
    ''' Instance hrací kostky
    ''' </summary>
    Private kostka As Kostka
End Class

Komentáre môžete sklapnúť, aby nezaberali zbytočné miesto. Avšak je veľmi dobrý nápad je k atribútom písať. Trieda Kocka musí samozrejme byť v našom projekte.

Metódy

Poďme pre atribúty vytvoriť konštruktor, nebude to nič ťažké. Komentáre tu vynechám, vy si ich dopíšte podobne, ako u atribútov vyššie. Nebudem ich písať ani u ďalších metód, aby sa tutoriál zbytočne neroztahoval a zostal prehľadný.

Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka)
    Me.jmeno = jmeno
    Me.zivot = zivot
    Me.maxZivot = zivot
    Me.utok = utok
    Me.obrana = obrana
    Me.kostka = kostka
End Sub

Všimnite si, že maximálna zdravie si v konstruktoru odvodíme a nemáme na neho parameter v hlavičke metódy. Predpokladáme, že bojovník je pri vytvorení plne zdravý, stačí nám teda poznať iba jeho život a maximálny život bude rovnaký.

Prejdime k metódam, opäť sa najprv zamyslime nad tým, čo by mal bojovník vedieť. Začnime tým jednoduchším, budeme chcieť nejakú textovú reprezentáciu, aby sme mohli bojovníka vypísať. Prekryjeme teda metódu toString (), ktorá vráti meno bojovníka. Určite sa nám bude hodiť metóda, vracajúci či je bojovník nažive (teda typu Boolean). Aby to bolo trochu zaujímavejšie, budeme chcieť kresliť život bojovníka do konzoly, nebudeme teda písať, koľko má života, ale "vykreslíme" ho takto:

[#########    ]

Vyššie uvedený život by zodpovedal asi 70%. Doteraz spomínané metódy nepotrebovali žiadne parametre. Samotný útok a obranu nechajme na neskôr a poďme si implementovať toString (), nažive () a GrafickyZivot (). Začnime s toString (), tam nie je čo vymýšľať:

Public Overrides Function ToString() As String
    Return jmeno;
End Function

Teraz Implementujte metódu nažive (), opäť to nebude nič ťažké. Stačí skontrolovať, či je život väčšia ako 0 a podľa toho sa zachovať. Mohli by sme ju napísať napríklad takto:

Public Function Nazivu() As Boolean
    If zivot > 0 Then
        Return True
    Else
        Return False
    End If
End Function

Keďže aj samotný výraz (zivot> 0) je vlastne logická hodnota, môžeme vrátiť tú a kód sa značne zjednoduší:

Public Function Nazivu() As Boolean
    Return (zivot > 0)
End Function

Grafický život

Ako som sa už zmienil, metóda GrafickyZivot () bude umožňovať vykresliť ukazovateľ života v grafickej podobe. Už vieme, že z hľadiska objektového návrhu nie je vhodné, aby metóda objektu priamo vypisovala do konzoly (ak nie je k výpisu objekt určený), preto si znaky uložíme do reťazca a ten vrátime pre neskoršie vypísanie. Ukážeme si kód metódy a následne podrobne popíšeme:

Public Function GrafickyZivot() As String
    Dim s As String = "["
    Dim celkem As Integer = 20
    Dim pocet As Double = Math.Round((zivot / maxZivot) * celkem)
    If (pocet = 0) AndAlso (Nazivu()) Then
        pocet = 1
    End If
    For i As Integer = 0 To pocet - 1
        s += "#"
    Next
    s = s.PadRight(celkem + 1)
    s += "]"
    Return s
End Function

Pripravíme si reťazec s a vložíme doň úvodný znak "[". Určíme si celkovú dĺžku ukazovateľa života do premennej spolu (napr. 20). Teraz v podstate nepotrebujeme nič iné, než trojčlenka. Ak maxZivot zodpovedá celkom dielikov, zivot bude zodpovedať pocet dielkam. pocet je premenná s počtom dielikov aktuálneho zdravie.

Matematicky platí, že pocet = (zivot / maxZivot) * celkom;. My ešte doplníme zaokrúhlení na celé dieliky.

Mali by sme ošetriť prípad, kedy je život taký nízky, že nám vyjde na 0 dielikov, ale bojovník je stále nažive. V tom prípade vykreslíme 1 dielik, inak by to vyzeralo, že je už mŕtvy.

Ďalej stačí jednoducho for cyklom pripojiť k reťazcu s patričný počet znakov a doplniť ich medzerami do celkovej dĺžky. Doplnenie prevedieme pomocou PadRight () na dĺžku celkom + 1, kde ten znak naviac je úvodná znak "[". Pridáme koncový znak a reťazec vrátime.

Všetko si vyskúšame, prejdime do Program.cs a vytvorme si bojovníka (a kocku, pretože tu musíme konstruktoru bojovníka odovzdať). Následne výpisy, či je nažive a jeho život graficky:


Dim kostka As Kostka = New Kostka(10)
Dim bojovnik As Bojovnik = new Bojovnik("Zalgoren", 100, 20, 10, kostka)

Console.WriteLine("Bojovník: {0}", bojovnik) ' test ToString()
Console.WriteLine("Naživu: {0}", bojovnik.Nazivu()) ' test Nazivu()
Console.WriteLine("Život: {0}", bojovnik.GrafickyZivot()) ' test GrafickyZivot()
Class Bojovnik
    Private jmeno As String
    Private zivot As Integer
    Private maxZivot As Integer
    Private utok As Integer
    Private obrana As Integer
    Private kostka As Kostka

    Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka)
        Me.jmeno = jmeno
        Me.zivot = zivot
        Me.maxZivot = zivot
        Me.utok = utok
        Me.obrana = obrana
        Me.kostka = kostka
    End Sub

    Public Function Nazivu() As Boolean
        Return (zivot > 0)
    End Function

    Public Function GrafickyZivot() As String
        Dim s As String = "["
        Dim celkem As Integer = 20
        Dim pocet As Double = Math.Round((zivot / maxZivot) * celkem)
        If (pocet = 0) AndAlso (Nazivu()) Then
            pocet = 1
        End If
        For i As Integer = 0 To pocet - 1
            s += "#"
        Next
        s = s.PadRight(celkem + 1)
        s += "]"
        Return s
    End Function

    Public Overrides Function ToString() As String
        Return jmeno
    End Function

End Class
Konzolová aplikácia
Bojovník: Zalgoren
Naživu: True
Život: [####################]

Boj

Dostávame sa k samotnému boju. Implementujeme metódy pre útok a obranu.

Obrana

Začnime obranou. Metóda BRANS () bude umožňovať brániť sa úderu, ktorého sila bude odovzdaná metóde ako parameter. Metódu si opäť ukážeme a potom popíšeme:

Public Sub BranSe(uder As Integer)
    Dim zraneni As Integer = uder - (obrana + kostka.hod())
    If zraneni > 0 Then
        zivot -= zraneni
        If zivot <= 0 Then
            zivot = 0
        End If
    End If
End Sub

Najprv spočítame skutočné zranenia a to tak, že z útoku nepriateľa odpočítame našu obranu zvýšenú o číslo, ktoré padlo na hracej kocke. Ak sme zranenia celej neodrazil (zranenie> 0), budeme znižovať náš život. Táto podmienka je dôležitá, keby sme zranenia odrazili a bolo napr. -2, bez podmienky by sa život zvýšil. Po znížení života skontrolujeme, či nie je v zápornej hodnote a prípadne ho dorovnáme na nulu.

Útok

Metóda Útočia () bude brať ako parameter inštanciu bojovníka, na ktorého sa útočí. To preto, aby sme na ňom mohli zavolať metódu BRANS (), ktorá na náš útok zareaguje a zmenší protivníkov život. Tu vidíme výhody referencií vo Visual Basic .NET, môžeme si inštancie jednoducho odovzdávať a volať na nich metódy, bez toho aby došlo k ich skopírovanie. Ako prvý vypočítame úder, podobne ako pri obrane, úder bude náš útok + hodnota z hracej kocky. Na súperovi následne zavoláme metódu BRANS () s hodnotou úderu:

Public Sub Utoc(souper As Bojovnik)
    Dim uder As Integer = utok + kostka.hod()
    souper.BranSe(uder)
End Sub

To by sme mali, poďme si skúsiť v našom ukážkovom programe zaútočiť a potom znova vykresliť život. Pre jednoduchosť nemusíme zakladať ďalšieho bojovníka, ale môžeme zaútočiť sami na seba:


Dim kostka As Kostka = New Kostka(10)
Dim bojovnik As Bojovnik = New Bojovnik("Zalgoren", 100, 20, 10, kostka)

Console.WriteLine("Bojovník: {0}", bojovnik) ' test ToString()
Console.WriteLine("Naživu: {0}", bojovnik.nazivu())    ' test Nazivu()
Console.WriteLine("Život: {0}", bojovnik.GrafickyZivot()) ' test GrafickyZivot()

bojovnik.Utoc(bojovnik) ' test útoku
Console.WriteLine("Život po útoku: {0}", bojovnik.GrafickyZivot())

Console.ReadKey()
Class Bojovnik
    Private jmeno As String
    Private zivot As Integer
    Private maxZivot As Integer
    Private utok As Integer
    Private obrana As Integer
    Private kostka As Kostka

    Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka)
        Me.jmeno = jmeno
        Me.zivot = zivot
        Me.maxZivot = zivot
        Me.utok = utok
        Me.obrana = obrana
        Me.kostka = kostka
    End Sub

    Public Function Nazivu() As Boolean
        Return (zivot > 0)
    End Function

    Public Function GrafickyZivot() As String
        Dim s As String = "["
        Dim celkem As Integer = 20
        Dim pocet As Double = Math.Round((zivot / maxZivot) * celkem)
        If (pocet = 0) AndAlso (Nazivu()) Then
            pocet = 1
        End If
        For i As Integer = 0 To pocet - 1
            s += "#"
        Next
        s = s.PadRight(celkem + 1)
        s += "]"
        Return s
    End Function

    Public Sub BranSe(uder As Integer)
        Dim zraneni As Integer = uder - (obrana + kostka.hod())
        If zraneni > 0 Then
            zivot -= zraneni
            If zivot <= 0 Then
                zivot = 0
            End If
        End If
    End Sub

    Public Sub Utoc(souper As Bojovnik)
        Dim uder As Integer = utok + kostka.hod()
        souper.BranSe(uder)
    End Sub

    Public Overrides Function ToString() As String
        Return jmeno
    End Function

End Class
Konzolová aplikácia
Bojovník: Zalgoren
Naživu: True
Život: [####################]
Život po útoku: [##################  ]

Zdá sa, že všetko funguje, ako má. Prejdime k poslednému bodu dnešného tutoriálu a to k správam.

Správy

Ako už bolo povedané, o útokoch a obrane budeme užívateľa informovať výpisom na konzolu. Výpis nebude vykonávať samotná trieda Bojovnik, tá bude len vracať správy ako textové reťazce. Jedna možnosť by bola nastaviť návratový typ metód útočí () a BRANS () na String a pri ich volanie vrátiť aj správu. Problém by však nastal v prípade, keď by sme chceli získať správu od metódy, ktorá už niečo vracia. Metóda samozrejme nemôže jednoducho vrátiť 2 veci.

Poďme na vec univerzálnejšie, správu budeme ukladať do privátnej premennej sprava a urobíme metódy pre jej uloženie a vrátenie. Samozrejme by sme mohli urobiť premennú verejnú, ale nie je tu dôvod, prečo umožniť zvonku zápis do správy a tiež by skladanie zložitejšie správy vnútri triedy mohlo byť niekedy problematické.

K atribútom triedy teda pridáme:

Private zprava As String

Teraz si vytvoríme dve metódy. Privátne NastavZpravu (), ktorá berie ako parameter text správy a slúži na interné účely triedy, kde nastaví správu do privátnej premennej:

Private Sub NastavZpravu(zprava As String)
    Me.zprava = zprava
End Sub

Nič zložité. Podobne jednoduchá bude verejná metóda pre navrátenie správy:

Public Function VratPosledniZpravu() As String
    Return Me.zprava
End Function

O prácu so správami obohatíme naše metódy útočí () a BRANS (), teraz budú vyzerať takto:

Public Sub Utoc(souper As Bojovnik)
    Dim uder As Integer = utok + kostka.hod()
    NastavZpravu(String.Format("{0} útočí s úderem za {1} hp", jmeno, uder))
    souper.BranSe(uder)
End Sub

Public Sub BranSe(uder As Integer)
    Dim zraneni As Integer = uder - (obrana + kostka.hod())
    If zraneni > 0 Then
        zivot -= zraneni
        Dim zprava = String.Format("{0} utrpěl poškození {1} hp", jmeno, zraneni)
        If zivot <= 0 Then
            zivot = 0
            zprava &= " a zemřel"
        Else
            zprava = String.Format("{0} odrazil útok", jmeno)
        End If
        NastavZpravu(zprava)
    End If
End Sub

Všetko si opäť vyskúšame, tentoraz už vytvoríme druhého bojovníka:

Dim kostka As New Kostka(10)
Dim bojovnik As New Bojovnik("Zalgoren", 100, 20, 10, kostka)

Console.WriteLine("Život: {0}", bojovnik.GrafickyZivot())
' test GrafickyZivot();
' útok na našeho bojovníka
Dim souper As New Bojovnik("Shadow", 60, 18, 15, kostka)
souper.Utoc(bojovnik)
Console.WriteLine(souper.VratPosledniZpravu())
Console.WriteLine(bojovnik.VratPosledniZpravu())

Console.WriteLine("Život: {0}", bojovnik.GrafickyZivot())

Console.ReadKey()
Class Bojovnik
    Private jmeno As String
    Private zivot As Integer
    Private maxZivot As Integer
    Private utok As Integer
    Private obrana As Integer
    Private kostka As Kostka
    Private zprava As String

    Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka)
        Me.jmeno = jmeno
        Me.zivot = zivot
        Me.maxZivot = zivot
        Me.utok = utok
        Me.obrana = obrana
        Me.kostka = kostka
    End Sub

    Public Function Nazivu() As Boolean
        Return (zivot > 0)
    End Function

    Public Function GrafickyZivot() As String
        Dim s As String = "["
        Dim celkem As Integer = 20
        Dim pocet As Double = Math.Round((zivot / maxZivot) * celkem)
        If (pocet = 0) AndAlso (Nazivu()) Then
            pocet = 1
        End If
        For i As Integer = 0 To pocet - 1
            s += "#"
        Next
        s = s.PadRight(celkem + 1)
        s += "]"
        Return s
    End Function

    Public Sub Utoc(souper As Bojovnik)
        Dim uder As Integer = utok + kostka.hod()
        NastavZpravu(String.Format("{0} útočí s úderem za {1} hp", jmeno, uder))
        souper.BranSe(uder)
    End Sub

    Public Sub BranSe(uder As Integer)
        Dim zraneni As Integer = uder - (obrana + kostka.hod())
        If zraneni > 0 Then
            zivot -= zraneni
            Dim zprava = String.Format("{0} utrpěl poškození {1} hp", jmeno, zraneni)
            If zivot <= 0 Then
                zivot = 0
                zprava &= " a zemřel"
            Else
                zprava = String.Format("{0} odrazil útok", jmeno)
            End If
            NastavZpravu(zprava)
        End If
    End Sub

    Private Sub NastavZpravu(zprava As String)
        Me.zprava = zprava
    End Sub

    Public Function VratPosledniZpravu() As String
        Return Me.zprava
    End Function

    Public Overrides Function ToString() As String
        Return jmeno
    End Function

End Class

Konzolová aplikácia
Život: [####################]
Shadow útočí s úderem za 24 hp
Zalgoren utrpěl poškození 10 hp
Život: [##################  ]

Máme kocku i bojovníka, teraz už chýba len aréna. Tú si vytvoríme hneď v nasledujúcej lekcii, VB.NET - Aréna s bojovníkmi .


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

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

 

Predchádzajúci článok
Kvíz - Úvod, konštruktory, metódy, dátové typy v VB.NET OOP
Všetky články v sekcii
Objektovo orientované programovanie vo Visual Basic .NET
Preskočiť článok
(neodporúčame)
VB.NET - Aréna s bojovníkmi
Článok pre vás napísal Michal Žůrek - misaz
Avatar
Užívateľské hodnotenie:
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.
Aktivity