Obsah lekce:
Zatím máme dokončenu jednodušší verzi procedury pro otočení kartičky. Neošetřujeme však možné chyby, jako například pokus o znovu otočení stejné kartičky nebo zadání souřadnic mimo rozsah pole našeho pexesa. Proceduru otockarticku máme zatím v následující podobě:
procedure otockarticku(var radek,sloupec:byte); begin p[radek, sloupec].viditelna := true; end;
V této proceduře je dále nutné ošetřit některé chyby, ke kterým mohlo dojít. Jedná se zejména o následující:
Tyto tři problematické jevy ušetříme pomocí cyklu, který nám zopakuje zadání hodnot, pokud dojde k nějaké chybě.
Pro tento účel si vytvoříme pomocnou proměnnou kartickaok, která bude uchovávat informaci, zda má být cyklus spuštěn ještě jednou.
Po spuštění procedury se do této proměnné uloží hodnota false, aby byl cyklus spuštěn alespoň jednou. Uvnitř tohoto cyklu následně bude uživatel vyzván k zadání hodnoty řádku a sloupce. Po zadání řádku a sloupce se ověří, zda kartička již nebyla otočena nebo odebrána. Pokud je tato podmínka splněna, uloží se do proměnné kartickaok hodnota true a cyklus je ukončen. Touto úpravou ošetříme dva body ze tří, které jsme stanovili v předchozím textu (konkrétně "Otočení odebrané kartičky" a "Pokus o otočení kartičky mimo rozsah pole pexesa").
procedure otockarticku(var radek,sloupec:byte); var kartickaok : boolean; begin kartickaok := false; while kartickaok = false do begin writeln('Zadejte souradnice karticky (radek): '); readln(radek); writeln('Zadejte souradnice karticky (sloupec): '); readln(sloupec); if (p[radek,sloupec].odebrana = false) and (p[radek,sloupec].viditelna = false) then begin kartickaok :=true; p[radek,sloupec].viditelna:=true; end; end; end;
Následně je nutné ještě ošetřit situaci, kdy uživatel zadá adresu kartičky mimo rozsah pole pexesa. Do našeho cyklu přidáme na místo po zadání hodnot řádku a sloupce postupně dva cykly: jeden, který zopakuje zadání čísla řádku v případě, že číslo řádku bude mimo povolený rozsah od 1 do n, a druhý, který zopakuje zadání čísla sloupce v případě, že číslo sloupce bude mimo povolený rozsah od 1 do n.
Po této úpravě bude kód procedury pro otočení kartičky vypadat následovně:
procedure otockarticku(var radek,sloupec:byte); var kartickaok : boolean; begin kartickaok := false; while kartickaok = false do begin writeln('Zadejte souradnice karticky (radek): '); readln(radek); while (radek < 1) or (radek > n) do begin writeln('Zadejte znovu souradnice karticky (radek): '); readln(radek); end; writeln('Zadejte souradnice karticky (sloupec): '); readln(sloupec); while (sloupec < 1) or (sloupec > n) do begin writeln('Zadejte znovu souradnice karticky (sloupec): '); readln(sloupec); end; if (p[radek,sloupec].odebrana = false) and (p[radek,sloupec].viditelna = false) then begin kartickaok :=true; p[radek,sloupec].viditelna:=true; end; end; end;
Pro potřeby testování programu nyní ještě upravíme hlavní část programu, odkud voláme proceduru pro otočení kartičky pexesa. Nyní již totiž nebudeme načítat souřadnice kartičky v hlavní části programu, ale až v proceduře pro otočení kartičky.
Z hlavní části programu odstraníme následující řádky:
writeln('Zadejte souradnice 1. karticky (radek): '); readln(radek1); writeln('Zadejte souradnice 1. karticky (sloupec): '); readln(sloupec1); writeln('Zadejte souradnice 2. karticky (radek): '); readln(radek2); writeln('Zadejte souradnice 2. karticky (sloupec): '); readln(sloupec2);
A ponecháme pouze volání procedury otockarticku:
otockarticku(radek1,sloupec1); otockarticku(radek2,sloupec2);
V předchozích lekcích jsme zatím řešili pouze práci s kartičkami pexesa. Nyní se přesuneme k další části a tou jsou hráči. Nejprve je nutné pole hráčů inicializovat, tj. nastavit jeho výchozí hodnoty. Stejnou operaci jsme již dělali u kartiček pexesa, kde jsme je naplnili výchozími hodnotami obrázku a natavili vlastnosti stavu viditelnosti a odebrání kartičky.
Hráči jsou realizováni opět jako pole struktur, tj. pole datového typu rekord, které se skládá s následujících proměnných:
U hráčů budeme postupovat tak, že pro celé pole hráčů nastavíme pro jméno hráče prázdnou hodnotu a pro skóre hodnotu 0. To vše v celém rozsahu pole (ten je dán proměnnou maxhracu).
procedure inicializacehracu; var i:byte; begin for i:=1 to maxhracu do begin ph[i].jmeno:=''; ph[i].skore:=0; end; end;
Pomocí cyklu for postupně projdeme pole. Pro tento účel nám poslouží proměnná i, kterou postupně zvyšujeme od 1 do maxhracu a tím postupně procházíme pole ph (pole, ve kterém máme uložené hráče). U každého hráče takto nastavíme jméno na prázdný řetězec a skóre na 0.
Pro zadání počtu hráčů si nejprve vytvoříme globální proměnnou, do které následně uložíme počet hráčů. Proměnná můséí být globální, abychom k ní mohli přistupovat i z procedur, které budou řídit průběh hry.
Proměnnou pro počet hráčů pojmenujeme pocethracu. Bude se jednat o celočíselnou proměnnou typu byte.
Nyní již k samotní proceduře. Její základní verzi zobrazuje níže uvedený kód.
procedure zadejpocethracu; begin writeln('Zadejte pocet hracu>'); readln(pocethracu); end;
Výše uvedená procedura vypadá velmi jednoduše. Pouze se vypíše text s požadavkem a načte se hodnota od uživatele.
Tato jednoduchá varianta má však i jeden nedostatek - uživateli je dovoleno zadat libovolnou hodnotu (i když máme definovanou horní hranici počtu hráčů - v proměnné maxhracu). Tento nedostatek lze odstranit pomocí cyklu while. Postup bude následující:
procedure zadejpocethracu; begin writeln('Zadejte pocet hracu>'); readln(pocethracu); while ((pocethracu<2) or (pocethracu>maxhracu)) do begin writeln('Zdejte znovu>'); readln(pocethracu); end; end;
Další procedurou, která se týká hráčů je zadání jmen hráčů. Jedná se o proceduru s jednoduchým cyklem for, který postupně projde pole hráčů od 1 do pocethracu (hodnota, kterou jsme získali v proceduře zadejpocethracu) a u každého hráče uživatele vyzve pro zadání jména hráče.
procedure zadejjmenahracu; var i:byte; begin writeln('Zadejte jmena hracu>'); for i:=1 to pocethracu do begin readln(ph[i].jmeno); end; end;
Proceduru si můžeme ještě upravit, aby se u každého hráče zobrazila postupně informace "Zadejte jméno 1. hráče", "Zadejte jméno 2. hráče" apod.
procedure zadejjmenahracu; var i:byte; begin writeln('Zadejte jmena hracu:'); for i:=1 to pocethracu do begin writeln('Zadejte jmeno ', i, '. hrace>'); readln(ph[i].jmeno); end; end;
Abychom mohli testovat chod programu je samozřejmě nutné doplnit volání jednotlivých procedur, které jsme vytvořili, do hlavní části programu. Pro úplnost proto uveďme kompletní program po doplnění úprav z této lekce.
program pexeso1; {$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; radek1, sloupec1, radek2, sloupec2 : 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; end; end; procedure zamichanipexesa; var radek, sloupec : byte; r, s : byte; pom : byte; begin for radek := 1 to n do begin for sloupec := 1 to n do begin r := random(n) + 1; s := random(n) + 1; pom := p[radek, sloupec].obrazek; p[radek, sloupec].obrazek := p[r, s].obrazek; p[r, s].obrazek := pom; end; end; end; procedure zobrazenipexesa; var radek, sloupec : byte; begin for radek := 1 to n do begin for sloupec := 1 to n do begin IF p[radek, sloupec].odebrana THEN write('X ') ELSE IF p[radek, sloupec].viditelna THEN write(p[radek, sloupec].obrazek,' ') ELSE write('0 '); end; writeln; end; writeln; end; procedure otockarticku(var radek,sloupec:byte); var kartickaok : boolean; begin kartickaok := false; while kartickaok = false do begin writeln('Zadejte souradnice karticky (radek): '); readln(radek); while (radek < 1) or (radek > n) do begin writeln('Zadejte znovu souradnice karticky (radek): '); readln(radek); end; writeln('Zadejte souradnice karticky (sloupec): '); readln(sloupec); while (sloupec < 1) or (sloupec > n) do begin writeln('Zadejte znovu souradnice karticky (sloupec): '); readln(sloupec); end; if (p[radek,sloupec].odebrana = false) and (p[radek,sloupec].viditelna = false) then begin kartickaok :=true; p[radek,sloupec].viditelna:=true; end; end; end; procedure inicializacehracu; var i:byte; begin for i:=1 to maxhracu do begin ph[i].jmeno:=''; ph[i].skore:=0; end; end; procedure zadejpocethracu; begin writeln('Zadejte pocet hracu>'); readln(pocethracu); while ((pocethracu<2) or (pocethracu>maxhracu)) do begin writeln('Zdejte znovu>'); readln(pocethracu); end; end; procedure zadejjmenahracu; var i:byte; begin writeln('Zadejte jmena hracu:'); for i:=1 to pocethracu do begin writeln('Zadejte jmeno ', i, '. hrace>'); readln(ph[i].jmeno); end; end; begin { TODO -oUser -cConsole Main : Insert code here } inicializacepexesa; zamichanipexesa; inicializacehracu; zadejpocethracu; zadejjmenahracu; for radek := 1 to n do begin for sloupec := 1 to n do begin write(p[radek, sloupec].obrazek,' '); end; writeln; end; writeln; zobrazenipexesa; otockarticku(radek1,sloupec1); otockarticku(radek2,sloupec2); zobrazenipexesa; readln; end.