Dictionary<TKey,TValue>, klíč a hodnota, hranaté závorky, ContainsKey, TryGetValue, foreach přes slovník, Keys a ValuesProgram.cs z minulé hodiny — nebo jen prohlížečList<T> a práci s textem.Dictionary.Tenhle blok je jen pro vás — dětem ho nepromítejte.
| Fáze | Co se děje | Čas |
|---|---|---|
| Rozjezd | Připomenutí seznamu, ukázka „co je ta trojka?" | 10 min |
| Výklad + ukázky | Bloky 2–8, střídáte mluvení a promítání kódu | 40 min |
| Ukázky pro projekci | Pět hotových programů, píšete je živě | 20 min |
| Cvičení | Děti pracují samy, vy obcházíte | 60 min |
| Závěr | Kdo chce, ukáže svůj bestiář | 10 min |
Dnešek není o nové syntaxi, ale o pojmenování dat. Dítě, které pochopí,
že prisera["zivoty"] je čitelnější než prisera[1], udělalo první krok
k programování ve velkém.
Druhý cíl je oddělit data od kódu. Až budou mít ceník ve slovníku nahoře v souboru, můžou přidat nové zboží bez sahání do zbytku programu. Tuhle myšlenku zopakujte nahlas alespoň třikrát.
KeyValuePair<TKey,TValue> jako typ. U foreach pište var a řekněte
„dvojice klíč-hodnota". Generika se probírají až u tříd.out parametr u TryGetValue. Berte to jako hotové zaklínadlo:
„zkus najít, a když najdeš, dej mi to do téhle proměnné."Jak pracovat se smíšenou úrovní. Každé cvičení má tři stupně: Minimum,
Rozšíření, Výzva. Slabším stačí, když zvládnou jeden slovník a čtení hranatými
závorkami. Rychlíky posílejte na TryGetValue a na vnořené struktury —
mají v tom hodinu zábavy.
Podívej se na ten kód a odpověz: co je ta osmička?
Životy? Síla? Zlato za zabití? Nevíš to. A za týden to nebudeš vědět ani ty, kdo to napsal.
Seznam si pamatuje pořadí. To je skvělé u inventáře, kde má smysl mluvit o „prvním předmětu". Ale u příšery pořadí nic neznamená — tam potřebuješ jména.
A je tu druhý problém: kdyby někdo doprostřed vložil další údaj, posunou se všechny indexy a celý program se rozbije.
Tady se ptát nemusíš. prisera["sila"] je osmička a je to síla. Tečka.
Slovník (
Dictionary) je krabice, ve které má každá hodnota jmenovku. Místo čísla pozice použiješ klíč — a ten si vymýšlíš ty.
Analogie, která dětem sedí: seznam je řada čísel dveří, slovník je jmenovka na dveřích. Když se do domu nastěhuje nový soused, jmenovky ostatních zůstanou stejné.
Všimni si, že v hranatých závorkách je text v uvozovkách, ne číslo.
Zápis vypadá děsivě, ale má jen tři části. Čti ho takhle:
Dictionary<string, int>— „slovník, kde klíč je text a hodnota je číslo".
<string, int> — první typ je klíč (jmenovka), druhý je hodnota.
Tady: jméno zboží → cena.= new Dictionary<string, int> — vyrob nový prázdný slovník.{ ["meč"] = 90, ... } ** — a rovnou do něj nasyp tyhle dvojice.
Za poslední dvojicí čárka být může i nemusí.cenik.Count řekne, kolik dvojic ve slovníku je. Tady tři.
Pozor na jednu věc, která Python nemá: v C# musí mít všechny hodnoty
stejný typ. Do Dictionary<string, int> nedáš text. Když potřebuješ
i jméno příšery, buď si ho dej do obyčejné proměnné, nebo udělej druhý slovník
typu Dictionary<string, string>.
Dictionary = slovníkstring v prvním okénku = klíč je textint v druhém okénku = hodnota je číslo["meč"] = hranaté závorky, uvnitř klíč v uvozovkáchCelé to čti: „slovník z textu na číslo, jménem ceník, a v něm meč za devadesát."
Čtyři operace, které dnes potřebuješ:
| Zápis | Co dělá |
|---|---|
prisera["zivoty"] |
přečte hodnotu pod klíčem |
prisera["zivoty"] = 20; |
změní existující hodnotu |
prisera["zlato"] = 25; |
přidá nový klíč, když ještě není |
prisera.Remove("sila"); |
smaže klíč i s hodnotou |
Všimni si zvláštnosti: přidání a změna se píšou úplně stejně. Slovník se nezlobí — když klíč není, vyrobí ho; když je, přepíše ho.
To je velký rozdíl proti seznamu. Tam by inventar[5] = "meč" na neexistujícím
indexu program shodilo.
Čtení je přísnější než zápis. prisera["magie"], když klíč magie neexistuje,
program shodí výjimkou KeyNotFoundException. Je to jedna z nejčastějších
chyb dnešní hodiny — a v dalším bloku se naučíš, jak se jí vyhnout.
ContainsKey je otázka „máš to?" Vrátí true nebo false a program
nespadne. Používej ji vždycky, když klíč pochází od uživatele.
Čti to jako větu: „jestli ceník obsahuje klíč zboží, tak…"
Tohle je nejčastější vzor celé hodiny:
Nejdřív se zeptej, jestli klíč existuje. Teprve pak ho čti.
Zkus si přepsat zbozi na "meč" a spustit znovu.
TryGetValue je zkratka, která dělá dvě věci naráz: podívá se, jestli
klíč existuje, a když ano, rovnou ti hodnotu podstrčí do proměnné.
out int cena — „a hodnotu mi dej ven do nové proměnné cena".
Proměnnou nemusíš vyrábět dopředu, vznikne tady.true, když se to povedlo, jinak false.Proč to existuje, když je ContainsKey? Protože ContainsKey + cenik[klíč]
hledá ve slovníku dvakrát. TryGetValue jednou. U ceníku o třech položkách
je to jedno, u tisíce položek už ne.
Pro dnešek stačí ContainsKey. TryGetValue je Rozšíření pro ty,
komu se líbí, že je kratší.
foreach přes slovník dává dvojice. Každé kolo dostaneš jednu dvojici
klíč + hodnota a ptáš se jí na dvě věci:
polozka.Key — klíč (tady jméno příšery),polozka.Value — hodnota (tady životy).Velká písmena u Key a Value jsou povinná. polozka.key nefunguje.
Programátoři té proměnné většinou říkají
kvp(z anglického key-value pair). V cizím kódu uvidíšforeach (var kvp in bestiar)— je to úplně totéž, jen jiné jméno krabice.
Pořadí není zaručené. Slovník ti položky vrátí v nějakém pořadí, ale nesmíš na něj spoléhat. Když potřebuješ pořadí, použij seznam.
Někdy tě zajímá jen jedna polovina slovníku:
bestiar.Keys — jenom klíče. Hodí se na výpis nabídky.bestiar.Values — jenom hodnoty. Hodí se na sčítání.Všimni si v druhém foreach vzoru, kterému se říká akumulátor:
před cyklem si připravíš proměnnou na nulu a v každém kole do ní přičteš.
Po cyklu v ní máš součet.
Tenhle vzor je základ příští hodiny o cyklech — dnes si ho jen vyzkoušej.
A ještě jedna drobnost: bestiar.ContainsValue(120) se ptá na hodnotu
místo na klíč. Používá se zřídka, protože musí projít celý slovník.
Tohle je nejužitečnější trik se slovníkem vůbec: počítání, kolikrát se něco objevilo.
Postup je pokaždé stejný:
new Dictionary<string, int>(),
za kterým nejsou složené závorky, jen kulaté.V CsQuestu to použiješ na inventář: lektvar 3×, mince 12×.
Nemusíš mít seznam s dvanácti mincemi za sebou, stačí jedna dvojice.
Zkrácený zápis inventar[vec]++ dělá totéž jako inventar[vec] = inventar[vec] + 1.
Protože v C# musí mít slovník jeden typ hodnot, popíšeš složitější věc tak, že si uděláš víc slovníků se stejnými klíči.
zivoty["Drak"] → číslo 120popisy["Drak"] → text s popisemKlíč "Drak" je spojka mezi oběma tabulkami. Když si v jednom slovníku
napíšeš klíč s překlepem, druhý ho nenajde — a program spadne.
Proto si klíče piš malými písmeny a bez diakritiky, jakmile jich bude víc
než pět.
Tohle je zatím trochu kostrbaté. V 16. hodině se naučíš třídy a příšeru popíšeš jedním objektem, který má jméno, životy i popis pohromadě. Dnešní slovníky jsou na to poctivá příprava.
Věci, které dětem dnes neříkejte, ale vy je vědět potřebujete.
Proč je slovník rychlý. Dictionary<TKey,TValue> je hashovací tabulka.
Z klíče se spočítá číslo (hash), to určí přihrádku, a v ní se hledá.
Vyhledání je proto v průměru O(1) — nezávisle na tom, jestli má slovník
deset nebo deset milionů položek. Seznam musí procházet postupně, tedy O(n).
Dětem to neříkejte dnes; vrátíme se k tomu u algoritmů ve 12. hodině.
Pořadí položek. Dictionary negarantuje pořadí. V praxi to u malých
slovníků vypadá jako pořadí vložení, ale spoléhat se na to nesmíte —
po smazání klíče se pořadí rozhodí. Když je pořadí potřeba, existuje
SortedDictionary<TKey,TValue> (řadí podle klíče). Pro tuhle hodinu to nepotřebujete.
Rozdíl proti Pythonu. Kdo zná Python, narazí na tři věci:
| Python | C# |
|---|---|
{"a": 1} jde míchat typy |
všechny hodnoty musí mít stejný typ |
d.get("x", 0) |
TryGetValue nebo ContainsKey |
for k, v in d.items() |
foreach (var kvp in d) + .Key / .Value |
out parametr. TryGetValue(klíč, out int cena) používá out proměnnou
deklarovanou na místě (C# 7+). Proměnná cena platí i za if blokem.
Když klíč nenajde, je v ní default(TValue), tedy 0 pro int
a null pro string. Dětem stačí „nula".
Klíče a velikost písmen. cenik["Meč"] a cenik["meč"] jsou dva různé klíče.
Kdo chce nerozlišovat, vyrobí slovník jako
new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase).
Nechte si to jako trik do rukávu, až se někdo bude divit.
Inicializátor { ["a"] = 1 } vs. { {"a", 1} }. Obojí je platné.
My držíme první tvar, protože vypadá stejně jako pozdější čtení hranatými
závorkami, a to dětem pomáhá.
Dictionary a živé spouštění. Všechno z dnešní hodiny běží v prohlížeči
bez problémů — slovníky jsou čistá paměť, žádné soubory ani síť.
obrana) a vypiš ho.zivoty na polovinu pomocí prisera["zivoty"] = prisera["zivoty"] / 2;.Co si z toho odnést: hranaté závorky s textem uvnitř. prisera["sila"]
se čte jako „síla té příšery" — a nikdo se nemusí ptát, co znamená osmička.
poptavka na zboží, které v ceníku není. Co se vypíše?cenik["meč"] = cenik["meč"] + 10;.Co si z toho odnést: ContainsKey je pojistka. Nejdřív se zeptej,
jestli klíč existuje, teprve pak ho čti hranatými závorkami.
bestiar.Keys.bestiar.Count.Co si z toho odnést: dva vzory, které budeš používat pořád — akumulátor (sčítám do proměnné) a hledání maxima (pamatuju si zatím největší).
nalezy další věci a spusť znovu.nalezy necháš prázdné: { }.inventar[vec]++ místo dlouhého zápisu.Co si z toho odnést: slovník umí počítat. Vzor „je tam? přičti : není? založ na jedné" potkáš v programování do konce života.
kde na jiné místo a spusť znovu.odmeny (místo → zlato) a vypiš ho ve výpisu místa.Co si z toho odnést: tři slovníky se stejnými klíči tvoří dohromady data hry. Přidat nové místo znamená dopsat řádek do každého slovníku — a zbytku programu se nedotkneš.
Unhandled exception. System.Collections.Generic.KeyNotFoundException:
The given key 'magie' was not present in the dictionary.
Nejčastější chyba dnešní hodiny. Přečti ji zleva:
KeyNotFoundException — klíč nenalezen,'magie' — přesně ten klíč, který jsi chtěl číst,was not present in the dictionary — ve slovníku prostě není.Příčina bývá jedna ze tří: překlep, velké písmeno ("Magie" ≠ "magie"),
nebo klíč, který se do slovníku ještě nestihl dostat.
Oprava je vždycky stejná: před čtením se zeptej ContainsKey,
nebo použij TryGetValue.
| Hláška | Co to znamená | Jak to opravit |
|---|---|---|
KeyNotFoundException |
klíč ve slovníku není | před čtením if (slovnik.ContainsKey(klic)) |
ArgumentException: An item with the same key has already been added |
dvakrát stejný klíč v inicializátoru | jeden z nich smaž nebo přejmenuj |
CS0029: Cannot implicitly convert type 'string' to 'int' |
dáváš text do Dictionary<string, int> |
buď oprav hodnotu, nebo udělej slovník <string, string> |
CS1061: 'KeyValuePair<...>' does not contain a definition for 'key' |
malé písmeno | musí být .Key a .Value |
CS0021: Cannot apply indexing with [] to an expression of type ... |
indexuješ něco, co není slovník ani seznam | zkontroluj jméno proměnné |
CS1503: cannot convert from 'int' to 'string' |
v hranatých závorkách je číslo místo klíče | klíč patří do uvozovek: cenik["meč"] |
| vypíše se jiné pořadí, než čekáš | slovník pořadí negarantuje | nespoléhej na něj, nebo použij seznam |
Tvoje zadání:
Každá příšera v CsQuestu potřebuje kartu. Uděláš ji ze slovníku, aby bylo na první pohled vidět, co které číslo znamená.
- Vyrob slovník
priseratypuDictionary<string, int>s klíči"zivoty","sila"a"zlato".💡 Poradit
Zápis jenew Dictionary<string, int> { ["zivoty"] = 30, ... };.
Klíč patří do uvozovek, hodnota je číslo.- Vypiš kartu — tři řádky ve tvaru
Životy: 30.💡 Poradit
Čti hranatými závorkami:prisera["zivoty"].
Uvnitř$"..."to dej do složených závorek.- Příšera dostala ránu — sniž jí životy o 12 a vypiš nový stav.
💡 Poradit
Změna se píše jako přiřazení:prisera["zivoty"] = prisera["zivoty"] - 12;.- Přidej nový klíč
"obrana"s hodnotou 4 a vypiš, kolik má karta údajů.💡 Poradit
Přidání vypadá stejně jako změna.
Počet dvojic zjistíš přesprisera.Count.- Vypiš celou kartu cyklem
foreach— každý řádek jakoklíč: hodnota.💡 Poradit
foreach (var polozka in prisera)a uvnitřpolozka.Keyapolozka.Value.
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | slovník se třemi klíči a výpis hranatými závorkami (kroky 1–2) |
| Rozšíření | změna hodnoty, přidání klíče, Count (kroky 3–4) |
| Výzva | výpis přes foreach a zarovnání sloupců přes PadRight (krok 5) |
Očekávaný výsledek: karta se třemi řádky, po ráně 18 životů,
po přidání obrany Count čtyři a nakonec výpis čtyř dvojic pod sebou.
Kde se zaseknou:
- Píšou prisera[zivoty] bez uvozovek → CS0103: The name 'zivoty' does not exist.
Klíč je text, patří do uvozovek.
- Píšou prisera.zivoty. To je syntaxe tříd, ne slovníku.
- U kroku 5 napíšou polozka.key malým písmenem → CS1061.
- Zapomenou, že jmeno není v tom slovníku — ve výpisu přes foreach
se pak diví, že tam jméno není. Je to správně: jmeno je string,
do Dictionary<string, int> nepatří.
Kdo je hotový dřív: ať přidá druhou příšeru jako druhý slovník a vypíše obě karty pod sebou. Nebo ať zjistí, kolik zlata příšera nese, když ji porazí dvakrát.
Otázka na závěr: „Proč je prisera["sila"] lepší než prisera[1]?"
Odpověď, kterou chcete slyšet: protože je z toho vidět, co to číslo znamená,
a nerozbije se to, když přidáme další údaj.
Tvoje zadání:
Obchod U tří seker potřebuje ceník. Hrdina do něj sáhne, koupí si zboží a obchod mu poctivě odečte zlato.
- Vyrob slovník
cenikse čtyřmi druhy zboží a jejich cenami.💡 Poradit
Klíč je jméno zboží, hodnota je cena.["meč"] = 90,a tak dál.- Vypiš celou nabídku cyklem
foreach— jméno vlevo, cena vpravo.💡 Poradit
Zarovnání udělápolozka.Key.PadRight(10).- Zjisti, jestli je zboží z proměnné
poptavkav ceníku. Když ne, napiš to.💡 Poradit
Použijif (cenik.ContainsKey(poptavka))a větevelse.- Když zboží existuje a hrdina má dost zlata, odečti cenu a vypiš zůstatek.
💡 Poradit
Vnořená podmínka:if (zlato >= cena).
Pakzlato = zlato - cena;.- Nakonec zdraž všechno zboží o 10 zlaťáků a vypiš nový ceník.
💡 Poradit
Procházejforeach (string klic in cenik.Keys.ToList())a uvnitřcenik[klic] = cenik[klic] + 10;.ToList()je tam proto, abys mohl slovník měnit během procházení.
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | ceník a jeho výpis cyklem (kroky 1–2) |
| Rozšíření | ContainsKey a nákup s kontrolou zlata (kroky 3–4) |
| Výzva | hromadné zdražení přes Keys.ToList() (krok 5) |
Očekávaný výsledek: nabídka čtyř položek, štít za 60, po nákupu zbývá 60 zlata, pak ceník o deset dražší.
Kde se zaseknou:
- U kroku 5 zapomenou ToList() a dostanou
InvalidOperationException: Collection was modified.
Vysvětlení pro děti: „nemůžeš přestavovat regál, zatímco po něm chodíš.
ToList() si udělá papírový seznam jmen a podle něj pak měníš."
- Zkoušejí foreach (var polozka in cenik) { polozka.Value = ... } —
to nejde, Value se měnit nedá. Musí přes klíč.
- Zapomenou int cena = cenik[poptavka]; a pak píšou cenik[poptavka] třikrát.
Funguje to, ale ukažte jim, že proměnná je čitelnější.
Kdo je hotový dřív: ať přidá druhou položku k nákupu, ať zavede slevu pro zboží dražší než 50, nebo ať najde nejlevnější zboží v ceníku.
Otázka na závěr: „Co by bylo potřeba změnit, kdybychom chtěli přidat páté zboží?" Jediný řádek v ceníku — zbytek programu funguje dál. To je celá myšlenka oddělení dat od kódu.
Tvoje zadání:
Bestiář je kniha, ve které má každá příšera řádek. Ty ji teď naprogramuješ a spočítáš z ní statistiky.
- Vyrob slovník
bestiars pěti příšerami a jejich životy.💡 Poradit
Klíč je jméno příšery, hodnota jsou životy.
Např.["Skřet"] = 30,.- Vypiš celý bestiář cyklem
foreachse zarovnanými sloupci.💡 Poradit
polozka.Key.PadRight(12)apolozka.Value.ToString().PadLeft(4).- Spočítej součet všech životů a průměr na jednu příšeru.
💡 Poradit
Před cyklemint celkem = 0;, uvnitř přičítej.
Průměr jecelkem / bestiar.Count.- Najdi nejsilnější příšeru — tu s nejvíc životy.
💡 Poradit
Pamatuj sinejvicanejsilnejsi.
Kdyžpolozka.Value > nejvic, přepiš obojí.- Přidej druhý slovník
odmeny(jméno → zlato) a vypiš spojený přehled.💡 Poradit
Oba slovníky mají stejné klíče.
V cyklu pak čtiodmeny[polozka.Key].
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | bestiář a jeho výpis cyklem (kroky 1–2) |
| Rozšíření | součet, průměr a hledání maxima (kroky 3–4) |
| Výzva | dva slovníky se společnými klíči (krok 5) |
Očekávaný výsledek: pět řádků bestiáře, celkem 297 HP, průměr 59, nejsilnější Drak se 120 HP, a nakonec tabulka s odměnami.
Kde se zaseknou:
- int nejvic = 0; funguje jen proto, že životy jsou kladné. Zeptejte se rychlíků,
co by se stalo, kdyby příšery mohly mít záporné životy. Správná odpověď:
začít první položkou, ne nulou.
- Průměr vyjde jako celé číslo (59, ne 59,4). To je v pořádku — dělení dvou int
v C# zahazuje zbytek. Kdo chce přesně, přepíše na (double)celkem / bestiar.Count.
- Ve výpisu s PadLeft zapomenou .ToString(). int sám PadLeft neumí.
- V kroku 5 čtou odmeny[polozka.Key] bez pojistky. Funguje to, dokud mají
oba slovníky stejné klíče — ať jednu odměnu smažou a uvidí KeyNotFoundException.
Kdo je hotový dřív: ať najde i nejslabší příšeru, ať spočítá poměr „zlato na jeden život", nebo ať vypíše jen příšery nad 40 HP.
Otázka na závěr: „Proč jsou v obou slovnících stejné klíče?"
Protože klíč je spojka mezi tabulkami. Kdyby se v jedné psalo "Drak"
a v druhé "drak", nenajde se nic.
Tvoje zadání:
Po výpravě vysypeš batoh na stůl. Program z hromady věcí udělá přehledný seznam: co a kolikrát.
- Založ prázdný slovník
batohtypuDictionary<string, int>.💡 Poradit
Prázdný slovník jenew Dictionary<string, int>();— kulaté závorky, žádné složené.- Projdi pole
nalezya spočítej, kolikrát se která věc objevila.💡 Poradit
Kdyžbatoh.ContainsKey(vec), přičti jedničku, jinak nastav na 1.- Vypiš batoh — u každé věci počet a pruh ze znaků
▪.💡 Poradit
Pruh vyrobíš přesnew string('▪', polozka.Value).- Pomocí
TryGetValuezjisti, kolik má hrdina lektvarů.💡 Poradit
if (batoh.TryGetValue("lektvar", out int pocet))a velsenapiš, že žádný nemá.- Vyhoď z batohu všechno, čeho je jen jeden kus, a vypiš, co zbylo.
💡 Poradit
Projdibatoh.Keys.ToList()a kdyžbatoh[klic] == 1, zavolejbatoh.Remove(klic).
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | prázdný slovník a počítání výskytů (kroky 1–2) |
| Rozšíření | výpis s pruhy a TryGetValue (kroky 3–4) |
| Výzva | bezpečné mazání během procházení (krok 5) |
Očekávaný výsledek: mince 4×, lektvar 3×, pírko 1×, kámen 1×. Po vyhození zbydou dva druhy věcí.
Kde se zaseknou:
- Napíšou new Dictionary<string, int> {} se složenými závorkami. Funguje to taky,
ale ať si zvyknou na () — u prázdného slovníku je to čitelnější.
- U kroku 5 zapomenou ToList() → InvalidOperationException.
Je to stejná chyba jako ve cvičení 2, tentokrát u mazání. Zopakujte přirovnání
s regálem.
- TryGetValue je pro ně nové. Zdůrazněte, že out int pocetLektvaru
proměnnou vyrábí, nemusí být deklarovaná dopředu.
- Někdo zkusí batoh.Remove(polozka.Key) přímo uvnitř foreach (var polozka in batoh).
Spadne to okamžitě — dobrá příležitost ukázat, že chybová hláška říká
pravdu velmi přesně.
Kdo je hotový dřív: ať spočítá celkový počet kusů (ne druhů),
ať najde nejčastější věc, nebo ať batoh vypíše seřazený podle počtu
(batoh.OrderByDescending(p => p.Value)).
Otázka na závěr: „Kolik řádků by program měl, kdybychom mince počítali bez slovníku, každou zvlášť?" Slovník tuhle práci schová do tří řádků a funguje i na věci, o kterých jsme dopředu nevěděli.
Tvoje zadání:
Velké finále hodiny. Postavíš datovou vrstvu CsQuestu: mapu míst, jejich popisy, nebezpečí a počítadlo návštěv. Tohle je kus programu, se kterým budeš pracovat i příští hodiny.
- Vyrob slovník
popisytypuDictionary<string, string>se třemi místy.💡 Poradit
Tentokrát je hodnota text:Dictionary<string, string>.- Přidej slovník
nebezpeci(stejné klíče, hodnota 1–10) a vypiš mapu s hvězdičkami.💡 Poradit
Hvězdičky:new string('★', polozka.Value).
Klíče musí být přesně stejné jako vpopisy.- Pro místo v proměnné
kdevypiš popis a nebezpečí — s pojistkouContainsKey.💡 Poradit
if (popisy.ContainsKey(kde))… jinak napiš, že místo na mapě není.- Založ slovník
navstivenoa zaznamenej do něj cestu z poletrasa.💡 Poradit
Stejný vzor jako u batohu: je tam? přičti. Není? nastav na 1.- Vypiš deník výpravy a najdi místo, kde byl hrdina nejčastěji.
💡 Poradit
Projdinavstivenoa pamatuj si maximum — stejně jako u nejsilnější příšery.
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | slovník popisů a výpis mapy (kroky 1–2) |
| Rozšíření | bezpečné čtení aktuálního místa (krok 3) |
| Výzva | počítadlo návštěv a hledání maxima (kroky 4–5) |
Očekávaný výsledek: mapa se třemi řádky hvězdiček, popis dolu,
deník les 3×, dul 2×, vez 1× a hláška, že nejraději chodí do lesa.
Kde se zaseknou:
- Míchají diakritiku: v popisy mají klíč "důl", v nebezpeci "dul".
Pak nebezpeci[kde] spadne. Proto v zadání záměrně používáme klíče
bez diakritiky — je to praktické pravidlo, ne náhoda.
- Zapomenou, že popisy je Dictionary<string, string>, a zkusí do něj
dát číslo → CS0029.
- U hledání maxima dají výpis a porovnání do dvou samostatných cyklů.
Funguje to; ukažte, že jeden cyklus zvládne obojí.
- trasa.Length versus popisy.Count — pole má Length, slovník Count.
Dobré místo si to připomenout.
Kdo je hotový dřív:
- přidat čtvrté místo (musí dopsat do obou slovníků),
- spočítat celkové „nastřádané nebezpečí" trasy
(za každý krok přičti nebezpeci[misto]),
- vypsat místa, kde hrdina ještě nebyl
(projít popisy.Keys a testovat navstiveno.ContainsKey).
Otázka na závěr: „Kolik slovníků by hra potřebovala, kdyby mělo každé místo i odměnu, obrázek a seznam příšer?" Odpověď: čtyři, pět, šest… a právě proto se v 16. hodině naučíme třídy, kde bude jedno místo jedním objektem.
Rozšiř svůj
Program.cso datovou vrstvu CsQuestu:
- slovník
ceniks alespoň pěti druhy zboží a cenami,- slovník
bestiars alespoň čtyřmi příšerami a jejich životy,- druhý slovník
odmenyse stejnými klíči jako bestiář,- výpis obou tabulek cyklem
foreachse zarovnanými sloupci,- a nákup, který se zeptá uživatele na zboží, ověří ho přes
ContainsKeya odečte zlato.Ulož snímek obrazovky (nebo soubor
Program.cs) a přines na příští hodinu.
Úkol je schválně otevřený. Cílem je, aby si dítě doma znovu otevřelo editor a samo si vymyslelo obsah tabulek — ceník i bestiář jsou vděčné téma, protože si do nich každý dá to svoje.
Na začátku příští hodiny promítněte dva tři odevzdané bestiáře.
Ptejte se na obsah, ne na syntaxi. Kdo úkol nemá, nic se neděje —
9. hodina o cyklech navazuje na foreach, který se dnes dělal na hodině.
Nejčastější problém v odevzdaných úkolech bude čtení neexistujícího klíče.
Mějte hlášku KeyNotFoundException připravenou na plátně, ať ji poznají.
Kdo nemá doma .NET, udělá úkol přímo tady v prohlížeči a pošle zkopírovaný text.
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.
Console.ReadLine() — jeden řádek na jedno čtení.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š |
|---|---|---|
Dictionary<TKey,TValue> |
Dictionary |
celý slovník se všemi metodami |
slovnik[klíč] |
Indexer Item[] |
čtení a zápis hranatými závorkami |
ContainsKey |
ContainsKey |
ověření, jestli klíč existuje |
TryGetValue |
TryGetValue |
bezpečné čtení jedním krokem |
Remove |
Remove |
smazání klíče i s hodnotou |
Count |
Count |
počet dvojic ve slovníku |
Keys / Values |
Keys |
procházení jen klíčů nebo jen hodnot |
KeyValuePair |
KeyValuePair |
dvojice, kterou dává foreach |
foreach |
Příkaz foreach |
procházení kolekcí |
out |
Modifikátor out |
jak funguje out int cena |
KeyNotFoundException |
KeyNotFoundException |
výjimka při čtení neexistujícího klíče |
| Inicializátory kolekcí | Object and Collection Initializers | zápis { ["a"] = 1 } |
Stránka Dictionary<TKey,TValue> je na první pohled děsivá — je v ní přes
třicet metod. Ukažte dětem, že se dá prohledat prohlížečem (Ctrl+F)
a že v praxi potřebují čtyři: indexer, ContainsKey, Count a Remove.
Ve VS Code funguje i doplňování: napsat cenik. a podívat se, co nabídne,
je rychlejší než hledat v dokumentaci. Naučte je to.
Pro rychlejší studenty, kteří dokončí cvičení dřív, nebo na posledních 10–15 minut.
| Cvičení | Odkaz | Proč se hodí |
|---|---|---|
| Programování — seznamy a data | umimeinformatiku.cz | Práce s kolekcemi a čtení kódu, který data prochází |
| Proměnné a výrazy | umimeinformatiku.cz | Co je v krabici po několika přiřazeních — u slovníku totéž, jen s klíčem |
| Šifry a kódování | umimeinformatiku.cz | Substituční šifra je doslova slovník: znak → znak |
Šifry jsou tu obzvlášť vhodné, protože substituční šifra je přesně to, co jsme dnes dělali — tabulka, kde se z jednoho klíče čte jedna hodnota. Dětem to většinou docvakne až tady.
Nedávejte to celé třídě naráz. Použijte to jako záložní aktivitu pro tři až pět nejrychlejších dětí, aby nerušily ostatní. Mějte odkaz připravený v záložkách prohlížeče.
Dobrá alternativa pro rychlíky přímo v kódu: ať si udělají slovník
Dictionary<char, char> jako jednoduchou šifru a zkusí zašifrovat své jméno.
Zabaví je to na deset minut a spojí to dnešní hodinu s minulou o řetězcích.