Obsah lekce:
V předchozí části jsme se dostali do fáze, kdy máme nadefinovány všechny potřebné proměnné pro naše pexeso. Před tím, než si tyto proměnné naplníme hodnotami, se kterými budeme dále pracovat, si zkusíme naše pole s pexesem vypsat.
Pexeso máme uložené jako dvourozměrné pole struktur (ze kterých budeme vypisovat hodnotu obrazek). Struktura je datový typ record, který může obsahovat v jedné proměnné několik dalších proměnných (v našem případě obrazek, viditelna a odebrana).
Pro vypsání našeho pole budeme potřebovat 2 vnořené cykly for, které nám budou procházet řádky a sloupce. Před vytvořením těchto cyklů si vytvoříme pomocné proměnné radek a sloupec, do kterých nám budou cykly for ukládat aktuální pozici v poli. Tyto dvě proměnné umístíme do části, kde jsme již definovali předchozí proměnné (za příkaz var), a to následovně.
Když máme vytvořené proměnné, můžeme si vypsat, co naše pexeso aktuálně obsahuje. Pro vypsání obsahu dvourozměrného pole využijeme dva vnořené cykly for. První bude procházet jednotlivé řádky a druhý bude procházet hodnoty v každém řádku (tj. sloupce). Pro každou dvojici [radek, sloupec] je vypsána hodnota obrazek struktury p (doplněná o mezeru, aby byl výpis přehlednější).
Po opuštění vnitřního cyklu je ještě nutné zalomit řádek (příkaz writeln;). Výpis umístíme do bloku begin - end za definicí proměnných.
U funkce write, která nám hodnotu vypíše, přidáme ještě výpis mezery, abychom rozeznali jednotlivé vypsané hodnoty. Mezeru doplníme tak, že do funkce write doplnime za výpis obrázku čárku a mezeru, kterou ohraničíme znaky ' '.
for radek := 1 to n do begin for sloupec := 1 to n do begin write(p[radek, sloupec].obrazek,' '); end; writeln; end;
Po spuštění programu v této podobě pravděpodobně zjistíme, že hodnota obrazek je u našeho pexesa nastavena na 0 u všech kartiček. To je způsobeno tím, že jsme zatím žádnou hodnotu nenastavili (pole je inicializováno na hodnotu 0).
V předchozím kroku jsme si ověřili, že všechny hodnoty obrázku v pexesu máme nastaveny na hodnotu 0. My ale potřebujeme, aby zde byly dvakrát hodnoty 1-18. Máme totiž pole 6x6 kartiček pexesa, což je celkem 36 kartiček a každá kartička se má vyskytovat dvakrát.
Naším úkolem nyní bude nalezení způsobu, jak do pole našeho pexesa naskládat hodnoty 1-18 tak, aby se vyskytovala každá dvakrát.
Naskládání hodnot do pole pexesa můžeme provést několika způsoby (zatím nebudeme řešit zamíchání pexesa). Například můžeme naplnit pexeso hodnotami 1, 1, 2, 2, 3, 3, ... nebo postupně hodnotami 1 - 18 a 1 - 18.
První varianta nám naplní pole posloupností 1-18, za kterou bude následovat další posloupnost 1-18. Toto řešení bude vypadat následovně:
pocet := 0; for radek := 1 to n do begin for sloupec := 1 to n do begin p[radek, sloupec].obrazek := 1 + pocet mod 18; pocet := pocet + 1; end; end;
V této variantě použijeme pomocnou proměnnou pocet, kterou budeme zvyšovat při každém průchodu cyklu. Tuto proměnnou si vytvoříme stejným způsobem, jako předchozí celočíselné proměnné radek a sloupec. Na počátku ji nastavíme na hodnotu 0 a v každém průchodu vnitřního cyklu ji zvýšíme o 1. Pro získání požadovaných hodnot použijeme operátor celočíselného dělení (div) a výsledek zvýšíme o 1. Když bychom použili pouze celočíselné dělení, vracela by nám naše operace výsledek od 0 do 17 (např. 0 mod 18 = 0, 5 mod 18 = 5, 17 mod 18 = 17 a 18 mod 18 = 0), proto k výsledku přičteme hodnotu 1 a získáme posloupnost čísel od 1 do 18, po kterých bude znovu následovat 1-18 (protože pocet bude růst až do hodnoty 35).
I pro druhou variantu naplnění pole budeme potřebovat celočíselnou proměnnou pocet, která nám bude sloužit pro počítání počtu průchodů vnitřního cyklu. Naplnění hodnot pole v tomto případě může vypadat následovně:
pocet := 1; for radek := 1 to n do begin for sloupec := 1 to n do begin pocet := pocet + 1; p[radek, sloupec].obrazek := pocet div 2; end; writeln; end;
U tohoto způsobu naplnění pole (který je uveden výše) nejprve nastavíme proměnnou pocet na hodnotu 1 a následně ji zvýšíme při každém průchodu cyklu. Po zvýšení hodnoty této proměnné uložíme do p[radek, sloupec].obrazek výsledek celočíselného dělení proměnné pocet a hodnoty 2 (použití operátoru div). Tato operace nám bude postupně vracet hodnoty 1, 1, 2, 2, 3, 3, ..., 18, 18.
U třetí varianty řešení opět budeme potřebovat proměnnou pocet, ale budeme ji zvyšovat pouze v každém druhém průchodu cyklu. Pro tuto variantu využijeme proměnnou sloupec a vytvoříme podmínku, kdy pokud zbytek po celočíselném dělení proměnné sloupec číslem 2 bude 1, zvýšíme proměnnou sloupec o 1. Kód programu v tomto případě bue vypadat následovně:
pocet := 0; for radek := 1 to n do begin for sloupec := 1 to n do begin if (sloupec mod 2) = 1 then pocet := pocet + 1; p[radek, sloupec].obrazek := pocet; end; writeln; end;
Pro zajímavost si můžeme uvěst i variantu, kde se obejdeme bez pomocné proměnné pocet. V této variantě místo proměnné počet vypočítáme aktuální průchod cyklu z čísla aktuálního řádku a sloupce. Proměnná n nám udává počet sloupců.
for radek := 1 to n do begin for sloupec := 1 to n do begin p[radek, sloupec].obrazek := (((radek-1)*n + (sloupec-1)) mod 18) + 1; end; writeln; end;
Na výše uvedených variantách jsme si ukázali, že většina úkolů v oblasti algoritmizace a programování nemá pouze jedno řešení, ale často existuje více cest, jak dojít k požadovanému cíli.
Vybranou variantu můžete doplnit před část programu pro zobrazení hodnot a program vyzkoušet v této úpravě.
V dalším kroku inicializace pexesa je třeba nastavit hodnoty i u proměnných viditelna a odebrana, které jsou součástí naší struktury. Ve výchozím stavu by neměla být viditelná žádná kartička, proto u proměnné viditelna nastavíme hodnotu false. Stejnou hodnotu (false) nastavíme i u proměnné odebrana, protože na začátku hry jsou ve hře všechny kartičky.
Tyto dvě operace přidáme do cyklu, ve kterém jsme si nastavili výchozí hodnotu u proměnné obrazek (u varianty, kterou jsme si vybrali).
pocet := 1; for radek := 1 to n do begin for sloupec := 1 to n do begin pocet := pocet + 1; p[radek, sloupec].obrazek := pocet div 2; p[radek, sloupec].viditelna := false; p[radek, sloupec].odebrana := false; end; writeln; end;
Aby náš program byl přehlednější, přesuneme si naši inicializaci do samostatné procedury. Nejprve si připomeňme, jak proceduru zapsat.
procedure název (parametry procedury); //parametry jsou volitelné var proměnné //volitelná deklarace proměnných pro proceduru begin programový kód procedury end;
Do samostatné procedury inicializacepexesa přesuneme cyklus pro inicializaci pexesa a definici proměnných radek, sloupec a pocet. Takto umístěné proměnné označujeme termínem lokální proměnné. Tyto proměnné tedy budou viditelné pouze uvnitř naší procedury. Naopak proměnné, které jsme umístili na začátek našeho programu, jsou globální. Jsou tedy viditelné ve všech procedurách, které jsou obsaženy v našem programu.
Tato procedura nebude mít žádní vstupní parametry.
procedure inicializacepexesa; var radek, sloupec : byte; pocet : byte; begin pocet := 1; for radek := 1 to n do begin for sloupec := 1 to n do begin pocet := pocet + 1; p[radek, sloupec].obrazek := pocet div 2; p[radek, sloupec].viditelna := false; p[radek, sloupec].odebrana := false; end; writeln; end; end;
Kompletní program tedy bude vypadat následovně:
program pexeso3po; {$APPTYPE CONSOLE} uses SysUtils; const n=6; maxhracu=4; type karticka = record obrazek:byte; viditelna:boolean; odebrana:boolean; end; hrac = record jmeno:string; skore:byte; end; hraci=array[1..maxhracu]of hrac; pexeso=array[1..n,1..n]of karticka; var p:pexeso; ph:hraci; radek, sloupec : byte; procedure inicializacepexesa; var radek, sloupec : byte; pocet : byte; begin pocet := 1; for radek := 1 to n do begin for sloupec := 1 to n do begin pocet := pocet + 1; p[radek, sloupec].obrazek := pocet div 2; p[radek, sloupec].viditelna := false; p[radek, sloupec].odebrana := false; end; writeln; end; end; begin { TODO -oUser -cConsole Main : Insert code here } inicializacepexesa; for radek := 1 to n do begin for sloupec := 1 to n do begin write(p[radek, sloupec].obrazek,' '); end; writeln; end; readln; end.
Po úspěšné inicializaci pole pexesa bude pexeso obsahovat hodnoty dle následujícího obrázku.
Pro zobrazení pexesa bude vhodnější zobrazení obrázků, než výpis čísel, který aktuálně máme. Proto v další části vytvoříme proceduru pro výpis do prohlížeče. Procedura nám vytvoří soubor ve formátu HTML, který bude zobrazovat jednotlivé kartičky pexesa, jména hráčů a počty bodů.
Pro kartičky pexesa použijeme obrázky ve formátu JPG o velikosti 100x100px. Tyto obrázky budou pojmenované 1.jpg až 18.jpg. Navíc bude potřeba jeden obrázek pro rubovou stranu kartiček. Tento obrázek bude mít stejné rozměry a bude pojmenován 0.jpg.
Abychom v příští části mohli pokračovat s tvorbou výstupu do prohlížeče, budeme potřebovat obrázky. Připravte proto 18 různých obrázků ve formátu JPG s rozměry 100x100 px. Tyto obrázky pojmenujte 1.jpg až 18.jpg. Dále si připravte obrázek pro rub kartiček pexesa se stejnými rozměry. Tento soubor pojmenujte 0.jpg.
Navrhněte algoritmus pro zamíchání kartiček pexesa a zkuste jej realizovat jako proceduru v Pascalu.