Předvánoční Black Friday Předvánoční Black Friday
Až 80% zdarma! Předvánoční BLACK FRIDAY akce. Více informací

Cvičení k 9. lekci OOP v C# .NET

C# .NET Objektově orientované programování Cvičení k 9. lekci OOP v C# .NET American English version English version

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Následující 3 cvičení vám pomohou procvičit znalosti programování v C# .NET z minulé lekce. Ve vlastním zájmu se je pokuste vyřešit sami. Pod článkem máte pro kontrolu řešení ke stažení. Ale pozor, jakmile se na něj podíváte bez vyřešení příkladů, ztrácí pro vás cvičení smysl a nic se nenaučíte :)

Pokud si opravdu nebudete vědět rady, podívejte se raději znovu do minulého tutoriálu a pokuste se na to přijít.

Jednoduchý příklad

Naprogramujte aplikaci pro převod mezi stupni a radiány. Jelikož vše, co jste se učili ve škole, bylo ve stupních a vše, co se budete učit v programování, bude v radiánech, bude se vám znalost převodu hodit i do budoucna. Pokud vzorec neznáte, určitě si jej zvládnete jednoduše vyhledat :) Pro číslo Pí ve vzorci použijte konstantu na třídě Math. V aplikaci pro převody použijte statickou třídu.

Ukázka obrazovky programu:

Konzolová aplikace
6,28 radiánů na stupně: 359,817495342157
90 stupňů na radiány: 1,5707963267949

    class Prevodnik
    {
    }

Středně pokročilý příklad

Naprogramujte aplikaci, která vyrábí cukroví. Každé cukroví má nějakou barvu, tvar a váhu. Existuje např. cukroví banánové, jahodové, čokoládové a další. Jednotlivé druhy cukroví se odlišují pouze hodnotami v atributech. Jelikož by bylo zbytečné tvořit pro každý druh cukroví třídu a zároveň je pracné zadávat konkrétní atributy znovu a znovu tam, kde potřebujeme konkrétní instanci cukroví, použijeme zjednodušenou podobu návrhového vzoru Factory.

Factory (továrna) se používá zejména v případě, kdy potřebujete velké množství různě nastavených instancí. Jedná se o třídu se statickými metodami, které vytvoří instanci, nastaví ji určité parametry a takto nastavenou instanci vrátí. Vytvořte takovouto továrnu a implementujte v ní metody pro výrobu banánového, jahodového a čokoládového cukroví. Následně v aplikaci touto továrnou vytvořte a vypište:

  • 5ks banánového cukroví
  • 8ks jahodového cukroví
  • 12ks čokoládového cukroví

Vaší továrně nastavte atributy pro dané cukroví podle výstupu níže.

Ukázka obrazovky programu:

Konzolová aplikace
Cukroví barvy žlutá, tvaru kulatý a váhy 20g
Cukroví barvy žlutá, tvaru kulatý a váhy 20g
Cukroví barvy žlutá, tvaru kulatý a váhy 20g
Cukroví barvy žlutá, tvaru kulatý a váhy 20g
Cukroví barvy žlutá, tvaru kulatý a váhy 20g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy červená, tvaru kulatý a váhy 15g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g
Cukroví barvy hnědá, tvaru hranatý a váhy 25g

    class Cukrovi
    {
    }
    class TovarnaNaCukrovi
    {
    }

Pokročilý příklad

Vytvořte hrací kostku, která obsahuje metodu Hod(). Je to ta samá kostka, jakou jsme tvořili na začátku seriálu. Hod() vrací náhodné číslo od 1 do 6. Vytvořte 2 instance těchto kostek a nechte je v cyklu 10x hodit.

Konzolová aplikace
Na první kostce padlo 5
Na druhé kostce padlo 5
Na první kostce padlo 3
Na druhé kostce padlo 3
Na první kostce padlo 6
Na druhé kostce padlo 6
Na první kostce padlo 5
Na druhé kostce padlo 5
Na první kostce padlo 1
Na druhé kostce padlo 1
Na první kostce padlo 1
Na druhé kostce padlo 1
Na první kostce padlo 2
Na druhé kostce padlo 2
Na první kostce padlo 3
Na druhé kostce padlo 3
Na první kostce padlo 1
Na druhé kostce padlo 1
Na první kostce padlo 5
Na druhé kostce padlo 5

    class Kostka
    {
    }

Co to, na obou kostkách padají stejná čísla?! Jak je to možné?

Třída Kostka má jako atribut instanci třídy Random. Jakmile se vytvoří kostka, vytvoří se i nový generátor náhodných čísel. Obě kostky vytváříme ve stejný čas, takže i generátory jsou vytvořené v jednu chvíli. Toto je onen kámen úrazu. Jelikož vygenerovat opravdové náhodné číslo je v domácích podmínkách jen těžko realizovatelné, používají se tzv. čísla pseudonáhodná. Random používá tzv. seed (semeno), tím je čas, ve který se instance Random vytvořila. Od tohoto seedu se potom odvíjejí čísla, která padají. V našem případě mají obě instance stejný seed, s čímž v C# .NET nelze nic moc dělat.

Pokuste se problém vyřešit s použitím statiky a své řešení odůvodněte. Jako bonus se zamyslete i nad tím, jak by to šlo bez ní.


 

Stáhnout

Staženo 434x (154.84 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
6 hlasů
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 sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Předchozí článek
Statika
Miniatura
Následující článek
Vlastnosti
Aktivity (10)

 

 

Komentáře
Zobrazit starší komentáře (23)

Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:14.11.2017 14:52

Ne, ty nikdy nevypisuješ továrnu. Vypisuješ vždy to samé a to hodnotu, kterou ti vrátí ta metoda továrny. Jestli si tu hodnotu uložíš jako mezikrok do proměnné na výsledek nemá žádný vliv.

Odpovědět  +1 14.11.2017 14:52
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Karel Wala
Člen
Avatar
Odpovídá na David Čápka
Karel Wala:14.11.2017 17:52

Jo jasně, v té metodě stejně vždy vytvářím novou instanci cukroví (s danými atributy). Díky moc

 
Odpovědět  +1 14.11.2017 17:52
Avatar
Dušan Kovářík:26. června 3:54

První cvičení je triviální, ale líbí se mi na něm, že demonstruje právě tu situaci, kdy je vhodné statiku použít. Je to vlastně trochu podobné, jako třída Math. Já jsem třídu pojmenoval Prevod, i když by bylo jistě vhodnější ji pojmenovat např. Uhel, protože by do ní bylo možné implementovat spoustu dalších statických metod pro práci s úhly:

/// <summary>
/// Obsahuje metody pro převod stupňů na radiány a naopak
/// </summary>
static class Prevod
{
    /// <summary>
    /// Převede velikost úhlu ve stupních na radiány
    /// </summary>
    /// <param name="stupne">Velikost úhlu ve stupních</param>
    /// <returns>Velikost úhlu v radiánech</returns>
    public static double StupneNaRadiany(double stupne)
    {
        return stupne * Math.PI / 180;
    }

    /// <summary>
    /// Převede velikost úhlu v radiánech na stupně
    /// </summary>
    /// <param name="radiany">Velikost úhlu v radiánech</param>
    /// <returns>Velikost úhlu ve stupních</returns>
    public static double RadianyNaStupne(double radiany)
    {
        return radiany * 180 / Math.PI;
    }
}

Main():

double uhelVRadianech = 6.28;
double uhelVeStupnich = 90;
Console.WriteLine("{0} radiánů na stupně: {1}", uhelVRadianech, Prevod.RadianyNaStupne(uhelVRadianech));
Console.WriteLine("{0} stupňů na radiány: {1}", uhelVeStupnich, Prevod.StupneNaRadiany(uhelVeStupnich));
Console.ReadKey();
 
Odpovědět 26. června 3:54
Avatar
Dušan Kovářík:26. června 4:03

Druhý příklad je super - se zájmem jsem si přečetl odkazovaný článek o návrhovém vzoru Factory - ani jsem nevěděl, že tady na ITnetwork takové věci jsou - paráda! Líbí se mi to tady čím dál víc:

Tovarna:

/// <summary>
/// Obsahuje metody na výrobu banánového, jahodového a čokoládového cukroví
/// </summary>
static class Tovarna
{
    /// <summary>
    /// Vyrobí banánové cukroví
    /// </summary>
    /// <returns>Nová instance cukroví s atributy odpovídajícími banánovému cukroví</returns>
    public static Cukrovi Bananove()
    {
        return new Cukrovi("žlutá", "kulatý", 20);
    }

    /// <summary>
    /// Vyrobí jahodové cukroví
    /// </summary>
    /// <returns>Nová instance cukroví s atributy odpovídajícími jahodovému cukroví</returns>
    public static Cukrovi Jahodove()
    {
        return new Cukrovi("červená", "kulatý", 15);
    }

    /// <summary>
    /// Vyrobí čokoládové cukroví
    /// </summary>
    /// <returns>Nová instance cukroví s atributy odpovídajícími čokoládovému cukroví</returns>
    public static Cukrovi Cokoladove()
    {
        return new Cukrovi("hnědá", "hranatý", 25);
    }
}

U třídy Cukrovi už se těším na vlastnosti, které jsou myslím v další lekci. S tím, co jsem se naučil dosud, jsem tam musel dát tři metody, které nedělají nic jiného, než že vrací hodnotu daného atributu:

/// <summary>
/// Reprezentuje cukroví s danými vlastnostmi
/// </summary>
class Cukrovi
{
    /// <summary>
    /// Barva cukroví
    /// </summary>
    private string barva;

    /// <summary>
    /// Tvar cukroví
    /// </summary>
    private string tvar;

    /// <summary>
    /// Váha cukroví v gramech
    /// </summary>
    private int vaha;

    /// <summary>
    /// Vytvoří instanci jednoho kusu cukroví
    /// </summary>
    /// <param name="barva">Barva</param>
    /// <param name="tvar">Tvar</param>
    /// <param name="vaha">Váha v gramech</param>
    public Cukrovi(string barva, string tvar, int vaha)
    {
        this.barva = barva;
        this.tvar = tvar;
        this.vaha = vaha;
    }

    /// <summary>
    /// Vrátí barvu cukroví
    /// </summary>
    /// <returns>Barva cukroví</returns>
    public string Barva()
    {
        return barva;
    }

    /// <summary>
    /// Vrátí tvar cukroví
    /// </summary>
    /// <returns>Tvar cukroví</returns>
    public string Tvar()
    {
        return tvar;
    }

    /// <summary>
    /// Vrátí váhu cukroví
    /// </summary>
    /// <returns>Váha cukroví v gramech</returns>
    public int Vaha()
    {
        return vaha;
    }
}

A nakonec Main():

// Výroba cukroví
Cukrovi[] cukrovi = new Cukrovi[20];
for (int i = 0; i < cukrovi.Length; i++)
{
    if (i < 5)
        cukrovi[i] = Tovarna.Bananove();
    else if (i < 13)
        cukrovi[i] = Tovarna.Jahodove();
    else
        cukrovi[i] = Tovarna.Cokoladove();
}

// Výpis vyrobených kusů cukroví
foreach (Cukrovi kus in cukrovi)
    Console.WriteLine("Cukroví barvy {0}, tvaru {1} a váhy {2}g", kus.Barva(), kus.Tvar(), kus.Vaha());

Console.ReadLine();
 
Odpovědět 26. června 4:03
Avatar
Dušan Kovářík:26. června 4:41

Třetí cvičení jsem vyřešil prostě tak, že instanci Random ve třídě Kostka jsem deklaroval jako statickou a konstruktor přidělí kostce pouze počet stěn. Takže libovolný počet instancí třídy kostka bude sdílet pouze jeden generátor pseudonáhodných čísel a metoda Next() bude tím pádem také volána vždy na jednou a tomtéž generátoru, bez ohledu na to, kolik instancí kostek bude v programu existovat.

Kostka:

class Kostka
{
    /// <summary>
    /// Generátor náhodných čísel
    /// </summary>
    private static Random random = new Random();

    /// <summary>
    /// Počet stěn hrací kostky
    /// </summary>
    private int pocetSten;

    /// <summary>
    /// Vytvoří novou instanci hrací kostky o 6 stěnách
    /// </summary>
    public Kostka()
    {
        pocetSten = 6;
    }

    /// <summary>
    /// Vykoná hod kostkou
    /// </summary>
    /// <returns>Číslo od 1 do počtu stěn</returns>
    public int Hod()
    {
        return random.Next(1, pocetSten + 1);
    }
}

Main():

Kostka k1 = new Kostka();
Kostka k2 = new Kostka();
for (int i = 0; i < 10; i++)
{
    Console.WriteLine("Na první kostce padlo {0}", k1.Hod());
    Console.WriteLine("Na druhé kostce padlo {0}", k2.Hod());
}
Console.ReadKey();
 
Odpovědět 26. června 4:41
Avatar
Vasil Rudobaba:8. listopadu 14:06

Čau,
Snažil jsem se odevzdat příklad č.1 a nějak mi to nejde. Program mi funguje a nepřijde mi, že bych měl něco špatně? Nebo mám? :)

Převodník

static class Prevodnik
    {
        /// <summary>
        /// Metoda pro převod radiánu na stupně.
        /// </summary>
        /// <param name="radian">Kolik radiánu se ma převést na stupně..? Zadej číslo, které může být desetinné.</param>
        /// <returns></returns>
        public static double PrevedNaStupne(double radian)
        {
            double vysledek = radian * (180 / Math.PI);
            return vysledek;
        }
        /// <summary>
        /// Metoda pro převod stupňu na radiány.
        /// </summary>
        /// <param name="stupne">Kolik stupňu se má převést na radiány.?</param>
        /// <returns></returns>
        public static double PrevedNaRadiany(double stupne)
        {
            double vysledek = stupne * (Math.PI / 180);
            return vysledek;
        }

    }

Program:

double radianu = 6.28;
double stupnu = 90;


Console.WriteLine("{0} radiánů na stupně: {1}", radianu, Prevodnik.PrevedNaStupne(radianu));
Console.WriteLine("{0} stupňů na radiány: {1}", stupnu, Prevodnik.PrevedNaRadiany(stupnu));
 
Odpovědět 8. listopadu 14:06
Avatar
David Jančík
Tým ITnetwork
Avatar
Odpovídá na Vasil Rudobaba
David Jančík:8. listopadu 14:13

Byla chyba v testu, máš to správně, díky za feedback :)

Odpovědět 8. listopadu 14:13
Čím více času dostaneš, tím méně ho máš.
Avatar
Odpovídá na David Jančík
Vasil Rudobaba:8. listopadu 17:11

Díky za odpověď.. :)

 
Odpovědět 8. listopadu 17:11
Avatar
Jan Křížek:5. prosince 17:27

Příklady jsou výborné. S kostkou jsem to vyřešil tak, že jsem použil

using System.Threading;

a mezi instance jsem přidal

Thread.Sleep(200);

:)
 
Odpovědět 5. prosince 17:27
Avatar
Vít Vohralík:10. prosince 21:09

Příklad zcela náhodných čísel jsem vyřešil tím, že jsem nastavil Random na static a readonly. Když jsem dal pouze static, tak to generuje pořád čísla závislá na čase, ale po přidání readonly to generuje zcela náhodně.
Kód:

class Kostka
    {
        private static readonly Random rnd = new Random();
        public int pocetSten;
        public Kostka()
        {
            pocetSten = 6;
        }
        public int Hod() {
            return rnd.Next(1, pocetSten + 1);
        }
    }
Editováno 10. prosince 21:10
 
Odpovědět 10. prosince 21:09
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 33. Zobrazit vše