Czech version
logolink

< Back to the list of lessons

Memory Game V

AlgortimyContent of the lesson:

  • Comparison of Cards
  • Game Progress

Comparison of Cards

Before creating the algorithm for the game progress you have to create one more procedure to compare cards. After turning a couple of cards you have to find out whether they are identical or not. In case they are you have to remove these cards and increase the score of the active player.

Create a new procedure named porovnejkarticky which requires 5 input parameters:

  • Coordinates of two cards to be compared (variables of the byte data type, name them x1, y1, x2 and y2).
  • Variable to store the information whether these cards are identical (logical boolean value, name it shodne).
The core of the procedure for comparing cards
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;

We added only one condition which compares two cards and if the value of obrazek is the same the procedure saves true inside the variable shodne; otherwise it saves false inside the variable shodne.

You should extend the procedure. In case the cards are identical, two more steps have to be done with these cards:

  • The variable viditelna should be set back to false.
  • The variable odebrana should be set to true.
Procedure for comparing cards
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;

Besides adding a few assignments of values, it was necessary to close the commands inside the IF block to the block BEGIN ... END. The reason is that more commands were used inside the IF block. In case you used one command only, you would not have to use the block BEGIN ... END as in the previous sample.

Game Progress

For the proper functioning of the Memory Game we need to add one more procedure. This procedure is the part of program which will control the whole game progress. Create a new procedure and name it hra.

This procedure will not have any input parameters but it will be necessary to define several local variables:

  • hrac - number of the active player
  • radek1, sloupec1 - coordinates of the first turned card
  • radek2, sloupec2 - coordinates of the second turned card
  • shodnekarticky - information about the fact whether the turned cards are identical
  • konechry - an auxiliary variable which will control the game progress

Take a look at the core of the procedure hra supplemented by these local variables. We will add more commands to the procedure in the next part.

Procedure to control the game progress
procedure hra;
var konechry,shodnekarticky:boolean;
    hrac,radek1,radek2,sloupec1,sloupec2:byte;
begin

end; 

Then we can define the game progress. The base part is the while cycle which will be executed until the value of konechry is false. The game will be terminated as soon as it changes to true.

Before launching this cycle you have to set the variable konechry to false and also set default value for the variable hrac. This variable sets the active player and the default value is 1.

Procedure to control the game progress
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; 

The while cycle which controls the game progress will gradually turn both cards (it will call the procedure otockarticku twice). This procedure turnes both cards and saves their coordinates inside the variables radek1, sloupec1 (or radek2, sloupec2). Then both cards are compared using the procedure porovnejkarticku (this procedure requires 5 input parameters - both couples of coordinates and the variable shodnekarticky to store the information if the cards are identical or not).

Then you can see a condition to check if the cards are identical. In case they are, the score of the active player is increased by 1 (ph[hrac].skore := ph[hrac].skore+1;); otherwise the variable hrac is increased by one (or set to one in case that the last player was active) to switch the active player.

It is necessary to call the procedure zobrazenipexesa after all changes (turning cards, comparing cards, ...).

This cycle is repeated until any card remains in the game.

Finally, you should handle the end of the game (if the variable konechry is changed to true).

Procedure to control the game progress which handles the end of game
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; 

You should remove all attempts to write values to console and replace them with the procedure hra. This part of source code will look like the following one (after mentioned adjustments):

Calling the procedure hra from the main part
 ..
 
begin
    { TODO -oUser -cConsole Main : Insert code here }

    inicializacepexesa;
    zamichanipexesa;
    inicializacehracu;
    zadejpocethracu;
    zadejjmenahracu;

    hra;

    readln;
end.

The Entire Source Code

Our program is fully functional right now. We only have to improve the output to create a better visualization. We will try to output the Memory Game to browser in the next lesson.

For completeness you can see the entire source code below this text.

The entire source code after adjustments
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
    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;

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.

Individual Task

Adjust the procedure zobrazpexeso to be able to display names of players and their scores. Add an information about the active player inside the procedure hra.

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