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 4 input parameters:

  • Coordinates of two cards to be compared (variables of the byte data type, name them x1, y1, x2 and y2).

The returning value will be the variable to store the information whether these cards are identical.

The core of the procedure for comparing cards
int porovnejkarticky(int x1, int x2, int y1, int y2)
{
  if (p[x1][y1].obrazek==p[x2][y2].obrazek) return 1;
  else return 0;
}

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

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 0.
  • The variable odebrana should be set to 1.
Procedure for comparing cards
int porovnejkarticky(int x1, int x2, int y1, int y2)
{
  p[x1][y1].viditelna=0;
  p[x2][y2].viditelna=0;
  if (p[x1][y1].obrazek==p[x2][y2].obrazek) 
  {
       p[x1][y1].odebrana=1;
       p[x2][y2].odebrana=1;
       return 1;
  }
  else return 0;
}

Besides adding a few assignments of values, it was necessary to close the commands inside the IF block to the block { ... }. 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 { ... } 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
void hra()
{
     int konechry, shodnekarticky;
     int hrac, radek1, radek2, sloupec1, sloupec2;

}

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

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 0.

Procedure to control the game progress
void hra()
{
     int konechry, shodnekarticky;
     int hrac, radek1, radek2, sloupec1, sloupec2;
     
     hrac = 0;
     konechry = 0;
     
     while (konechry == 0)
     {
     		zobrazenipexesa();
            otockarticku();
            zobrazenipexesa();
            otockarticku();
            zobrazenipexesa();
            shodnekarticky = porovnejkarticky(radek1,sloupec1,radek2,sloupec2);
            if (shodnekarticky == 1)
            {
                 ph[hrac].skore = ph[hrac].skore + 1;
            }
            else
            {
               if (hrac != pocethracu-1)
               {
                   hrac = hrac + 1;
               }
               else
               {
                   hrac = 0;
               }
            }
            fflush(stdin);
            getchar();
     }
}

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 1).

Procedure to control the game progress which handles the end of game
void hra()
{
     int konechry, shodnekarticky;
     int hrac, radek1, radek2, sloupec1, sloupec2;
     int pocet;
     
     hrac = 0;
     konechry = 0;
     
     while (konechry == 0)
     {
     		zobrazenipexesa();
            otockarticku();
            radek1 = rx;
            sloupec1 = sx;
            zobrazenipexesa();
            otockarticku();
            radek2 = rx;
            sloupec2 = sx;
            zobrazenipexesa();
            shodnekarticky = porovnejkarticky(radek1,sloupec1,radek2,sloupec2);
            if (shodnekarticky == 1)
            {
                 ph[hrac].skore = ph[hrac].skore + 1;
                 pocet = 0;
                 for (int i = 0; i < pocethracu; i++)
                 {
                     pocet = pocet + ph[i].skore;
                 }
                 
                if (pocet == (n*n / 2))
                konechry = true;
            }
            else
            {
               if (hrac != pocethracu-1)
               {
                   hrac = hrac + 1;
               }
               else
               {
                   hrac = 0;
               }
            }
            fflush(stdin);
            getchar();
     }
}

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
 ..
 
 int _tmain(int argc, _TCHAR* argv[])
{

  int radek, sloupec, pocet;

  inicializacepexesa();
  zamichanipexesa();
  inicializacehracu();
  zadejpocethracu();
  zadejpocethracu();
  
  hra();
  
  fflush(stdin);
  getchar();
  
  ...
  

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
#include "stdafx.h"
#include <string.h>
#define n 6
#define maxhracu 4

typedef struct {
  int obrazek;
  int viditelna;
  int odebrana;
} karticka;              

typedef struct {
  char jmeno[255];
  int skore;
} hrac;

karticka p[n][n]; 
hrac ph[maxhracu];
int rx, sx;

void inicializacehracu()
{
    int i;
    for (i = 0; i < maxhracu; i++)
    {
        strcpy("",ph[i].jmeno);
        ph[i].skore=0;
    }
} 

void zadejpocethracu()
{
         printf("Zadejte pocet hracu: ");
         scanf("%d",&pocethracu);
         while ((pocethracu < 2) or (pocethracu > maxhracu))
         {
             printf("Zadejte znovu: ");
             scanf("%d",&pocethracu);         
         }
}
    
void zadejjmenahracu()
{
    int i;
    printf("Zadejte jmena hracu:\n");
    for (i = 0; i < pocethracu; i++)
    {
        printf("Zadejte jmeno %d. hrace: ", i+1);
        scanf("%s", &ph[i].jmeno);
    }
}

void inicializacepexesa()
{
	int radek, sloupec, pocet;
    pocet = 1;
        
    for (radek = 0; radek < n; radek++)
    {
        for (sloupec = 0; sloupec < n; sloupec++)
        {
            pocet = pocet + 1;
            p[radek][sloupec].obrazek = pocet % 2;
            p[radek][sloupec].viditelna = 0;
            p[radek][sloupec].odebrana = 0;
        }
    }
}

void zamichanipexesa()
{
  int radek, sloupec;
  int r, s;
  int pom;
  
  for (radek = 0; radek < n; radek++)
  {
    for (sloupec = 0; sloupec < n; sloupec++)
    {
        r = rand()%n;
        s = rand()%n;
        pom = p[radek][sloupec].obrazek;
        p[radek][sloupec].obrazek = p[r][s].obrazek;
        p[r][s].obrazek = pom;
    } 
  }
}

void zobrazenipexesa()
{
  int radek, sloupec;

  for (radek = 0; radek < n; radek++)
  {
    for (sloupec = 0; sloupec < n; sloupec++)
    {
         if (p[radek][sloupec].odebrana == 1)
         {
            printf("X ");
         }
         else
         { 
            if (p[radek][sloupec].viditelna == 1)
            {
              printf("%d ", p[radek][sloupec].obrazek);  
            }
            else
            {
              printf("0 ");  
            }
         }            
    }
    printf("\n");
  }
}


void otockarticku()
{
    int radek, sloupec;
    int kartickaok = 0;
    p[radek][sloupec].viditelna = 1;
    while (kartickaok == 0)
    {
         printf("Zadejte souradnice karticky (radek): ");
         scanf("%d", &radek);
         
        while ((radek < 0) || (radek > n-1))
        {
            printf("Zadejte znovu souradnice karticky (radek): ");
            scanf("%d", &radek);
        }
        
         printf("Zadejte souradnice karticky (sloupec): ");
         scanf("%d", &sloupec);
         
        while ((sloupec < 0) || (sloupec > n-1))
        {
            printf("Zadejte znovu souradnice karticky (sloupec): ");
            scanf("%d", &sloupec);
        }
         
         if ((p[radek][sloupec].odebrana == 0) && (p[radek][sloupec].viditelna == 0))
         {
         	kartickaok = 1;
            p[radek][sloupec].viditelna = 1;
         }
    }
    rx = radek;
    sx = sloupec;
}

void hra()
{
     int konechry, shodnekarticky;
     int hrac, radek1, radek2, sloupec1, sloupec2;
     int pocet;
     
     hrac = 0;
     konechry = 0;
     
     while (konechry == 0)
     {
     		zobrazenipexesa();
            otockarticku();
            radek1 = rx;
            sloupec1 = sx;
            zobrazenipexesa();
            otockarticku();
            radek2 = rx;
            sloupec2 = sx;
            zobrazenipexesa();
            shodnekarticky = porovnejkarticky(radek1,sloupec1,radek2,sloupec2);
            if (shodnekarticky == 1)
            {
                 ph[hrac].skore = ph[hrac].skore + 1;
                 pocet = 0;
                 for (int i = 0; i < pocethracu; i++)
                 {
                     pocet = pocet + ph[i].skore;
                 }
                 
                if (pocet == (n*n / 2))
                konechry = true;
            }
            else
            {
               if (hrac != pocethracu-1)
               {
                   hrac = hrac + 1;
               }
               else
               {
                   hrac = 0;
               }
            }
            fflush(stdin);
            getchar();
     }
}

int _tmain(int argc, _TCHAR* argv[])
{

  int radek, sloupec, pocet;

  inicializacepexesa();
  zamichanipexesa();
  inicializacehracu();
  zadejpocethracu();
  zadejjmenahracu();
  
  hra();

  zobrazenipexesa();
  
  fflush(stdin);
  getchar();
  return 0;
 }

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áš