Czech version
logolink

< Back to the list of lessons

Memory Game IV

AlgortimyContent of the lesson:

  • Turning Cards - Part II
  • Initializing Players
  • Entering Number of Players
  • Entering Names of Players

Handling Problems When Turning Cards

We completed the easier version of our procedure to turn a card. However, we did not treat any errors like an attempt to turn the same card twice or entering a value out of bounds of array. The procedure otockarticku has this appearance:

Turning a card
void otockarticku(int radek, int sloupec)
{
    p[radek][sloupec].viditelna = 1;
}

You have to treat these errors which can occur:

  • Turning the same card twice
  • Turning already removed card
  • An attempt to turn a card out of bounds of array pexeso

We will use a cycle to repeat the entering process to be able to treat this three problems.

Create a new variable named kartickaok for this purpose which will store the information whether the cycle should be run once again.

After launching the procedure, the variable is set to 0 to run the cycle once at least. A player will be asked to enter the value of row and column inside the cycle. After entering values they are checked because the same card cannot be turned twice. In case this condition is valid, the variable kartickaok is set to 1 and the cycle is terminated. You will treat two of three problems using this method ("Turning the same card twice" and "Turning already removed card").

Turning a card
void otockarticku()
{
    int radek, sloupec;
    int kartickaok = 0;
    p[radek][sloupec].viditelna = 1;
    while (kartickaok == 0)
    {
         printf("Zadejte souradnice karticky (radek): ");
         scanf("%d", &radek);
         printf("Zadejte souradnice karticky (sloupec): ");
         scanf("%d", &sloupec);
         
         if ((p[radek][sloupec].odebrana == 0) && (p[radek][sloupec].viditelna == 0))
         {
         	kartickaok = 1;
            p[radek][sloupec].viditelna = 1;
         }
    }
}

Then you have to treat the situation when user enters one or both values out of bounds of the array pexeso. Add two more cycles behind the entering mechanism - one to repeat entering the row in case the value is not valid and the other one to repeat entering the column in case the value is not valid. A valid number must be in interval 0 to n-1.

After this adjustment our procedure should look like the following one:

Turning a card
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;
}

Because of the fact, that we can not return two values from the function in C language, we must create two global variables rx and sx, which we will use for passing the values. The second way is to use the pointers, but this topic is over the scope of our course.

To be able to debug our program we should adjust the main part of the program which calls the procedure to turn a card. We will not load the coordinates in the main part but in the procedure otockarticku.

Delete these lines from the main part:

printf("Zadejte souradnice 1. karticky (radek): ");
scanf("%d", radek1);
printf("Zadejte souradnice 1. karticky (sloupec): ");
scanf("%d", sloupec1);

printf("Zadejte souradnice 2. karticky (radek): ");
scanf("%d", radek2);
printf("Zadejte souradnice 2. karticky (sloupec): ");
scanf("%d", sloupec2);
And insert the call to procedure otockarticku:
   otockarticku();
   radek1 = rx;
   sloupec1 = sx;
   otockarticku();
   radek2 = rx;
   sloupec2 = sx;

Initializing Players

In previous lessons we dealt with the cards only. Now we can move to the next part - to the players. At first you have to initialize (to set default values) the array of players. We made the same operation when creating cards and filling them with default values.

Players are realized as an array of structures (of data type record) which consists of these variables:

  • Name - unique identifier of each player. Use string data type (can store up to 255 characters).
  • Score - the number of removed couples by this player. Use byte data type (values will be in interval 0-18).
  • When we are inicializing the players, we must use the function for change the string - funkci strcpy(), We must append the header file string.h to our program. We must add the following line:

    Přidání hlavičkového souboru string.h
        #include <string.h>
        

We will set the name to void and the score to 0 for the whole array (using the variable maxhracu).

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

Using the for cycle to go through the array. You should use the variable i, which is increased from 1 to maxhracu and goes through the whole array ph (where we store our players).

Entering Number of Players

To be able to enter the number of players we have to define a new global variable to store the number or players. This variable has to be global to be accessible from any procedure as well as from the main part.

Name the variable as pocethracu and use the byte data type.

The following source code illustrates the basic version of our procedure:

Entering Number of Players
void zadejpocethracu()
    {
         printf("Zadejte pocet hracu: ");
         scanf("%d",&pocethracu);
    }

This procedure is quite simple; it only writes the text using the loaded variable from user.

This simple variant has one huge disadvantage - user can enter any value although we defined the upper limit of players using the maxhracu constant. You can remove this problem using the while cycle and these steps:

  • Load the value of pocethracu using the current version of procedure at first.
  • Add a while cycle behind it to be executed as long as the variable pocethracu is lower than 2 or greater than the value of maxhracu. An error message should be written inside this cycle and it should ask user to re-enter the value.
Entering Number of Players - Final Version
void zadejpocethracu()
    {
         printf("Zadejte pocet hracu: ");
         scanf("%d",&pocethracu);
         while ((pocethracu < 2) or (pocethracu > maxhracu))
         {
             printf("Zadejte znovu: ");
             scanf("%d",&pocethracu);         
         }
    }

Entering Names of Players

The next step is entering the names of players. Create a new procedure using a simple for cycle which goes through the array of players (from 1 to pocethracu - this value was acquired using the zadejpocethracu procedure) and asks each player to enter his name.

Entering Names of Players
void zadejjmenahracu()
{
    int i;
    printf("Zadejte jmena hracu:\n");
    for (i = 0; i < pocethracu; i++)
    {
        scanf("%s", &ph[i].jmeno);
    }
}

You can edit the procedure to show information like "Enter name of Player 1:", "Enter name of Player 2:" and so on.

Entering Names of Players
    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);
    }
}

Adding Calls to Procedures to the Main Program

To be able to test everything you have to add calls to all procedures you have created of course. The entire source code using upgrades from this lesson is available below this text.

The entire source code
#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;
}

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

  int radek, sloupec, pocet;

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

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

   otockarticku();
   radek1 = rx;
   sloupec1 = sx;
   otockarticku();
   radek2 = rx;
   sloupec2 = sx;

  zobrazenipexesa();
  
  fflush(stdin);
  getchar();
  return 0;
 }
webdesign, xhtml, css, php - Mgr. Michal Mikláš