Anglická verze
logolink

< Zpět na seznam lekcí

Hra pexeso V

AlgortimyObsah lekce:

  • Porovnání kartiček
  • Průběh hry

Porovnání kartiček

Před vytvoření popisu algoritmu pro průběh hry je třeba vytvořit ještě jednu proceduru a touto procedurou bude porovnání kartiček. Po otočení dvojice kartiček je třeba zjistit, zda jsou kartičky shodné a v případě, že shodné jsou, tyto kartičky odebrat a upravit skóre daného hráče.

Potřebnou proceduru pojmenujeme porovnejkarticky a na vstupu bude celkem 5 vstupních hodnot:

  • Souřadnice dvou kartiček k porovnání (celočíselné proměnné typu byte, označíme je x1, y1, x2 a y2).
  • Proměnná pro uložení informace, zda jsou kartičky shodné (logická hodnota typu boolean, označíme ji shodne).
Základ procedury pro porovnání kartiček
procedure porovnejkarticky(var x1,y1,x2,y2:byte; var shodne:boolean);
begin
  if p[x1,y1].obrazek=p[x2,y2].obrazek then
    shodne:=true
  else
    shodne:=false;
end;

Do této procedury zatím pouze doplníme podmínku, která porovná dvě kartičky pexesa a pokud je hodnota obrazek shodná, procedura uloží do proměnné shodne hodnotu true (pravda), v opačném případě doplní do této proměnné hodnotu false (nepravda).

Následně proceduru ještě rozšíříme. V případě, že jsou kartičky shodné, tak se provedou dvě úpravy hodnot u těchto kartiček:

  • Hodnota viditelna se nastaví zpět na false.
  • Hodnota odebrana se změní na true.
Procedura pro porovnání kartiček
procedure porovnejkarticky(var x1,y1,x2,y2:byte; var shodne:boolean);
begin

  p[x1,y1].viditelna:=false;
  p[x2,y2].viditelna:=false;

  if p[x1,y1].obrazek=p[x2,y2].obrazek then
    begin
      p[x1,y1].odebrana:=true;
      p[x2,y2].odebrana:=true;
      shodne:=true;
    end
  else
    shodne:=false;
end;

Kromě přidání několika piřazení hodnot bylo nutné příkazy v bloku IF umístit do bloku BEGIN ... END. Důvodem je použití více příkazů u větve IF. V případě jednoho příkazu je možné používat bez BEGIN ... END tak, jako v předchozím příkladu.

Průběh hry

Pro správnou funkci programu Pexeso chybí již jen jedna procedura. Touto procedurou je část programu, která bude řídit průběh hry. Proceduru si pojmenujeme hra.

Procedura hra nebude mít žádné vstupní parametry, ale bude nutné si definovat několik lokálních proměnných:

  • hrac - určuje číslo hráče, který je na řadě
  • radek1, sloupec1 - souřadnice 1. otočené kartičky
  • radek2, sloupec2 - souřadnice 2. otočené kartičky
  • shodnekarticky - uložení informace, zda jsou otočené kartičky shodné
  • konechry - pomocná proměnná, která bude řídit cyklus průběhu hry

Uveďme si tedy nejprve základní kostru procedury hra doplněnou o tyto lokální proměnné. Následně si doplníme i další příkazy a funkce této procedury.

Procedura pro řízení běhu hry
procedure hra;
var konechry,shodnekarticky:boolean;
    hrac,radek1,radek2,sloupec1,sloupec2:byte;
begin

end; 

Následně již můžeme definovat průběh hry. Základem bude cyklus while, který bude prováděn, pokud proměnná konechry bude mít hudnotu false. Jakmile se změní na true, hra bude ukončena.

Před spuštěním tohoto cyklu je třeba nastavit proměnnou konechry na hodnotu false a také je tžeba nastavit výchozí hodnotu pro proměnnou hrac. Tato proměnná bude určovat, který hráč je na řadě a na počátku bude mít hodnotu 1.

Procedura pro řízení běhu hry
procedure hra;
var konechry,shodnekarticky:boolean;
    hrac,radek1,radek2,sloupec1,sloupec2:byte;
begin
    hrac:=1;
    konechry := false;
    
    while konechry = false do
    begin
        zobrazenipexesa;
        otockarticku(radek1,sloupec1);
        zobrazenipexesa;
        otockarticku(radek2,sloupec2);
        zobrazenipexesa;
        porovnejkarticky(radek1,sloupec1,radek2,sloupec2,shodnekarticky);
        if shodnekarticky then
        begin
            ph[hrac].skore := ph[hrac].skore+1;
        end
        else
        begin
            if hrac<>pocethracu then
                hrac := hrac + 1
            else
                hrac := 1;
        end;
        readln;
    end;
end; 

Uvnitř cyklu, který bude řídit průběh hry dojde postupně k otočení dvou kartiček (dvě volání procedury otockarticku). Tato procedura zajistí otočení kartičky a uložení jejich souřadnic do proměnných radek1, sloupec1 (případně radek2, sloupec2). Následně jsou kartičky porovnány prostřednictvím procedury porovnejkarticku (do ní vstupují dvě dvojice souřadnic kartičky a proměnná shodnekarticky, do které bude uložena informace, zda jsou kartičky shodné, či nikoliv).

Následně je spuštěna podmínka, která ověří, zda jsou kartičky shodné. Pokud jsou shodné, zvýší skóre aktuálního hráče o 1 (ph[hrac].skore := ph[hrac].skore+1;), v opačném případě se zvýší číslo hráče o 1 (nebo se změní na 1, pokud byl na řadě poslední hráč v pořadí).

Důležité je ještě volání procedury zobrazenipexesa po každé změně (otočení kartičky, vyhodnocení stejných kartiček, ...).

Tento cyklus se opakuje, pokud ve hře zůstávají nějaké kartičky.

Pro správnou funkci programu doplníme ještě ošetření konce hry (změna proměnné konechry na hodnotu true).

Procedura pro řízení běhu hry s ošetřením konce hry
procedure hra;
var konechry,shodnekarticky:boolean;
    hrac,radek1,radek2,sloupec1,sloupec2:byte;
    pocet, i : byte;
begin
    hrac:=1;
    konechry := false;
    
    while konechry = false do
    begin
        zobrazenipexesa;
        otockarticku(radek1,sloupec1);
        zobrazenipexesa;
        otockarticku(radek2,sloupec2);
        zobrazenipexesa;
        porovnejkarticky(radek1,sloupec1,radek2,sloupec2,shodnekarticky);
        if shodnekarticky then
        begin
            ph[hrac].skore := ph[hrac].skore+1;
            pocet := 0
            for i := 1 to pocethracu do
            begin
                pocet := pocet + ph[i].skore;
            end;
            if pocet = (n*n div 2) then
                konechry = true;
        end
        else
        begin
        if hrac<>pocethracu then
                hrac := hrac + 1
            else
                hrac := 1;
        end;
        
        
        readln;
    end;
end; 

Následně v hlavní části programu odstraníme všechny pokusné výpisy a nahradíme je voláním procedury hra. Po této úpravě bude tato část kódu vypadat následovně:

Volání procedury hra v hlavní části programu
 ..
 
begin
    { TODO -oUser -cConsole Main : Insert code here }

    inicializacepexesa;
    zamichanipexesa;
    inicializacehracu;
    zadejpocethracu;
    zadejjmenahracu;

    hra;

    readln;
end.

Kompletní kód programu

Aktuálně je již program plně funkční. Pro kompletaci programu chybí již jen výstup do prohlížeče, aby bylo pexeso lépe vzualizováno. Tomuto úkolu bude věnována příští lekce.

Pro úplnost je opět vhodné uvěst kompletní kód našeho programu.

Program po doplnění úprav
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;
pocethracu : 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
    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;

procedure porovnejkarticky(var x1,y1,x2,y2:byte; var shodne:boolean);
begin

  p[x1,y1].viditelna:=false;
  p[x2,y2].viditelna:=false;

  if p[x1,y1].obrazek=p[x2,y2].obrazek then
    begin
      p[x1,y1].odebrana:=true;
      p[x2,y2].odebrana:=true;
      shodne:=true;
    end
  else
    shodne:=false;
end;

procedure hra;
var konechry,shodnekarticky:boolean;
    hrac,radek1,radek2,sloupec1,sloupec2:byte;
    pocet, i : byte;
begin
    hrac:=1;
    konechry := false;
    
    while konechry = false do
    begin
        zobrazenipexesa;
        otockarticku(radek1,sloupec1);
        zobrazenipexesa;
        otockarticku(radek2,sloupec2);
        zobrazenipexesa;
        porovnejkarticky(radek1,sloupec1,radek2,sloupec2,shodnekarticky);
        if shodnekarticky then
        begin
            ph[hrac].skore := ph[hrac].skore+1;
            pocet := 0
            for i := 1 to pocethracu do
            begin
                pocet := pocet + ph[i].skore;
            end;
            if pocet = (n*n div 2) then
                konechry = true;
        end
        else
        begin
        if hrac<>pocethracu then
                hrac := hrac + 1
            else
                hrac := 1;
        end;
        
        
        readln;
    end;
end; 

begin
{ TODO -oUser -cConsole Main : Insert code here }

inicializacepexesa;
zamichanipexesa;
inicializacehracu;
zadejpocethracu;
zadejjmenahracu;

hra;

readln;
end.

Úkol

Upravte proceduru zobrazpexeso tak, aby zobrazovala i jména hráčů a počty jejich bodů. Do procedury hra přidejte informaci, který hráč je na řadě.

webdesign, xhtml, css, php - Mgr. Michal Mikláš