← Přehled všech hodin

Úklid kódu — moduly, jmenné prostory a vlastní knihovna

Cíl hodiny: Tvůj CsQuest má dnes možná 400 řádků v jednom souboru. Naučíš se ho rozdělit na části, které mají jméno, svoje místo a dají se použít znovu.
Jak stránku používat: vpravo nahoře je tlačítko Prezentace — schová všechno kromě jednoho bloku a přepíná se šipkami. U ukázek a cvičení je kód vlevo editovatelný: uprav ho a klikni na Spustit (nebo Ctrl+Enter). Program se přeloží a spustí přímo v prohlížeči a vpravo se objeví to, co vypsal do konzole. Nic se neinstaluje.
Kam to dnes směřuje:

1. Vysvětlení a souvislosti

Poznámky pro učiteleJak celou hodinu vést1. Vysvětlení a souvislosti

Tenhle blok je jen pro vás — dětem ho nepromítejte.

Fáze Co se děje Čas
Motivace Otevřete jejich vlastní soubor a zkuste v něm něco najít 10 min
Co je modul Bloky 2–3 + ukázka 1 15 min
using a namespace Bloky 4–6 + ukázka 2 20 min
Statická třída jako modul Blok 7 + ukázka 3 15 min
Objekt na řádek a zpět Blok 8 + ukázky 4–5 20 min
Cvičení Děti pracují samy, vy obcházíte 55 min
Shrnutí Před/po: kolik řádků má hlavní část 5 min

Hlavní myšlenka hodiny: rozdělení kódu není kosmetika. Je to jediný způsob, jak se dá program po pár týdnech ještě číst. Děti to samy necítí — proto začínáme ukázkou jejich vlastního neuklizeného souboru.

Jedno velké upozornění k našemu prostředí. Tlačítko ▶ Spustit v prohlížeči umí přeložit jeden kus kódu. Nedokáže načíst druhý soubor z disku. Proto dnes budeme „soubory" simulovat: každou část ohraničíme komentářem // ===== soubor Data.cs ===== a napíšeme ji jako samostatnou třídu. Ve Visual Studio Code doma (viz úvodní hodina) je to doopravdy jeden soubor Data.cs, druhý Nastroje.cs a tak dál — a nic víc se nemění. Tuhle větu během hodiny zopakujte aspoň třikrát.

Druhé upozornění: namespace se v prohlížečovém spouštěči nepřeloží (hlásí CS7021). Není to chyba studenta ani vaše — je to vlastnost režimu, ve kterém prohlížeč kód spouští. Proto jsou všechny ukázky s namespace dnes jen „na čtení" a nemají tlačítko Spustit.

Poznámky pro učiteleMotivace — otevřete jejich vlastní soubor1. Vysvětlení a souvislosti

Než cokoli vysvětlíte, udělejte tohle:

  1. Nechte studenta promítnout jeho vlastní CsQuest z minulé hodiny.
  2. Zadejte úkol: „najdi řádek, kde se rozhoduje, kolik zlata dá skřet."
  3. Měřte čas. Obvykle 30–90 sekund scrollování.
  4. Zeptejte se: „a co za měsíc? A co kdyby ten soubor psal někdo jiný?"

Tohle udělá pro motivaci víc než jakákoli teorie. Dnešní hodina má jediný cíl: aby se v tom souboru dalo něco najít do pěti vteřin.

Druhý argument, který na děti platí: „až budete dělat projekt ve dvou, nemůžete oba psát do jednoho souboru." Rozdělení kódu je i způsob, jak se dá spolupracovat.

Blok 1Co je modul1. Vysvětlení a souvislosti

Zatím jsi psal všechno do jednoho kusu kódu. To funguje, dokud je program malý. Jakmile má pár set řádků, začne se dít tohle:

  • hledáš jednu metodu a scrolluješ minutu,
  • omylem máš dvě věci se stejným jménem,
  • bojíš se cokoli změnit, protože nevíš, co se rozbije.

Modul je pojmenovaná část programu, která má na starosti jednu věc. V C# je modul v podstatě jeden soubor .cs a v něm jedna třída.

Co chceš Jak se to jmenuje Kde to bydlí
seznamy míst, cen, jmen Data Data.cs
kostky, procenta, pruh životů Nastroje Nastroje.cs
třídy Postava, Prisera Model Postava.cs, Prisera.cs
samotný průběh hry hlavní program Program.cs

Pravidlo, které se vyplatí: jeden soubor = jedna třída = jedno téma. Když se soubor jmenuje Data.cs, nesmí v něm být souboj.

Proč to dnes píšeme do jednoho okna

Naše tlačítko ▶ Spustit umí přeložit jeden kus kódu, ne celý projekt. Proto budeme „soubory" jen naznačovat komentářem:

// ===== soubor Data.cs =====
static class Data { ... }
// ===== konec Data.cs =====

Doma ve Visual Studio Code je to opravdový soubor a žádný komentář nepotřebuješ. Všechno ostatní — názvy, static, public — zůstává úplně stejné.

Blok 2Statická třída jako modul1. Vysvětlení a souvislosti

Modul s daty a pomocnými metodami nechceš „vyrábět" přes new. Potřebuješ ho jen jednou a pořád stejný. Přesně na to je static class:

Console.WriteLine($"Míst na mapě: {Data.Mista.Count}");
Console.WriteLine($"První místo:  {Data.Mista[0]}");
Console.WriteLine($"Cena lektvaru: {Data.CenaLektvaru} zl.");

static class Data
{
    public const int CenaLektvaru = 25;

    public static List<string> Mista = new List<string>
    {
        "Mlžný hvozd",
        "Skřetí tábor",
        "Zřícenina Vraního hradu"
    };
}

Všimni si tří věcí:

  • před class je static — třída se nedá vyrobit přes new,
  • před každou položkou je taky static (nebo const),
  • k obsahu se dostaneš přes jméno třídy s tečkou: Data.Mista.

To poslední je přesně to, co dělá modul modulem. Když někde v kódu uvidíš Data.Mista, hned víš, odkud to je.

Blok 3Modul s metodami1. Vysvětlení a souvislosti

Do modulu nepatří jen data, ale hlavně pomocné metody, které používáš pořád dokola. Dej je na jedno místo a napiš je jenom jednou:

Random kostka = new Random(7);

Console.WriteLine($"Hod k6:  {Nastroje.HodKostkou(kostka, 6)}");
Console.WriteLine($"Hod k20: {Nastroje.HodKostkou(kostka, 20)}");
Console.WriteLine($"Procenta: {Nastroje.Procenta(30, 120)} %");
Console.WriteLine(Nastroje.PruhZivotu(75, 120));

static class Nastroje
{
    public static int HodKostkou(Random kostka, int sten)
    {
        return kostka.Next(1, sten + 1);
    }

    public static int Procenta(int cast, int celek)
    {
        if (celek == 0)
        {
            return 0;
        }

        return cast * 100 / celek;
    }

    public static string PruhZivotu(int zivoty, int max)
    {
        int delka = zivoty * 20 / max;
        return $"│{new string('█', delka).PadRight(20, '░')}│ {zivoty}/{max}";
    }
}

Zkus si představit, kolikrát bys PruhZivotu psal bez modulu. Teď ho máš jednou — a když se ti nelíbí, opravíš ho na jednom místě.

Blok 4Co vlastně dělá `using`1. Vysvětlení a souvislosti

Na začátku skoro každého C# programu jsou řádky jako using System;. Znamenají: „budu používat věci z téhle skupiny, nechci psát jejich celé jméno."

Celé jméno třídy Console je totiž System.Console. Bez using bys musel psát:

System.Console.WriteLine("Ahoj");

S using System; stačí Console.WriteLine("Ahoj"). Nic víc v tom není — using nic nenačítá ani nestahuje, jen zkracuje psaní.

Zápis Co dělá
using System; zpřístupní krátká jména ze skupiny System
using System.Collections.Generic; odsud je List<T> a Dictionary<K,V>
using System.Linq; odsud je Sum, Where, OrderBy
using static System.Math; umožní psát Max(a, b) místo Math.Max(a, b)
using Kostky = Nastroje; dá třídě přezdívku (alias)
Proč to v našem editoru nevidíš

Moderní C# má takzvané implicitní usingy — nejběžnější skupiny (System, System.Linq, System.Collections.Generic a další) jsou zapnuté automaticky. Proto ti Console i List<T> fungují, i když jsi žádný using nenapsal. Ve starších projektech je uvidíš nahoře vypsané.

Blok 5`using static` a alias1. Vysvětlení a souvislosti

Dvě méně známé podoby using, které se hodí znát, až budeš číst cizí kód:

// alias = přezdívka pro dlouhý název; patří vždy úplně nahoru
using Kostky = Nastroje;

Console.WriteLine($"Vetší z čísel: {Math.Max(12, 30)}");
Console.WriteLine($"Odmocnina:     {Math.Sqrt(81)}");
Console.WriteLine($"Přes přezdívku: {Kostky.HodKostkou(new Random(3), 6)}");

static class Nastroje
{
    public static int HodKostkou(Random kostka, int sten)
    {
        return kostka.Next(1, sten + 1);
    }
}

Všimni si, že using Kostky = Nastroje; je na prvním řádku. Všechny using musí být nad příkazy — jinak překladač zahlásí chybu.

Kdy alias použít: když máš dvě třídy se stejným krátkým jménem z různých knihoven. Jinak ho nepoužívej — kód se tím hůř čte.

Blok 6Jmenný prostor (`namespace`)1. Vysvětlení a souvislosti

Když roste projekt, nestačí jména tříd — dvě knihovny můžou mít obě třídu Hrac. Proto se třídy zabalují do jmenných prostorů:

// soubor Data.cs
namespace CsQuest.Herni;

static class Data
{
    public const int CenaLektvaru = 25;
}

// soubor Program.cs
using CsQuest.Herni;

Console.WriteLine(Data.CenaLektvaru);

Čti to takhle: namespace je příjmení třídy. Celé jméno naší třídy je CsQuest.Herni.Data. Řádek using CsQuest.Herni; znamená „v tomhle souboru můžu říkat jen Data".

A tady je ten most, který si zapamatuj:

Python C#
import data using CsQuest.Herni;
data.MISTA Data.Mista
jeden soubor = jeden modul jeden soubor = jedna třída
modul najde podle názvu souboru třídu najde podle namespace v projektu
Tohle si v prohlížeči nespustíš

Blok výše je schválně jen na čtení — namespace naše tlačítko ▶ Spustit nepřeloží (ohlásí CS7021). Je to omezení prohlížečového režimu, ne chyba. Ve Visual Studio Code doma namespace funguje normálně a používá ho každý skutečný projekt.

Blok 7`public` a `internal` — kdo to uvidí1. Vysvětlení a souvislosti

U modulů je důležité rozhodnout, co je „vývěsní štít" a co je vnitřní šuplík:

Slovo Kdo na to vidí
public kdokoli, i cizí projekt
internal jen kód ve stejném projektu
private jen ta samá třída

Pravidlo pro dnešek: public jen to, co má někdo zvenku opravdu volat. Zbytek nech private. Modul se pak dá měnit zevnitř bez strachu, že tím něco rozbiješ jinde.

Console.WriteLine(Nastroje.PruhZivotu(60, 120));
Console.WriteLine(Nastroje.PruhZivotu(15, 120));

static class Nastroje
{
    private const int SirkaPruhu = 20;

    private static int Delka(int zivoty, int max)
    {
        return zivoty * SirkaPruhu / max;
    }

    public static string PruhZivotu(int zivoty, int max)
    {
        return $"│{new string('█', Delka(zivoty, max)).PadRight(SirkaPruhu, '░')}│ {zivoty}/{max}";
    }
}

Zvenku existuje jediná metoda PruhZivotu. Jak se počítá délka je vnitřní věc modulu — a to je přesně správně.

Blok 8Objekt na řádek a zpátky1. Vysvětlení a souvislosti

Poslední dnešní kousek. Když chceš postavu uložit, musíš z ní udělat text. A když ji chceš načíst, musíš text zase rozebrat. Dvě metody, které to řeší:

  • NaRadek() — objekt → text (je to metoda objektu, ví o sobě všechno),
  • ZRadku(...) — text → objekt (je static, protože objekt teprve vznikne).
Postava hrdina = new Postava("Elrik", 120, 13);
string radek = hrdina.NaRadek();

Console.WriteLine($"Uloženo jako: {radek}");

Postava nactena = Postava.ZRadku(radek);
Console.WriteLine($"Načteno zpět: {nactena.Jmeno}, {nactena.Zivoty} HP, síla {nactena.Sila}");

class Postava
{
    public string Jmeno { get; set; }
    public int Zivoty { get; set; }
    public int Sila { get; set; }

    public Postava(string jmeno, int zivoty, int sila)
    {
        Jmeno = jmeno;
        Zivoty = zivoty;
        Sila = sila;
    }

    public string NaRadek()
    {
        return $"{Jmeno};{Zivoty};{Sila}";
    }

    public static Postava ZRadku(string radek)
    {
        string[] casti = radek.Split(';');
        return new Postava(casti[0], int.Parse(casti[1]), int.Parse(casti[2]));
    }
}

Tenhle pár metod je základ každého ukládání hry. Na disk se to zapíše až doma (File.WriteAllLines), ale převod objektu na text je ta zajímavá část — a tu už umíš.

Poznámky pro učiteleTechnické pozadí1. Vysvětlení a souvislosti

Co se v C# opravdu děje. Python načítá modul za běhu: import data najde soubor data.py, spustí ho a vyrobí objekt modulu. C# nic takového nedělá — překladač dostane všechny .cs soubory projektu najednou a udělá z nich jednu sestavu (.dll nebo .exe). Rozdělení do souborů je proto v C# čistě organizační věc pro člověka, ne technická nutnost pro počítač.

Praktické důsledky, které stojí za zmínku:

  1. V C# neexistuje kruhový import. Problém, který v Pythonu trápí každého, tady prostě není — třídy se vidí navzájem bez ohledu na pořadí souborů.
  2. Kód v modulu se „nespustí". Pythonový modul se při importu vykoná, proto se tam píše if __name__ == "__main__":. C# spustí jen vstupní bod programu. Obdobou testovacího bloku je samostatný konzolový projekt nebo testovací projekt (xUnit).
  3. using není import. Nic nenačítá. Odkaz na cizí knihovnu se přidává jako balíček (dotnet add package) nebo reference na projekt. Přesné srovnání: pip installdotnet add package, importusing.
  4. Název souboru nemusí sedět s názvem třídy. Překladač to nekontroluje. Přesto na tom trvejte — je to nepsaný standard a IDE podle toho nabízí soubory.

Co dnes vědomě zjednodušujeme. Neřešíme partial class, sealed, file-scoped typy ani viditelnost napříč sestavami. Stačí, když si děti odnesou dvojici „soubor = třída" a using = zkratka jména".

Na co si dát pozor u hodnocení. Odměňujte krátkou hlavní část programu, ne počet tříd. Jedna dobře pojmenovaná Nastroje je lepší než pět tříd po jedné metodě.

Blok 9Časté chyby1. Vysvětlení a souvislosti
Chyba Jak se projeví Co s tím
metoda v modulu bez static CS0120 — je potřeba instance do statické třídy patří jen statické členy
new Data() CS0712 statická třída se nevyrábí, volá se přes tečku
zapomenuté public jinde ji „nevidíš" pomocné metody public, vnitřnosti private
namespace v okně s Spustit CS7021 namespace patří do projektu ve VS Code
třída nahoře mezi příkazy CS8803 příkazy nahoře, třídy dole
int.Parse na prázdný text výjimka za běhu zkontroluj Split a počet částí
všechno public static program vypadá jako jedna hromada ptej se: volá to někdo zvenku?

2. Ukázky pro projekci

Blok 10Ukázka 1 — Jeden soubor versus víc modulů2. Ukázky pro projekci

Napřed to, co většina z vás má teď: všechno v jednom. Pak to samé, jen rozdělené. Program dělá přesně totéž.

Studenti zkuste změnit
  • Přidej do Data.Mista čtvrté místo a spusť znovu.
  • Změň CenaLektvaru — kolik míst v kódu jsi musel upravit?
  • Přejmenuj Nastroje na Pomocnik (editor to zvládne, ty ručně).
  • Zkus zavolat Data.Mista bez slova Data a přečti si chybu.
demo/demo1_moduly.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

Co si z toho odnést: modul není o tom, že program umí víc. Je o tom, že se v něm dá orientovat.

Blok 11Ukázka 2 — Modul, který si hlídá své vnitřnosti2. Ukázky pro projekci

Dobrý modul ukazuje ven jen pár metod a zbytek schová. Tahle ukázka má sedm metod, ale zvenku se volají jen tři.

Studenti zkuste změnit
  • Změň SirkaPruhu na 30 a sleduj, kolik míst jsi musel upravit.
  • Zkus zavolat Nastroje.Delka(10, 100) — přečti si chybu.
  • Přidej metodu Nadpis(string text), která text orámuje.
  • Změň znak '█' za '#' a najdi, kde se mění.
demo/demo2_modul_uvnitr.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

Co si z toho odnést: private není omezení, ale svoboda. Co je uvnitř, můžeš kdykoli přepsat — zvenku to nikdo nepozná.

Blok 12Ukázka 3 — Modul s daty celé hry2. Ukázky pro projekci

Všechna čísla a texty hry na jednom místě. Když chceš hru vyladit, otevřeš jediný soubor a neriskuješ, že rozbiješ pravidla.

Studenti zkuste změnit
  • Zdraž lektvar na 40 a spusť — co se stalo s nákupem?
  • Přidej čtvrté místo i s jeho obtížností.
  • Změň StartovniZlato a sleduj celý výpis.
  • Přidej public const string NazevHry a použij ho v nadpisu.
demo/demo3_data_hry.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

Co si z toho odnést: vyvažování hry (jestli je moc lehká, nebo těžká) je pak otázka pár čísel v jednom souboru.

Blok 13Ukázka 4 — Postava, která se umí uložit2. Ukázky pro projekci

Objekt převedený na řádek textu a zase zpátky. To je celý základ ukládání hry.

Studenti zkuste změnit
  • Přidej postavě Zlato a dopiš ho do NaRadek() i do ZRadku().
  • Změň oddělovač z ; na | — pozor, musíš to změnit na obou místech.
  • Zkus načíst řádek, který má jen dvě části. Co se stane?
  • Přidej do družiny čtvrtou postavu a spusť znovu.
demo/demo4_ulozeni.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

Co si z toho odnést: NaRadek() a ZRadku() musí vždycky sedět k sobě. Když do jednoho něco přidáš, musíš to přidat i do druhého.

Blok 14Ukázka 5 — CsQuest po úklidu2. Ukázky pro projekci

Finální podoba: čtyři moduly a hlavní část, která se dá přečíst nahlas. Přesně takhle by měl tvůj projekt vypadat po dnešní hodině.

Studenti zkuste změnit
  • Změň jen Data.Obtiznosti a sleduj, jak se změní celá výprava.
  • Přidej do Souboj hlášku, když hrdina klesne pod 30 HP.
  • Přesuň výpis bilance do modulu Vypis.
  • Spočítej, kolik řádků má hlavní část. Kolik měla před úklidem?
demo/demo5_csquest_uklid.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

Co si z toho odnést: hlavní část programu má teď třicet řádků a čte se skoro jako popis hry. To je cíl.

Blok 15Když se něco pokazí2. Ukázky pro projekci

Chyby kolem modulů vypadají divoce, ale je jich jen pár druhů.

Hláška / projev Co se stalo Oprava
CS0120 voláš metodu bez static přes jméno třídy dopiš static k metodě
CS0708 v static class je nestatická položka ve statické třídě musí být všechno static
CS0712 new Data() u statické třídy statická třída se nevyrábí
CS0103 Mista místo Data.Mista k modulu se chodí přes tečku
CS0122 položka je private co se volá zvenku, musí být public
CS7021 namespace v okně se Spustit namespace jen ve VS Code, tady bez něj
CS8803 třída napsaná nad příkazy příkazy nahoře, třídy dole
CS0111 dvě metody stejného jména i parametrů přejmenuj jednu
IndexOutOfRangeException Split vrátil míň částí zkontroluj oddělovač a počet sloupců
FormatException int.Parse dostal text ukládáš a načítáš ve stejném pořadí?
vše je public static modul přestal chránit své vnitřnosti ptej se: volá to opravdu někdo zvenku?
Pro učitele — jak chybu diagnostikovat

Skoro každá dnešní chyba má stejný lék: přečíst hlášku a podívat se na slovo static. Nechte studenty hlášku přečíst nahlas dřív, než začnou cokoli měnit. Ušetří to polovinu času.

Chyby IndexOutOfRangeException a FormatException se objeví až u cvičení 4. Připravte si na ně jedno vysvětlení: „uložil jsi čtyři věci a načítáš tři — tvoje NaRadek a ZRadku si nerozumí."

3. Cvičení

Jak dnes pracovat: pět cvičení postupně rozebere jeden program na moduly a zase ho složí dohromady.
Blok 16Cvičení 1 — První modul (15 min)3. Cvičení

Zadání:

Vytáhni všechna data hry z hlavní části programu do vlastního modulu Data.

  1. Založ static class Data a dej do ní seznam míst
    💡 Poradit
    Statická třída patří — jako každá třída — pod příkazy:
    static class Data
    {
    public static List<string> Mista = new List<string> { "Mlžný hvozd" };
    }
    Nezapomeň na public i na static u položky.
  2. Vypiš místa přes Data.Mista
    💡 Poradit
    K obsahu modulu se chodí vždycky přes jméno třídy a tečku:
    foreach (string m in Data.Mista)
    Kdybys napsal jen Mista, dostaneš CS0103.
  3. Přidej konstanty NazevHry a CenaLektvaru
    💡 Poradit
    public const string NazevHry = "CsQuest";
    public const int CenaLektvaru = 25;
    U const se static nepíše — je statická automaticky.
  4. Přidej seznam předmětů a jejich cen
    💡 Poradit
    Dva seznamy vedle sebe (stejné pořadí), nebo rovnou slovník:
    public static Dictionary<string, int> Ceny = new Dictionary<string, int>
    {
    { "Lektvar", 25 },
    { "Meč", 90 }
    };
  5. Přidej nové místo a ověř, že se objeví samo
    💡 Poradit
    Dopiš řádek jen do Data.Mista a hlavní část nech úplně beze změny. Pokud se nové místo objevilo, modul funguje přesně tak, jak má.
Úroveň Co má zvládnout
Minimum Body 1–2, seznam míst v modulu
Rozšíření Body 3–4, konstanty a ceník
Výzva Bod 5 plus seznam nepřátel pro každé místo
cviceni/cviceni1_prvni_modul.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Pro učitele — na co si dát pozor

Očekávaný výsledek: hlavní část neobsahuje ani jedno napevno napsané číslo nebo název místa. Všechno je v Data.

Kde se zaseknou:

  1. Chybějící static u položkyCS0708. Připomeňte: ve statické třídě je všechno statické.
  2. Mista bez Data.CS0103. To je vlastně dobrá zpráva — překladač hlídá, že víme, odkud data bereme.
  3. Třída napsaná nahoruCS8803. Pravidlo z 15. hodiny platí i dnes.
  4. const u seznamuCS0133. const jde jen u čísel, textů a bool. U seznamu se používá static.

Krok 5 je pointa. Zdůrazněte, že se hlavní část nezměnila. Ptejte se: „kde bys přidával místo před hodinou?"

Rychlíkům zadejte Data.Nepratele — seznam seznamů, ke každému místu jeden.

Řešení 1 — jedna z možných variant

Toto je jedna z možných variant. Tvoje řešení se může lišit a to je v pořádku.

reseni/reseni1_prvni_modul.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 17Cvičení 2 — Modul s nástroji (20 min)3. Cvičení

Zadání:

Postav modul Nastroje s pomocnými metodami, které používáš pořád dokola.

  1. Vytvoř static class Nastroje s metodou HodKostkou(Random, int)
    💡 Poradit
    Metoda ve statické třídě musí být taky static:
    public static int HodKostkou(Random kostka, int sten)
    {
    return kostka.Next(1, sten + 1);
    }
    Pozor na sten + 1 — horní mez u Next se nikdy netrefí.
  2. Přidej Procenta(int cast, int celek)
    💡 Poradit
    Hlídej dělení nulou:
    if (celek == 0) { return 0; }
    return cast * 100 / celek;
    Násob nejdřív stem, jinak ti celočíselné dělení sežere výsledek.
  3. Přidej PruhZivotu(int zivoty, int max)
    💡 Poradit
    Spočítej délku plné části a zbytek dopadni tečkami:
    int delka = zivoty * 20 / max;
    return new string('█', delka).PadRight(20, '░');
  4. Schovej pomocné výpočty jako private
    💡 Poradit
    Konstantu šířky i výpočet délky nikdo zvenku nepotřebuje:
    private const int SirkaPruhu = 20;
    private static int Delka(int zivoty, int max) { ... }
    Zvenku zůstane viditelná jen PruhZivotu.
  5. Použij modul v malé simulaci tří kol
    💡 Poradit
    Založ Random kostka = new Random(4);, v cyklu ubírej životy o Nastroje.HodKostkou(kostka, 10) a po každém kole vypiš Nastroje.PruhZivotu(...). Seed 4 zajistí, že výsledek bude pokaždé stejný.
Úroveň Co má zvládnout
Minimum Body 1–2, dvě funkční metody
Rozšíření Body 3–4, pruh životů a private vnitřnosti
Výzva Bod 5 plus metoda Nadpis(string) s rámečkem
cviceni/cviceni2_nastroje.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Pro učitele — na co si dát pozor

Očekávaný výsledek: hlavní část neobsahuje žádný výpočet. Jen volání Nastroje.Neco(...) a výpisy.

Kde se zaseknou:

  1. cast / celek * 100 → vždycky 0. Celočíselné dělení. Násob první.
  2. kostka.Next(1, sten) → nikdy nepadne nejvyšší číslo. Nechte je to odhalit na k6: kdo dostane šestku?
  3. Zapomenuté static u metodyCS0708 nebo CS0120.
  4. private metoda volaná zvenkuCS0122. To je správně! Ukažte, že překladač hlídá hranici modulu.
  5. Chybějící Math.Max(0, zivoty) → při záporných životech spadne new string('█', -3). Dobrá příležitost ukázat, že modul má být odolný.

Diskuse na závěr: zeptejte se, kolikrát v jejich CsQuestu počítají procenta. Obvykle třikrát až pětkrát, pokaždé trochu jinak. To je přesně ten důvod.

Rychlíkům zadejte Nastroje.Zarovnej(string text, int sirka) nebo metodu, která vrátí barevný stav ("v pohodě" / "zraněn" / "kriticky").

Řešení 2 — jedna z možných variant

Toto je jedna z možných variant. Tvoje řešení se může lišit a to je v pořádku.

reseni/reseni2_nastroje.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 18Cvičení 3 — Třídy do vlastního souboru (20 min)3. Cvičení

Zadání:

Rozděl program na tři „soubory": třídu Postava, modul Vypis a hlavní část.

  1. Napiš třídu Postava s konstruktorem a ToString()
    💡 Poradit
    Obyčejná třída, tedy bez static — postav chceš víc:
    class Postava
    {
    public string Jmeno { get; set; }
    public Postava(string jmeno, int zivoty) { ... }
    }
  2. Přidej modul Vypis s metodou Radek(Postava p)
    💡 Poradit
    Modul dostane celou postavu jako parametr:
    public static string Radek(Postava p)
    {
    return $"{p.Jmeno,-8} {p.Zivoty,4} HP";
    }
    Musí být static, protože Vypis je statická třída.
  3. Přidej Vypis.Nadpis() a Vypis.Cara()
    💡 Poradit
    Čáru sestavíš z opakovaného znaku:
    public static string Cara() => new string('═', 46);
    Nadpis pak vypadá jako čára, text, čára.
  4. Ohranič každou část komentářem „souboru"
    💡 Poradit
    Před třídu napiš // ===== soubor Postava.cs ===== a za ni // ===== konec Postava.cs =====. Doma ve VS Code to bude opravdový soubor a tyhle komentáře zmizí.
  5. Vypiš celou družinu jednou smyčkou
    💡 Poradit
    List<Postava> druzina = new List<Postava>();
    Naplň ji a pak:
    foreach (Postava p in druzina) { Console.WriteLine(Vypis.Radek(p)); }
    Hlavní část má tak jen pár řádků.
Úroveň Co má zvládnout
Minimum Body 1–2, třída a jeden výpis
Rozšíření Body 3–4, nadpis a hranice „souborů"
Výzva Bod 5 plus součet a průměr přes celou družinu
cviceni/cviceni3_tridy_do_modulu.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Pro učitele — na co si dát pozor

Očekávaný výsledek: tři jasně oddělené části. Postava neví nic o výpisu, Vypis nic nepočítá o soubojích, hlavní část jen spojuje.

Kde se zaseknou:

  1. static u PostavaCS0712 při new Postava(...). Ptejte se: kolik jich potřebuješ? Jednu, nebo víc? Data a nástroje = static. Věci, kterých je víc = normální třída.
  2. Vypis.Radek bez staticCS0708.
  3. Vypis jako obyčejná třída → funguje to, ale musí se psát new Vypis().Radek(p). Ukažte, proč je static lepší.
  4. Dělení nulou v pruhu — když někdo zapomene MaxZivotu, je tam 0 a program spadne. Dobrá lekce o výchozích hodnotách.

Klíčová otázka pro celou třídu: „proč Vypis nepatří dovnitř Postavy?" Odpověď: aby šlo změnit vzhled, aniž by se sáhlo na pravidla hry. Tomu se říká oddělení odpovědností a je to nejdůležitější myšlenka hodiny.

Rychlíkům zadejte Vypis.Tabulka(List<Postava>), která vypíše celou družinu včetně nadpisu a součtů jediným voláním.

Řešení 3 — jedna z možných variant

Toto je jedna z možných variant. Tvoje řešení se může lišit a to je v pořádku.

reseni/reseni3_tridy_do_modulu.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 19Cvičení 4 — Ukládání postav (20 min)3. Cvičení

Zadání:

Nauč postavu převést se na řádek textu a zase se z něj složit.

  1. Přidej Postava metodu NaRadek()
    💡 Poradit
    Obyčejná metoda objektu — ví o sobě všechno:
    public string NaRadek()
    {
    return $"{Jmeno};{Zivoty};{Sila}";
    }
    Středník jako oddělovač se hodí, protože se v jménech nevyskytuje.
  2. Přidej statickou metodu ZRadku(string)
    💡 Poradit
    Musí být static — objekt teprve vznikne:
    public static Postava ZRadku(string radek)
    {
    string[] casti = radek.Split(';');
    return new Postava(casti[0], int.Parse(casti[1]), int.Parse(casti[2]));
    }
  3. Ulož celou družinu do List&lt;string&gt;
    💡 Poradit
    Simulujeme soubor seznamem řádků:
    List<string> soubor = new List<string>();
    foreach (Postava p in druzina) { soubor.Add(p.NaRadek()); }
    Doma z toho bude File.WriteAllLines("hra.txt", soubor).
  4. Načti družinu zpátky a ověř, že sedí
    💡 Poradit
    Projdi řádky a skládej nové objekty:
    foreach (string r in soubor) { nactena.Add(Postava.ZRadku(r)); }
    Potom porovnej Sum nebo Count původní a načtené družiny.
  5. Ošetři poškozený řádek
    💡 Poradit
    Před rozebráním zkontroluj počet částí a použij int.TryParse:
    if (casti.Length != 3) { return null; }
    if (!int.TryParse(casti[1], out int z)) { return null; }
    Návratový typ pak bude Postava? a při načítání null přeskočíš.
Úroveň Co má zvládnout
Minimum Body 1–2, jeden objekt tam a zpět
Rozšíření Body 3–4, celá družina
Výzva Bod 5 plus hlášení, kolik řádků bylo poškozených
cviceni/cviceni4_ukladani.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Pro učitele — na co si dát pozor

Očekávaný výsledek: NaRadek() a ZRadku() tvoří pár — co jedna zapíše, druhá přečte. Tomu se v praxi říká serializace.

Kde se zaseknou:

  1. ZRadku bez staticCS0120. Vysvětlení pro děti: „nemůžeš zavolat metodu objektu, který ještě neexistuje."
  2. Nesedící pořadíNaRadek píše jméno, životy, sílu; ZRadku čte jméno, sílu, životy. Program nespadne, jen se hra rozbije. To je nejzákeřnější chyba dneška — nechte je ji najít samy.
  3. Přidaná vlastnost jen do jedné metodyIndexOutOfRangeException. Pravidlo: sáhneš na jednu, sáhni hned na druhou.
  4. int.Parse versus int.TryParse — ukažte rozdíl na řádku Kája;devadesát;18. Parse shodí celý program, TryParse ho zachrání.
  5. Postava? s otazníkem — to je jen poznámka pro překladač, že metoda smí vrátit null. Neřešte hlouběji, stačí „může vrátit nic".

Proč neukládáme na disk. V prohlížeči nemáme soubory. Seznam řádků se ale chová úplně stejně — a doma stačí přidat File.WriteAllLines / File.ReadAllLines. Tuhle větu řekněte nahlas, ať vědí, že jim nic nechybí.

Rychlíkům zadejte ukládání ve formátu klíč=hodnota (jmeno=Elrik;hp=120), které přežije i změnu pořadí sloupců.

Řešení 4 — jedna z možných variant

Toto je jedna z možných variant. Tvoje řešení se může lišit a to je v pořádku.

reseni/reseni4_ukladani.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 20Cvičení 5 — CsQuest: velký úklid (25 min)3. Cvičení

Zadání:

Rozděl celý CsQuest na čtyři moduly. Hlavní část má zůstat krátká a čitelná.

  1. Založ modul Data se všemi čísly a texty hry
    💡 Poradit
    Do Data patří všechno, co bys chtěl ladit: názvy míst, obtížnosti, startovní zlato, ceny. Pravidlo: když je v hlavní části číslo, patří do Data.
  2. Přidej modul Nastroje s kostkou a pruhem
    💡 Poradit
    Vezmi metody z cvičení 2 — HodKostkou a PruhZivotu. Nic nevymýšlej znovu, jen je zkopíruj do nové statické třídy.
  3. Přesuň Postava do vlastního „souboru"
    💡 Poradit
    Třída Postava ať umí Utoc, Zranit a Zije. Pravidla postavy patří do postavy, ne do hlavní části.
  4. Přidej modul Hra s metodou Souboj(...)
    💡 Poradit
    public static bool Souboj(Postava hrdina, string nepritel, int obtiznost, Random r)
    Vrať true při vítězství. Uvnitř nech cyklus, ale vždy s pojistkou kolo <= 20, ať se nezacyklí.
  5. Nech v hlavní části jen průběh výpravy
    💡 Poradit
    Hlavní část má být skoro jako scénář:
    foreach místo → Hra.Souboj(...) → výpis → když padne, break
    Spočítej si řádky. Míň než 30 je výborné.
Úroveň Co má zvládnout
Minimum Body 1–2, data a nástroje mimo hlavní část
Rozšíření Body 3–4, postava a souboj ve svých modulech
Výzva Bod 5 plus závěrečná bilance a hodnost podle zlata
cviceni/cviceni5_velky_uklid.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Pro učitele — na co si dát pozor

Očekávaný výsledek: hlavní část má kolem 25 řádků a dá se přečíst nahlas jako popis hry. Všechno ostatní je ve čtyřech pojmenovaných modulech.

Kde se zaseknou:

  1. Nevědí, co kam patří. Dejte jim rozhodovací otázku: „je to číslo nebo text? → Data. Počítá to něco obecného? → Nastroje. Je to vlastnost hrdiny? → Postava. Je to pravidlo hry? → Hra."
  2. Zapomenuté static — pořád dokola. Tentokrát už by měli hlášku znát.
  3. Cyklení souboje — bez pojistky kolo <= 20 může souboj běžet věčně, když hrdina neublíží dost. Pojistka je v zadání schválně.
  4. Kopírování místo přesouvání — zůstane jim starý kód v hlavní části. Připomeňte: smaž, co jsi přesunul.

Měřte to. Nechte je před začátkem spočítat řádky hlavní části a po skončení znovu. Ten rozdíl je nejlepší hodnocení dnešní hodiny.

Tři minuty na závěr: ať každý řekne, který modul se mu psal nejlíp. Většinou Data — a to je dobře, protože je to i ten nejužitečnější.

Rychlíkům zadejte modul Ulozeni s metodami Uloz(List<Postava>) a Nacti(List<string>), které využijí NaRadek() ze cvičení 4.

Řešení 5 — jedna z možných variant

Toto je jedna z možných variant. Tvoje řešení se může lišit a to je v pořádku.

reseni/reseni5_velky_uklid.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

4. Domácí úkol

Blok 21Domácí úkol na příští hodinu4. Domácí úkol

Ukliď svůj CsQuest do modulů a přines ho na příští hodinu — bude to základ finále.

  • modul Data se všemi čísly a texty hry (žádné číslo v hlavní části),
  • modul Nastroje s alespoň třemi pomocnými metodami,
  • třídy Postava a Prisera v jasně oddělených „souborech",
  • modul Hra s aspoň jednou metodou, která řídí souboj nebo výpravu,
  • v hlavní části méně než 40 řádků — jen průběh hry.

Bonus: přidej NaRadek() a ZRadku(), aby se postava dala uložit a načíst.

Pro učitele

Tohle je poslední „stavební" úkol kurzu. Příští hodina je finále — a je mnohem příjemnější, když děti přijdou s programem, ve kterém se dá něco najít. Zdůrazněte to: „příště budete svoji hru ukazovat ostatním. Uklizený kód se předvádí líp."

Na co se při kontrole dívat: ne na počet modulů, ale na délku hlavní části. Nechte je napsat na první řádek komentář s počtem řádků hlavní části před úklidem a po něm. Ten rozdíl je celá známka.

Kdo to nestihne, ať ukliďí aspoň Data. Je to nejmenší krok s největším viditelným efektem a nikoho nezablokuje.

Pro ty, kdo pracují doma ve VS Code: tady je ten úkol nejlepší — můžou vyrobit opravdové soubory Data.cs, Nastroje.cs, Postava.cs, Hra.cs a Program.cs. Připomeňte, že dotnet run je najde sám a nic se nemusí „importovat".

Zobrazit ukázkové řešení domácího úkolu

Toto je jedna z možných variant, jak mohl úkol dopadnout. Tvoje řešení se může lišit a to je v pořádku.

domaci/domaci_ukol17.cs
Tady se objeví výstupKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 22Oficiální dokumentace4. Domácí úkol

Oficiální dokumentace je místo, kam se programátoři chodí podívat, když si chtějí něco ověřit nebo zjistit víc detailů. Je většinou v angličtině, ale to nevadí — zkus se orientovat podle názvu příkazu a podle ukázek kódu.

Co jsme použili Oficiální dokumentace Co tam najdeš
namespace Jmenné prostory k čemu jsou a jak se skládají jména
using Direktiva using všechny tři podoby včetně aliasů
implicitní usingy Implicitní using proč nemusíš psát using System;
static class Statické třídy kdy se hodí a co do nich patří
public / internal / private Modifikátory přístupu kdo na co zvenku vidí
struktura projektu Struktura projektu .NET co je .csproj a jak najde soubory
string.Split String.Split rozdělení textu na části
string.Join String.Join spojení částí zpátky do řádku
int.TryParse Int32.TryParse bezpečný převod textu na číslo
List<T> List<T> seznam řádků, ze kterého se skládá výpis
File.WriteAllLines File zápis a čtení souborů (doma ve VS Code)
balíčky dotnet add package obdoba pip install z jiných jazyků
Jak s dokumentací pracovat na hodině

Stránka o statických třídách je dnes nejužitečnější — má tam přesně ten příklad s pomocnými metodami, který stavíme ve cvičení 2.

Stránku o struktuře projektu ukažte na projektoru i těm, kdo nepracují doma. Stačí, když uvidí, že .csproj nevyjmenovává soubory — bere prostě všechny .cs v adresáři. Je to nejrychlejší způsob, jak pochopit rozdíl proti jazykům, kde se moduly musí ručně importovat.

5. Umíme informatiku

Blok 23Navazující cvičení na Umíme informatiku5. Umíme informatiku

Pro rychlejší studenty, kteří dokončí cvičení dřív, nebo na posledních 10–15 minut.

Cvičení Odkaz Proč se hodí
Programování — základy umimeinformatiku.cz čtení cizího kódu, dnes hlavně orientace v delším programu
Funkce a procedury umimeinformatiku.cz parametry a návratové hodnoty — základ každého modulu
Práce s textem umimeinformatiku.cz Split a Join, které dnes používáme při ukládání

Sekce o funkcích je dnes nejvhodnější, protože modul není nic jiného než dobře pojmenovaná sbírka funkcí.

Jak to zařadit

Ještě lepší bonus než online cvičení je ale tahle úloha: „Vezmi cizí program od spolužáka a rozděl ho na moduly. Nesmíš změnit, co dělá — jen kam to patří."

Refaktoring cizího kódu je dovednost, kterou v běžné výuce skoro nikdo netrénuje, a přitom je to v praxi to nejčastější, co programátor dělá. Navíc se u toho děti musí domluvit, což je půlka práce v týmu.