Lekce 8 - Aréna s mágem (dědičnost a polymorfismus)
V minulé lekci, Dědičnost a polymorfismus, jsme si vysvětlili dědičnost a polymorfismus.
Na dnešní VB.NET tutoriál máme slíbeno, že si je vyzkoušíme v praxi.
Bude to opět na naší aréně, kde z bojovníka oddědíme mága. Tento
tutoriál již patří k těm náročnějším a bude tomu tak i u dalších.
Proto si průběžně procvičujte práci s objekty, zkoušejte si naše
cvičení a také vymýšlejte nějaké své aplikace, abyste si zažili
základní věci. To, že je tu přítomen celý seriál neznamená, že ho
celý najednou přečtete a pochopíte Snažte se programovat průběžně.

Než začneme něco psát, shodněme se na tom, co by měl mág umět. Mág bude fungovat stejně, jako bojovník. Kromě života bude mít však i manu. Zpočátku bude mana plná. V případě plné many může mág vykonat magický útok, který bude mít pravděpodobně vyšší damage, než útok normální (ale samozřejmě záleží na tom, jak si ho nastavíme). Tento útok manu vybije na 0. Každé kolo se bude mana zvyšovat o 10 a mág bude podnikat jen běžný útok. Jakmile se mana zcela doplní, opět bude moci magický útok použít. Mana bude zobrazena grafickým ukazatelem, stejně jako život.
Vytvoříme tedy třídu Mag.vb, zdědíme ji z Bojovnik a dodáme ji atributy, které chceme oproti bojovníkovi navíc. Bude tedy vypadat takto (opět si ji okomentujte):
Class Mag Inherits Bojovnik Private mana As Integer Private maxMana As Integer Private magickyUtok As Integer End Class
V mágovi nemáme zatím přístup ke všem proměnným, protože jsou v bojovníkovi nastavené jako privátní. Musíme třídu Bojovnik lehce upravit. Změníme modifikátory Private u atributů na Protected. Budeme potřebovat jen kostka a jmeno, ale klidně nastavíme jako Protected všechny atributy charakteru, protože se v budoucnu mohou hodit, kdybychom se rozhodli oddědit další typy bojovníků. Naopak atribut zprava není vhodné nastavovat jako Protected, protože nesouvisí s bojovníkem, ale s nějakou vnitřní logikou třídy. Třída tedy bude vypadat nějak takto:
Protected jmeno As String Protected zivot As Integer Protected maxZivot As Integer Protected utok As Integer Protected obrana As Integer Protected kostka As Kostka Private zprava As String ...
Přejděme ke konstruktoru.
Konstruktor potomka
VB.NET nedědí konstruktory! Je to pravděpodobně z toho důvodu, že předpokládá, že potomek bude mít navíc nějaké atributy a původní konstruktor by u něj byl na škodu. To je i náš případ, protože konstruktor mága bude brát oproti tomu z bojovníka navíc 2 parametry (mana a magický útok).
Definujeme si tedy konstruktor v potomkovi, který bere parametry potřebné pro vytvoření bojovníka a několik parametrů navíc pro mága.
O potomků je nutné vždy volat konstruktor předka, je to z toho důvodu, že bez volání konstruktoru nemusí být instance správně inicializovaná. Konstruktor předka nevoláme pouze v případě, že žádný nemá. Náš konstruktor musí mít samozřejmě všechny parametry potřebné pro předka plus ty nové, co má navíc potomek. Některé potom předáme předkovi a některé si zpracujeme sami. Konstruktor předka se vykoná před naším konstruktorem.
V VB.NET existuje klíčové slovo MyBase, které je podobné námi již známému Me. Narozdíl od Me, které odkazuje na konkrétní instanci třídy, MyBase odkazuje na předka. My tedy můžeme zavolat konstruktor předka s danými parametry a poté vykonat navíc inicializaci pro mága.
Konstruktor mága bude tedy vypadat takto:
Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka, mana As Integer, magickyUtok As Integer) MyBase.New(jmeno, zivot, utok, obrana, kostka) Me.mana = mana Me.maxMana = mana Me.magickyUtok = magickyUtok End Sub
Pozn.: Stejně můžeme volat i jiný konstruktor v té samé třídě (ne předka), jen místo MyBase použijeme Me.
Přesuňme se nyní do Module1.vb a druhého bojovníka (Shadow) změňme na mága, např. takto:
Dim gandalf As Bojovnik = New Mag("Gandalf", 60, 15, 12, kostka, 30, 45)
Změnu samozřejmě musíme udělat i v řádku, kde bojovníka do arény vkládáme. Všimněte si, že mága ukládáme do proměnné typu Bojovnik. Nic nám v tom nebrání, protože bojovník je jeho předek. Stejně tak si můžeme typ proměnné změnit na Mag. Když aplikaci nyní spustíme, bude fungovat úplně stejně, jako předtím. Mág vše dědí z bojovníka a zatím tedy funguje jako bojovník.
Polymorfismus a přepisování metod
Bylo by výhodné, kdyby objekt Arena mohl s mágem pracovat stejným způsobem jako s bojovníkem. My již víme, že takovémuto mechanismu říkáme polymorfismus. Aréna zavolá na objektu metodu Utoc() se soupeřem v parametru. Nestará se o to, jestli bude útok vykonávat bojovník nebo mág, bude s nimi pracovat stejně. U mága si tedy přepíšeme metodu Utoc() z předka. Přepíšeme zděděnou metodu tak, aby útok pracoval s manou, hlavička metody však zůstane stejná.
Abychom mohli nějakou metodu přepsat, musí být v předkovi označena jako přepisovatelná (v některých jazycích se takovým metodám říká virtuální). Nehledejte za tím žádnou vědu, jednoduše pomocí klíčového slova Overridable VB.NET sdělíme, že si přejeme, aby potomek mohl tuto metodu přepsat. Hlavičku metody v Bojovnik.vb tedy změníme na:
Public Overridable Sub Utoc(souper As Bojovnik)
Když jsme u metod, budeme ještě jistě používat metodu NastavZpravu(), ta je však privátní. Označme ji jako Protected:
Protected Sub NastavZpravu(zprava As String)
Pozn. Při návrhu bojovníka jsme samozřejmě měli myslet na to, že
se z něj bude dědit a již označit vhodné atributy a metody jako Protected,
případně metody jako přepisovatelné. Klíčovým slovem Overridable je
označena metoda, kterou lze v potomkovi přepsat, jinak to není možné. V
tutoriálu k bojovníkovi jsem vás tím však nechtěl zbytečně zatěžovat,
proto musíme modifikátory změnit až teď, kdy jim rozumíme
Metoda Utoc() v bojovníkovi bude tedy Public Overridable. Nyní se vraťme do potomka a pojďme ji přepsat. Metodu normálně definujeme v Mag.vb tak, jak jsme zvyklí. Za modifikátorem Public však ještě použijeme klíčové slovo Overrides, které značí, že si jsme vědomi toho, že se metoda zdědila, ale přejeme si změnit její chování.
Public Overrides Sub Utoc(souper As Bojovnik)
Podobně jsme přepisovali metodu ToString() u našich objektů, každý objekt v VB.NET je totiž odděděný od System.Object, který obsahuje 4 metody, jedna z nich je i ToString(). Při její implementaci tedy musíme použít Overrides.
Chování metody Utoc() nebude nijak složité. Podle hodnoty many buď provedeme běžný útok nebo útok magický. Hodnotu many potom buď zvýšíme o 10 nebo naopak snížíme na 0 v případě magického útoku.
Public Overrides Sub Utoc(souper As Bojovnik) Dim uder As Integer = 0 ' Mana není naplněna If mana < maxMana Then mana += 10 If mana > maxMana Then mana = maxMana End If uder = utok + kostka.hod() NastavZpravu([String].Format("{0} útočí s úderem za {1} hp", jmeno, uder)) Else ' Magický útok uder = magickyUtok + kostka.hod() NastavZpravu([String].Format("{0} použil magii za {1} hp", jmeno, uder)) mana = 0 End If souper.BranSe(uder) End Sub
Kód je asi srozumitelný. Všimněte si omezení many na maxMana, může se nám totiž stát, že tuto hodnotu přesáhneme, když ji zvyšujeme o 10. Když se nad kódem zamyslíme, tak útok výše v podstatě vykonává původní metoda Utoc(). Jistě by bylo přínosné zavolat podobu metody na předkovi místo toho, abychom chování opisovali. K tomu opět použijeme MyBase:
Class Mag Inherits Bojovnik Private mana As Integer Private maxMana As Integer Private magickyUtok As Integer Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka, mana As Integer, magickyUtok As Integer) MyBase.New(jmeno, zivot, utok, obrana, kostka) Me.mana = mana Me.maxMana = mana Me.magickyUtok = magickyUtok End Sub Public Overrides Sub Utoc(souper As Bojovnik) ' Mana není naplněna If mana < maxMana Then mana += 10 If mana > maxMana Then mana = maxMana End If MyBase.Utoc(souper) Else ' Magický útok Dim uder As Integer = magickyUtok + kostka.hod() NastavZpravu([String].Format("{0} použil magii za {1} hp", jmeno, uder)) souper.BranSe(uder) mana = 0 End If End Sub End Class
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
Class Bojovnik Protected jmeno As String Protected zivot As Integer Protected maxZivot As Integer Protected utok As Integer Protected obrana As Integer Protected 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 Overridable 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()) Dim zprava As String If zraneni > 0 Then zivot -= zraneni zprava = String.Format("{0} utrpěl poškození {1} hp", jmeno, zraneni) If zivot <= 0 Then zivot = 0 zprava &= " a zemřel" End If Else zprava = String.Format("{0} odrazil útok", jmeno) End If NastavZpravu(zprava) End Sub Protected 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
Class Arena Private bojovnik1 As Bojovnik Private bojovnik2 As Bojovnik Private kostka As Kostka Public Sub New(bojovnik1 As Bojovnik, bojovnik2 As Bojovnik, kostka As Kostka) Me.bojovnik1 = bojovnik1 Me.bojovnik2 = bojovnik2 Me.kostka = kostka End Sub Private Sub Vykresli() Console.Clear() Console.WriteLine("-------------- Aréna -------------- " & vbCrLf) Console.WriteLine("Zdraví bojovníků: " & vbCrLf) Console.WriteLine("{0} {1}", bojovnik1, bojovnik1.GrafickyZivot()) Console.WriteLine("{0} {1}", bojovnik2, bojovnik2.GrafickyZivot()) End Sub Private Sub VypisZpravu(zprava As String) Console.WriteLine(zprava) Thread.Sleep(500) End Sub Public Sub Zapas() ' původní pořadí Dim b1 As Bojovnik = bojovnik1 Dim b2 As Bojovnik = bojovnik2 Console.WriteLine("Vítejte v aréně!") Console.WriteLine("Dnes se utkají {0} s {1}! " & vbCrLf, bojovnik1, bojovnik2) ' prohození bojovníků Dim zacinaBojovnik2 As Boolean = (kostka.hod() <= kostka.VratPocetSten() / 2) If zacinaBojovnik2 Then b1 = bojovnik2 b2 = bojovnik1 End If Console.WriteLine("Začínat bude bojovník {0}!" & vbCrLf & "Zápas může začít...", b1) Console.ReadKey() ' cyklus s bojem While b1.Nazivu() And b2.Nazivu() b1.Utoc(b2) Vykresli() VypisZpravu(b1.VratPosledniZpravu()) ' zpráva o útoku VypisZpravu(b2.VratPosledniZpravu()) ' zpráva o obraně If b2.Nazivu Then b2.Utoc(b1) Vykresli() VypisZpravu(b2.VratPosledniZpravu()) ' zpráva o útoku VypisZpravu(b1.VratPosledniZpravu()) ' zpráva o obraně End If Console.WriteLine() End While End Sub End Class
{VBNET_CONSOLE} ' vytvoření objektů Dim kostka As New Kostka(10) Dim zalgoren As New Bojovnik("Zalgoren", 100, 20, 10, kostka) Dim gandalf As Bojovnik = New Mag("Gandalf", 60, 15, 12, kostka, 30, 45) Dim arena As New Arena(zalgoren, gandalf, kostka) ' zápas arena.Zapas() Console.ReadKey() {/VBNET_CONSOLE}
Opět vidíme, jak můžeme znovupoužívat kód. S dědičností je spojeno opravdu mnoho technik, jak si ušetřit práci. V našem případě to ušetří několik řádků, ale u většího projektu by to mohlo mít obrovský význam.
Aplikace nyní funguje tak, jak má.
Konzolová aplikace
-------------- Aréna --------------
Zdraví bojovníků:
Zalgoren [############# ]
Gandalf [################# ]
Gandalf použil magii za 52 hp
Zalgoren utrpěl poškození 36 hp
Aréna nás však neinformuje o maně mága, pojďme to napravit. Přidáme mágovi veřejnou metodu GrafickaMana(), která bude obdobně jako u života vracet String s grafickým ukazatelem many.
Abychom nemuseli logiku se složením ukazatele psát dvakrát, upravíme metodu GrafickyZivot() v Bojovnik.vb. Připomeňme si, jak vypadá:
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
Vidíme, že není kromě proměnných zivot a maxZivot na životě nijak závislá. Metodu přejmenujeme na GrafickyUkazatel a dáme ji 2 parametry: aktuální hodnotu a maximální hodnotu. zivot a maxZivot v těle metody poté nahradíme za aktualni a maximalni. Modifikátor bude Protected, abychom metodu mohli v potomkovi použít:
Protected Function GrafickyUkazatel(aktualni As Integer, maximalni As Integer) As String Dim s As String = "[" Dim celkem As Integer = 20 Dim pocet As Double = Math.Round((aktualni / maximalni) * 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
Metodu GrafickyZivot() v Bojovnik.cs naimplementujeme znovu, bude nám v ní stačit jediný řádek a to zavolání metody GrafickyUkazatel() s příslušnými parametry:
Public Function GrafickyZivot() As String Return GrafickyUkazatel(zivot, maxZivot) End Function
Určitě jsem mohl v tutoriálu s bojovníkem udělat metodu GrafickyUkazatel() rovnou. Chtěl jsem však, abychom si ukázali, jak se řeší případy, kdy potřebujeme vykonat podobnou funkčnost vícekrát. S takovouto parametrizací se v praxi budete setkávat často, protože nikdy přesně nevíme, co budeme v budoucnu od našeho programu požadovat.
Nyní můžeme vykreslovat ukazatel tak, jak se nám to hodí. Přesuňme se do Mag.vb a naimplementujme metodu GrafickaMana():
Public Function GrafickaMana() As String Return GrafickyUkazatel(mana, maxMana) End Function
Jednoduché, že? Nyní je mág hotový, zbývá jen naučit arénu zobrazovat manu v případě, že je bojovník mág. Přesuňme se tedy do Arena.vb.
Rozpoznání typu objektu
Jelikož se nám nyní vykreslení bojovníka zkomplikovalo, uděláme si na něj samostatnou metodu VypisBojovnika(), jejím parametrem bude daná instance bojovníka:
Private Sub VypisBojovnika(b As Bojovnik) Console.WriteLine(b) Console.Write("Zivot: ") Console.WriteLine(b.GrafickyZivot()) End Sub
Nyní pojďme reagovat na to, jestli je bojovník mág. Minule jsme si řekli, že k tomu slouží operátor TypeOf a Is:
Private Sub VypisBojovnika(b As Bojovnik) Console.WriteLine(b) Console.Write("Zivot: ") Console.WriteLine(b.GrafickyZivot()) If TypeOf b Is Mag Then Console.Write("Mana: ") Console.WriteLine(DirectCast(b, Mag).GrafickaMana()) End If End Sub
Bojovníka jsme museli na mága přetypovat, abychom se k metodě GrafickaMana() dostali. Samotný Bojovnik ji totiž nemá. To bychom měli, VypisBojovnika budeme volat v metodě Vykresli(), která bude vypadat takto:
Class Arena Private bojovnik1 As Bojovnik Private bojovnik2 As Bojovnik Private kostka As Kostka Public Sub New(bojovnik1 As Bojovnik, bojovnik2 As Bojovnik, kostka As Kostka) Me.bojovnik1 = bojovnik1 Me.bojovnik2 = bojovnik2 Me.kostka = kostka End Sub Private Sub VypisBojovnika(b As Bojovnik) Console.WriteLine(b) Console.Write("Zivot: ") Console.WriteLine(b.GrafickyZivot()) If TypeOf b Is Mag Then Console.Write("Mana: ") Console.WriteLine(DirectCast(b, Mag).GrafickaMana()) End If End Sub Private Sub Vykresli() Console.Clear() Console.WriteLine("-------------- Aréna -------------- " & vbLf) Console.WriteLine("Bojovníci: " & vbLf) VypisBojovnika(bojovnik1) Console.WriteLine() VypisBojovnika(bojovnik2) Console.WriteLine() End Sub Private Sub VypisZpravu(zprava As String) Console.WriteLine(zprava) Thread.Sleep(500) End Sub Public Sub Zapas() ' původní pořadí Dim b1 As Bojovnik = bojovnik1 Dim b2 As Bojovnik = bojovnik2 Console.WriteLine("Vítejte v aréně!") Console.WriteLine("Dnes se utkají {0} s {1}! " & vbCrLf, bojovnik1, bojovnik2) ' prohození bojovníků Dim zacinaBojovnik2 As Boolean = (kostka.hod() <= kostka.VratPocetSten() / 2) If zacinaBojovnik2 Then b1 = bojovnik2 b2 = bojovnik1 End If Console.WriteLine("Začínat bude bojovník {0}!" & vbCrLf & "Zápas může začít...", b1) Console.ReadKey() ' cyklus s bojem While b1.Nazivu() And b2.Nazivu() b1.Utoc(b2) Vykresli() VypisZpravu(b1.VratPosledniZpravu()) ' zpráva o útoku VypisZpravu(b2.VratPosledniZpravu()) ' zpráva o obraně If b2.Nazivu Then b2.Utoc(b1) Vykresli() VypisZpravu(b2.VratPosledniZpravu()) ' zpráva o útoku VypisZpravu(b1.VratPosledniZpravu()) ' zpráva o obraně End If Console.WriteLine() End While End Sub End Class
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
Class Bojovnik Protected jmeno As String Protected zivot As Integer Protected maxZivot As Integer Protected utok As Integer Protected obrana As Integer Protected 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 Protected Function GrafickyUkazatel(aktualni As Integer, maximalni As Integer) As String Dim s As String = "[" Dim celkem As Integer = 20 Dim pocet As Double = Math.Round((aktualni / maximalni) * 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 Function GrafickyZivot() As String Return GrafickyUkazatel(zivot, maxZivot) End Function Public Overridable 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()) Dim zprava As String If zraneni > 0 Then zivot -= zraneni zprava = String.Format("{0} utrpěl poškození {1} hp", jmeno, zraneni) If zivot <= 0 Then zivot = 0 zprava &= " a zemřel" End If Else zprava = String.Format("{0} odrazil útok", jmeno) End If NastavZpravu(zprava) End Sub Protected 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
Class Mag Inherits Bojovnik Private mana As Integer Private maxMana As Integer Private magickyUtok As Integer Public Sub New(jmeno As String, zivot As Integer, utok As Integer, obrana As Integer, kostka As Kostka, mana As Integer, magickyUtok As Integer) MyBase.New(jmeno, zivot, utok, obrana, kostka) Me.mana = mana Me.maxMana = mana Me.magickyUtok = magickyUtok End Sub Public Function GrafickaMana() As String Return GrafickyUkazatel(mana, maxMana) End Function Public Overrides Sub Utoc(souper As Bojovnik) ' Mana není naplněna If mana < maxMana Then mana += 10 If mana > maxMana Then mana = maxMana End If MyBase.Utoc(souper) Else ' Magický útok Dim uder As Integer = magickyUtok + kostka.hod() NastavZpravu([String].Format("{0} použil magii za {1} hp", jmeno, uder)) souper.BranSe(uder) mana = 0 End If End Sub End Class
{VBNET_CONSOLE} ' vytvoření objektů Dim kostka As New Kostka(10) Dim zalgoren As New Bojovnik("Zalgoren", 100, 20, 10, kostka) Dim gandalf As Bojovnik = New Mag("Gandalf", 60, 15, 12, kostka, 30, 45) Dim arena As New Arena(zalgoren, gandalf, kostka) ' zápas arena.Zapas() Console.ReadKey() {/VBNET_CONSOLE}
Hotovo
Konzolová aplikace
-------------- Aréna --------------
Bojovníci:
Zalgoren
Život: [########## ]
Gandalf
Život: [##### ]
Mana: [############# ]
Zalgoren útočí s úderem za 28 hp
Aplikaci ještě můžeme dodat hezčí vzhled, vložil jsem ASCIIart nadpis Aréna, který jsem vytvořil touto aplikací: http://patorjk.com/software/taag . Navíc jsem obarvil ukazatele pomocí barvy pozadí a popředí. Metodu k vykreslení ukazatele jsem upravil tak, aby vykreslovala plný obdelník místo # (ten napíšete pomocí Alt + 219). Výsledek může vypadat takto:
Konzolová aplikace __ ____ ____ _ _ __ /__\ ( _ \( ___)( \( ) /__\ /(__)\ ) / )__) ) ( /(__)\ (__)(__)(_)\_)(____)(_)\_)(__)(__) Bojovníci: Zalgoren Život: ████████████████████ Gandalf Život: ████████████████████ Mana: ████████████████████ Gandalf použil magii za 48 hp Zalgoren utrpěl poškození 33 hp
Kód máte v příloze. Pokud jste něčemu nerozuměli, zkuste si článek přečíst vícekrát nebo pomaleji, jsou to důležité praktiky.
V následujícím cvičení, Řešené úlohy k 5.-8. lekci OOP ve Visual Basic .NET, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 241x (84 kB)
Aplikace je včetně zdrojových kódů v jazyce VB