Lekce 5 - Hrací kostka v C# podruhé - Překrývání metod a random
V minulé lekci, Hrací kostka v C# - Zapouzdření a konstruktor, jsme vytvořili svůj první pořádný objekt, byla jím hrací kostka.
V tomto tutoriálu objektově orientovaného programování v C# budeme pokračovat v tvorbě naší objektové hrací kostky. Začneme s metodou pro hod. Vysvětlíme si na ní práci s náhodnými čísly a poté prozkoumáme principy překrývání metod.
Náhodná čísla
V .NET frameworku máme pro generování náhodných čísel k dispozici
třídu Random
. Přejdeme do souboru Kostka.cs
a
přidáme třídě Kostka
privátní atribut random
typu Random
, kde bude náhodný generátor čísel:
/// <summary> /// Třída reprezentuje hrací kostku /// </summary> class Kostka { /// <summary> /// Generátor náhodných čísel /// </summary> private Random random; /// <summary> /// Počet stěn kostky /// </summary> private int pocetSten; }
Dále v konstruktorech vytvoříme instanci třídy Random
.
Upravené konstruktory budou vypadat následovně:
/// <summary> /// Vytvoří novou instanci hrací kostky /// </summary> public Kostka() { pocetSten = 6; random = new Random(); } /// <summary> /// Vytvoří novou instanci hrací kostky /// </summary> /// <param name="pocetSten">Počet stěn hrací kostky</param> public Kostka(int pocetSten) { this.pocetSten = pocetSten; random = new Random(); }
Hod kostkou
Nyní můžeme ve třídě Kostka
definovat další metodu.
Nazveme ji Hod()
:
/// <summary> /// Vykoná hod kostkou /// </summary> /// <returns>Číslo od 1 do počtu stěn</returns> public int Hod() { return random.Next(1, pocetSten + 1); }
Metoda nám vrátí náhodné číslo od jedné do počtu stěn, bude
public
(půjde volat zvenčí) a nebude mít žádný parametr.
Návratová hodnota bude typu int
. Náhodné číslo získáme tak,
že na generátoru random
zavoláme metodu Next()
. Ta
má několik přetížení:
Next()
– Varianta bez parametru vrací náhodné číslo v celém rozsahu datového typuint
, pro úplnost tedy konkrétně od-2147483648
do2147483647
.Next(do)
– Vrací nezáporná čísla menší než mezdo
. Napříkladrandom.Next(100)
tedy vrátí číslo od0
do99
.Next(od, do)
– Vrátí náhodné číslo v zadané mezi, přičemžod
do intervalu patří ado
již ne. Náhodné číslo od1
do100
by tedy vrátilo přetíženírandom.Next(1, 101)
.
Pro naše účely se nejlépe hodí třetí přetížení. Dejte si pozor,
abyste netvořili generátor náhodných čísel v metodě, která má náhodné
číslo vracet, tedy že se pro každé náhodné číslo nevytvořil nový
generátor. Výsledná čísla pak téměř nejsou náhodná, nebo dokonce
vůbec. Vždy si vytvořte jednu sdílenou instanci generátoru (např. do
privátního atributu pomocí konstruktoru) a na té potom metodu
Next()
volejte.
Překrývání metody ToString()
Kostka je téměř hotová. Ukažme si ještě jednu užitečnou metodu,
kterou kostce přidáme a kterou budeme hojně používat i ve většině
našich dalších objektů. Řeč je o metodě ToString()
, o níž
jsme se již zmínili a kterou obsahuje každý objekt. Tedy i
nyní naše kostka. Metoda je určena k tomu, aby vrátila tzv. textovou
reprezentaci instance. Hodí se ve všech případech, kdy si instanci
potřebujeme vypsat nebo s ní pracovat jako s textem. Touto metodou disponují
např. i čísla. Již víme, že v C# funguje implicitní konverze. Jakmile
tedy budeme chtít do konzole vypsat číslo nebo kterýkoli jiný objekt, C# na
něm zavolá metodu ToString()
a vypíše její výstup. Pokud si
tvoříme vlastní třídu, měli bychom zvážit, zda se nám takováto metoda
nemůže hodit. Nikdy bychom si neměli tvořit vlastní metodu, např. něco
jako Vypis()
, máme-li v C# připravenou cestu, jak tento
požadavek řešit. U kostky nemá ToString()
vyšší smysl, ale u
bojovníka bude jistě vracet jeho jméno. My si ToString()
ke
kostce přesto přidáme. Metoda bude vracet, že se jedná o kostku, a vrátí
i počet stěn. Nejprve si zkusme vypsat do konzole naši instanci kostky:
{CSHARP_CONSOLE} Kostka sestistenna = new Kostka(); Kostka desetistenna = new Kostka(10); Console.WriteLine(sestistenna); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Kostka { private Random random; private int pocetSten; public Kostka() { pocetSten = 6; random = new Random(); } public Kostka(int pocetSten) { this.pocetSten = pocetSten; random = new Random(); } public int VratPocetSten() { return pocetSten; } public int Hod() { return random.Next(1, pocetSten + 1); } } {/CSHARP_OOP}
Do konzole se vypíše pouze cesta k naší třídě, tedy
Arena.Kostka
. Metodu nemůžeme jen tak definovat, protože je již
definována (v dalších lekcích zjistíme proč). Musíme ji tedy přepsat,
resp. překrýt. Tím se opět nebudeme nyní dopodrobna
zabývat, nicméně je potřeba, abychom již nyní uměli
ToString()
používat. K překrytí použijeme klíčové slovo
override
:
{CSHARP_OOP} class Kostka { private Random random; private int pocetSten; public Kostka() { pocetSten = 6; random = new Random(); } public Kostka(int pocetSten) { this.pocetSten = pocetSten; random = new Random(); } public int VratPocetSten() { return pocetSten; } public int Hod() { return random.Next(1, pocetSten + 1); } /// <summary> /// Vrací textovou reprezentaci kostky /// </summary> /// <returns>Textová reprezentace kostky</returns> public override string ToString() { return String.Format("Kostka s {0} stěnami", pocetSten); } } {/CSHARP_OOP}
{CSHARP_CONSOLE} Kostka sestistenna = new Kostka(); Kostka desetistenna = new Kostka(10); Console.WriteLine(sestistenna); Console.ReadKey(); {/CSHARP_CONSOLE}
Nyní opět zkusíme do konzole vypsat přímo instanci kostky.
Výstup:
Konzolová aplikace
Kostka s 6 stěnami
Ještě si naše kostky vyzkoušíme. Zkusíme si v programu s našimi dvěma kostkami v cyklech házet a podíváme se, jestli fungují tak, jak očekáváme:
{CSHARP_CONSOLE} // vytvoření Kostka sestistenna = new Kostka(); Kostka desetistenna = new Kostka(10); // hod šestistěnnou Console.WriteLine(sestistenna); for (int i = 0; i < 10; i++) Console.Write(sestistenna.Hod() + " "); // hod desetistěnnou Console.WriteLine("\n\n" + desetistenna); for (int i = 0; i < 10; i++) Console.Write(desetistenna.Hod() + " "); 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 tatáž čísla. // S jakoukoli změnou v kódu (např. i přidáním komentáře) vyvoláte // novou kompilaci, a tedy i vygenerování nových čísel. {/CSHARP_CONSOLE}
{CSHARP_OOP} class Kostka { private Random random; private int pocetSten; public Kostka() { pocetSten = 6; random = new Random(); } public Kostka(int pocetSten) { this.pocetSten = pocetSten; random = new Random(); } public int VratPocetSten() { return pocetSten; } public int Hod() { return random.Next(1, pocetSten + 1); } public override string ToString() { return String.Format("Kostka s {0} stěnami", pocetSten); } } {/CSHARP_OOP}
Konzolová aplikace
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 hotovou poměrně hezkou a nastavitelnou třídu, která reprezentuje hrací kostku. Bude se nám hodit v naší aréně, ale můžeme ji použít i kdekoli jinde. Vidíme, jak OOP umožňuje znovupoužívat komponenty.
V následujícím cvičení, Řešené úlohy k 4.-5. lekci OOP v C# .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 1x (2.56 MB)
Aplikace je včetně zdrojových kódů v jazyce C#