Black Friday Black Friday
Black Friday výprodej! Až 80 % extra bodů zdarma! Více informací zde

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

C# .NET Objektově orientované programování Cvičení k 4. 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 objektově orientovaného 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.

Ohlasy studentů

Jednoduchý příklad

Naprogramujte aplikaci, ve které figurují dva typy objektů - Pes a Osoba. Pes má jméno, věk a metodu, která ho nechá zestárnout o jeden rok. Osoba má jméno a psa. V aplikaci si vytvořte jednoho psa a vypište jeho věk. Tohoto psa následně přiřaďte dvěma osobám. Psa první osoby nechte zestárnout o 1 rok a psa druhé osoby nechte také zestárnout o 1 rok. Tyto dva kroky mohou v kódu vypadat např. takto:

karel.pes.Zestarni();
lenka.pes.Zestarni();

Nakonec vypište věk psa libovolné osoby, který bude o 2 roky vyšší, než věk na začátku programu. Ověříte si tak, že mají obě osoby opravdu referenci na jednoho a toho samého psa.

Ukázka obrazovky programu:

Konzolová aplikace
Azor (1 let)
Azor (3 let)

    class Pes
    {
    }
    class Osoba
    {
    }

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

Naprogramujte jednoduchou textovou hru, která obsahuje následujících 7 propojených lokací:

Cvičení k C# .NET OOP – Mapa k textové hře

Každá lokace má název a textový popis, tato data budou následovat dále. Každá lokace má také referenci na 4 okolní lokace (tedy na lokaci na severu, jihu, západě a východě). Vytvořte herní svět z takto propojených lokací podle obrázku výše. Následně aplikaci naučte přijímat v cyklu příkazy od uživatele. Příkazy jsou:

  • jdi na [strana], např. "jdi na východ" - Jde na určitou světovou stranu
  • konec - Ukončí aplikaci

Použijte následující názvy lokací a jejich popisy. Odpovídají lokacím v obrázku (zleva doprava, shora dolů):

Název Popis
Hrad Stojíš před okovanou branou gotického hradu, která je zřejmě jediným vchodem do pevnosti. Klíčová dírka je pokryta pavučinami, což vzbuzuje dojem, že je budova opuštěná.
Les Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.
Lesní rozcestí Nacházíš se na lesním rozcestí.
Les Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.
Rybník Došel jsi ke břehu malého rybníka. Hladina je v bezvětří jako zrcadlo. Kousek od tebe je dřevěná plošina se stavidlem.
Les Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.
Dům Stojíš před svým rodným domem, cítíš vůni čerstvě nasekaného dřeva, která se line z hromady vedle vstupních dveří.

Počáteční lokace je lokace Dům.

Při pokusu o přechod na neplatnou lokaci program vypíše "Tímto směrem nelze jít."

Při zadání neplatného příkazu program vypíše "Můj vstupní slovník neobsahuje tento příkaz."

Ukázka obrazovky programu:

Konzolová aplikace
Les
Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.

Můžeš jít na sever východ

Zadej příkaz: jdi na sever
Lesní rozcestí
Nacházíš se na lesním rozcestí.

Můžeš jít na jih západ východ

Zadej příkaz: jdi na východ
Les
Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.

Můžeš jít na západ východ

Zadej příkaz: jdi na východ
Rybník
Došel jsi ke břehu malého rybníka. Hladina je v bezvětří jako zrcadlo. Kousek od tebe je dřevěná plošina se stavidlem.

Můžeš jít na západ


Z důvodu dynamického množství vstupů, hru vyzkoušejte ve vašem IDE a zde ji předejte až k ohodnocení.

Pokud vás nenapadá, jakým způsobem mezi lokacemi procházet, zamyslete se nad referencí na lokaci, ve které právě jste.

    class Lokace
    {
    }
    class Hra
    {
    }

Pokročilý příklad

Naprogramujte aplikaci evidující rodokmen Barta Simpsona a Homera Simpsona. Použijte k tomu následující data:

Rodokmen rodiny Simpsnů

V aplikaci budou figurovat osoby. Každá osoba má referenci na otce a matku, kteří jsou sami osobami.

Sestavte v paměti strom z napojených instancí osob tak, jak je na obrázku výše.

V druhém kroku se pokuste vypsat rodokmeny Barta Simpsona a Homera Simpsona tak, jak je to vidět na screenshotu níže.

Ukázka obrazovky programu:

Konzolová aplikace
Rodokmen pro osobu Bart Simpson
Bart Simpson
Homer Simpson
Abraham Simpson
Penelope Olsen
Marge Bouvier
Pan Bouvier
Jackie Bouvier

Rodokmen pro osobu Homer Simpson
Homer Simpson
Abraham Simpson
Penelope Olsen

    class Osoba
    {
    }
    class Rodokmen
    {
    }

Pokud jste vytvořili v paměti správně napojený strom, máte kus práce za sebou. Rodokmen vypíšete tak, že vypíšete jméno kořenu a přesunete se do jeho dvou větví (do otce a matky). Nyní máte další dva kořeny, ve kterých uděláte to samé. Dostanete další 4 a tak se celá situace opakuje, dokud neprojedete celý strom. Úlohu lze nejlépe řešit tzv. rekurzí. To je programátorská technika, kdy určitá metoda volá sebe sama s jinými parametry. Dokážete na řešení přijít? :)

Datové struktuře, kterou jste vytvořili, se říká opravdu strom. V našem případě se jedná o vyvážený binární strom, kterému se říká halda. Stromy se často používají v algoritmizaci pro ukládání dat, protože mají na rozdíl od klasických seznamů speciální vlastnosti. Zájemce odkáži na Kurzy algoritmů.


 

Stáhnout

Staženo 880x (266.23 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?
7 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
Následující článek
Bojovník do arény
Aktivity (26)

 

 

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

Avatar
vajkuba1234
Člen
Avatar
vajkuba1234:7. ledna 19:22

Proc nepouzivas konstruktor? Co presne ti to pise nebo dela?

Odpovědět 7. ledna 19:22
No hope, no future, JUST WAR! For world peace Israel must be DESTROYED!
Avatar
Dušan Kovářík:18. června 2:13

Funguje to :) Rodokmen jsem implementoval pomocí rekurzivní metody, která nic nevypisuje, ale vrací "odřádkovaný" string. Výpis jsem nechal výhradně na Main().

Main():

static void Main(string[] args)
{
    // Vytvoření osob rodokmenu Simpsonových
    Osoba abrahamSimpson = new Osoba("Abraham Simpson");
    Osoba penelopeOlsen = new Osoba("Penelope Olsen");
    Osoba panBouvier = new Osoba("Pan Bouvier");
    Osoba jackieBouvier = new Osoba("Jackie Bouvier");
    Osoba herbPowers = new Osoba("Herb Powers");
    Osoba homerSimpson = new Osoba("Homer Simpson");
    Osoba margeSimpson = new Osoba("Marge Simpson");
    Osoba selmaBouvier = new Osoba("Selma Bouvier");
    Osoba bartSimpson = new Osoba("Bart Simpson");

    // Vytvoření vztahů v rodokmenu
    bartSimpson.PriradRodice(homerSimpson, margeSimpson);
    herbPowers.PriradRodice(abrahamSimpson, penelopeOlsen);
    homerSimpson.PriradRodice(abrahamSimpson, penelopeOlsen);
    margeSimpson.PriradRodice(panBouvier, jackieBouvier);
    selmaBouvier.PriradRodice(panBouvier, jackieBouvier);

    // Výpis rodokměnů pro Barta Simpsona a Homera Simpsona
    Console.WriteLine(bartSimpson.SestavRodokmen());
    Console.WriteLine(homerSimpson.SestavRodokmen());

    Console.ReadKey();
}

Osoba:

/// <summary>
/// Třída reprezentuje osubu z rodokmenu Simpsonových
/// </summary>
class Osoba
{
    /// <summary>
    /// Jméno osoby
    /// </summary>
    private string jmeno;

    /// <summary>
    /// Otec osoby
    /// </summary>
    private Osoba otec;

    /// <summary>
    /// Matka osoby
    /// </summary>
    private Osoba matka;

    /// <summary>
    /// Rodokmen osoby ve formátu odřádkovaného textu
    /// </summary>
    private string rodokmen;

    /// <summary>
    /// Vytvoří novou instanci třídy Osoba
    /// </summary>
    /// <param name="jmeno">Jméno osoby</param>
    public Osoba(string jmeno)
    {
        this.jmeno = jmeno;
    }

    /// <summary>
    /// Přiřadí osobě rodiče ve formě referencí na jiné instance třídy Osoba
    /// </summary>
    /// <param name="otec">Otec osoby</param>
    /// <param name="matka">Matka osoby</param>
    public void PriradRodice(Osoba otec, Osoba matka)
    {
        this.otec = otec;
        this.matka = matka;
    }

    /// <summary>
    /// Do atributu třídy rodokmen sestaví odřádkovaný text s rodokmenem osoby
    /// </summary>
    /// <returns></returns>
    public string SestavRodokmen()
    {
        rodokmen = String.Format("Rodokmen pro osobu {0} \n", jmeno);
        PridejDalsi(this);
        return rodokmen;
    }

    /// <summary>
    /// Do atributu třídy rodokmen rekurzivně přidá všechny relevantní osoby
    /// </summary>
    /// <param name="aktualniOsoba">Osoba, pro kterou se aktuálně hledají rodiče</param>
    private void PridejDalsi(Osoba aktualniOsoba)
    {
        rodokmen += aktualniOsoba + "\n";
        if (aktualniOsoba.otec != null)
        {
            PridejDalsi(aktualniOsoba.otec);
        }
        if (aktualniOsoba.matka != null)
        {
            PridejDalsi(aktualniOsoba.matka);
        }
    }

    /// <summary>
    /// Vrátí jméno osoby
    /// </summary>
    /// <returns>Jméno osoby</returns>
    public override string ToString()
    {
        return jmeno;
    }
}
 
Odpovědět  +1 18. června 2:13
Avatar
Wen Fot
Člen
Avatar
Wen Fot:26. července 12:16

Prosím o radu.
Nevím proč mi to funguje jenom "chvilku". O co jde? Pro jednoduchost jsem vytvořil jen dvě lokace stejné třídy - hrad a les, které mají název a popis.Obě lokace mají 2 atributy: "lokaceZapad" a "lokaceVychod" ktere propojují objekty. Program nechava prochazet jen z jedne lokace do druhe - ze Z (zapad) na V (vychodu) a zpět. Po několika projdutích to nahlásí chybu. Myslím, že mám vše OK, ale asi nemám :). Díky za radu předem

Hlavní program:

static void Main(string[] args)
        {
            //definice lokací
            Lokace hrad = new Lokace("Karlštejn", "Pěkný hrad poblíž Prahy");
            Lokace les = new Lokace("Les Řáholec", "Les s Mankou, Cipískem a Rumcajsem.");

            //propojení lokací (přes zavolani druhého konstruktoru)
            hrad = new Lokace(hrad, les, null); // V, Z
            les = new Lokace(les, null, hrad);

            Lokace aktualniLokace = les; //startovací lokace

            Console.WriteLine("Nyní jste v lokaci");
            Console.WriteLine("Název: {0}\nPopis: {1}", aktualniLokace.nazev, aktualniLokace.popis);
            Console.WriteLine("---------------------------- -");

            string strana = "západ. Napiš (z) a enter";
            bool pokracovat = true;
            while (pokracovat)
            {
                Console.WriteLine("Ted můžeš jít na {0}", strana);
                string vstup = Console.ReadLine().ToLower();
                switch (vstup)
                { //aktualní lokaci posune na novou aktualní lokaci podle volby S nebo V
                    case "v":
                        aktualniLokace = aktualniLokace.lokaceVychod;
                        strana = "západ. Napiš (z) a enter";
                        break;

                    case "z":
                        aktualniLokace = aktualniLokace.lokaceZapad;
                        strana = "východ. Napiš (v) a enter";
                        break;
                }

                Console.WriteLine("Nyní jste v lokaci");
                Console.WriteLine("Název: {0}\nPopis: {1}", aktualniLokace.nazev, aktualniLokace.popis);
                Console.WriteLine("-----------------------------");

                //nacteni vstup pro ukončení/pokracovani programu
                Console.WriteLine("\nCHCECŠ POKRAČOVAT?\nStiskni [n/N] = ukončení." +
                   "\nStiskni [jinou klavesnici] = pokračování");
                vstup = Console.ReadKey().KeyChar.ToString().ToLower();
                switch (vstup)
                {
                    case "n":
                        pokracovat = false;
                        break;
                    default:
                        Console.WriteLine("\nOK, pokračujeme...");
                        break;
                }

            }

        }

Třída Lokace

class Lokace
    {
        public string nazev;
        public string popis;
        public Lokace lokaceVychod;
        public Lokace lokaceZapad;

        public Lokace(string nazev, string popis)
        {
            this.nazev = nazev;
            this.popis = popis;
        }

        public Lokace(Lokace lokace, Lokace lokaceVychod, Lokace lokaceZapad)
        {
            this.nazev = lokace.nazev;
            this.popis = lokace.popis;
            this.lokaceVychod = lokaceVychod;
            this.lokaceZapad = lokaceZapad;
        }
    }
 
Odpovědět 26. července 12:16
Avatar
Vasil Rudobaba:5. listopadu 16:54

Zdravím zkušenější kolegy,
Mám menší problém s příkladem 2. V podstatě ve Studiu mi vše funguje jak má(aspoň si to myslím :)), ale když kod zkopíruji sem pro otestování, tak to chvíli chroupe a pak vyhodí chybovou hlášku Server: Došlo k chybě.
Pár příkladu jsem již odevzdával a buď byli správně nebo mi to napsalo že jsem tupec a mám to špatně :).
Takže tou chybou si nějak nejsem jist. Příklad jsem předělával už 3x a pořád to samé.

Třída Lokace:

class Lokace
    {
        /// <summary>
        /// Jmeno lokace.
        /// </summary>
        private string jmeno;
        /// <summary>
        /// Popis lokace.
        /// </summary>
        private string popis;
        /// <summary>
        /// Sever od aktuální lokace.
        /// </summary>
        public Lokace sever;
        /// <summary>
        /// Východ od aktuální lokace.
        /// </summary>
        public Lokace vychod;
        /// <summary>
        /// Západ od aktuální lokace.
        /// </summary>
        public Lokace zapad;
        /// <summary>
        /// Jih od aktuální lokace.
        /// </summary>
        public Lokace jih;
        /// <summary>
        /// Konstruktor lokace.
        /// </summary>
        /// <param name="jmeno">Jmeno lokace.</param>
        /// <param name="popis">Popis lokace</param>
        public Lokace(string jmeno, string popis)
        {
            this.jmeno = jmeno;
            this.popis = popis;
        }
        /// <summary>
        /// Textova reprezentace Lokace
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string a = "Můžeš jít na ";
            if (sever != null)
                a += "sever ";
            if (vychod != null)
                a += "východ ";
            if (zapad != null)
                a += "západ ";
            if (jih != null)
                a += "jih ";

            return jmeno + "\n" + popis + "\n\n" + a + "\n\n" + "Zadej příkaz: ";
        }
    }

Třída Hra:

class Hra
    {
        /// <summary>
        /// Proměna pro pokračování nebo konec.
        /// </summary>
        private bool konec = false;

        /// <summary>
        /// Aktualni pozice ve hře.
        /// </summary>
        Lokace aktualniPozice;
        /// <summary>
        /// Konstruktor hry.
        /// </summary>
        public Hra()
        {
            Lokace dum = new Lokace("Dům", "Stojíš před svým rodným domem, citíš vůni čerstvě nasekaného dřeva, která se line z hromady vedle vstupních dvěří.");
            Lokace les = new Lokace("Les", "Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.");
            Lokace rybnik = new Lokace("Rybník", "Došel jsi ke břehu malého rybníka. Hladina je v bezvětří jako zrcadlo. Kousek od tebe je dřevěná plošina se stavidlem.");
            Lokace lesURybnika = new Lokace("Les", "Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.");
            Lokace lesniRozcesti = new Lokace("Lesní rozcesti", "Nacházíš se na lesním rozcestí.");
            Lokace lesUHradu = new Lokace("Les", "Jsi na lesní cestě, která se klikatí až za obzor, kde mizí v siluetě zapadajícího slunce. Ticho podvečerního lesa občas přeruší zpěv posledních ptáků.");
            Lokace hrad = new Lokace("Hrad", "Stojíš před okovanou branou gotického hradu, která je zřejmě jediným vchodem do pevnosti. Klíčová dírka je pokryta pavučinami, což vzbuzuje dojem, že je budova opuštěná.");
            this.aktualniPozice = dum;

            dum.zapad = les;
            les.sever = lesniRozcesti;
            les.vychod = dum;
            lesniRozcesti.vychod = lesURybnika;
            lesniRozcesti.zapad = lesUHradu;
            lesniRozcesti.jih = les;
            lesURybnika.vychod = rybnik;
            lesURybnika.zapad = lesniRozcesti;
            lesUHradu.vychod = lesniRozcesti;
            lesUHradu.zapad = hrad;
            hrad.vychod = lesUHradu;
            rybnik.zapad = lesURybnika;

        }
        /// <summary>
        /// Metoda pro začátek hry.
        /// </summary>
        public void Start()
        {

            while (konec == false)
            {
                Console.Write(aktualniPozice.ToString());
                string smer = Console.ReadLine();
                if (smer == "jdi na jih" && aktualniPozice.jih != null)
                    aktualniPozice = aktualniPozice.jih;
                if (smer == "jdi na sever" && aktualniPozice.sever != null)
                    aktualniPozice = aktualniPozice.sever;
                if (smer == "jdi na západ" && aktualniPozice.zapad != null)
                    aktualniPozice = aktualniPozice.zapad;
                if (smer == "jdi na východ" && aktualniPozice.vychod != null)
                    aktualniPozice = aktualniPozice.vychod;
                if (smer == "Konec")
                    System.Environment.Exit(0);
            }

        }
    }

Třída Program:

class Program
        {
                static void Main(string[] args)
                {
                         Hra hra = new Hra();

                         hra.Start();

                }
        }

Díky za rady.

 
Odpovědět 5. listopadu 16:54
Avatar
David Jančík
Tým ITnetwork
Avatar
Odpovídá na Vasil Rudobaba
David Jančík:5. listopadu 18:28

Díky za feedback. Chybí ti v programu ošetřit následující:

  • Při pokusu o přechod na neplatnou lokaci program vypíše "Tímto směrem nelze jít."
  • Při zadání neplatného příkazu program vypíše "Můj vstupní slovník neobsahuje tento příkaz."

Potom by ti to už mělo jít.

Odpovědět  +1 5. listopadu 18:28
Čím více času dostaneš, tím méně ho máš.
Avatar
Vasil Rudobaba:5. listopadu 19:39

Díky za odpověď.. Vím, že jsem to neměl ošetřeny, tak nějak jsem to vynechal a nečekal kontrolu i toho :) a zarazila mně ta hláška. Ve finále mně to stálo více času, než kdybych to udělal hned :D.
Doladím a zkusím.

 
Odpovědět 5. listopadu 19:39
Avatar
Odpovídá na David Jančík
Vasil Rudobaba:5. listopadu 20:57

Vše ok, už to prošlo. Dík.

 
Odpovědět 5. listopadu 20:57
Avatar
Odpovídá na David Jančík
Vasil Rudobaba:7. listopadu 17:21

Čau,
V příkladu 3 je "asi" chybka.. Na obrázku znázorňujícím strom je Marge Bouvier a na screenu je Marge Simpson.
Prošlo mi to s Simpson. Původně jsem opisoval výstupy ze stromu. Asi by nebylo špatné to sladit.

 
Odpovědět 7. listopadu 17:21
Avatar
David Jančík
Tým ITnetwork
Avatar
Odpovídá na Vasil Rudobaba
David Jančík:8. listopadu 0:39

Díky za feedback, opraveno.

Odpovědět 8. listopadu 0:39
Čím více času dostaneš, tím méně ho máš.
Avatar
Jaromír
Člen
Avatar
Jaromír:13. listopadu 10:13

Prosím o otestování odevzdaného příkladu č. 2, Nějak si nevím rady, co je špatně. V IDE vše funguje. Moc děkuji.

 
Odpovědět 13. listopadu 10:13
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 23. Zobrazit vše