Boter, kaas en eieren in C++

Home / Programmeren / Cplusplus / Boter kaas en eieren

Na galgje is het tijd voor een ander, simpel spelletje, boter kaas en eieren, ook wel rondje-kruisje genoemd. Je hebt hierbij een veld van 3x3 vakjes waarin de speler om de beurt rondjes en kruisjes moeten invullen. Als je er 3 op 1 rij weet te krijgen heb je gewonnen.

Het stappenplan (de pseudocode)

Omdat ook boter kaas en eieren niet zo simpel in elkaar zit is het handig een stappenplan te maken.

  1. We moeten een opslagruimte hebben waarin we de 9 vakjes kwijtkunnen
  2. Laat de gebruiker het rooster zien
  3. Vraag de gebruiker een plaats voor zijn kruisje te kiezen
  4. Plaats het kruisje op de juiste plaats
  5. Controleer of er 3 kruisjes op een rij zitten
  6. Laat de computer een plaats kiezen om zijn rondje neer te zetten
  7. Plaats het rondje op de juiste plaats
  8. Controleer of er 3 rondjes op een rij zitten
  9. Ga terug naar stap 2

Voordat we aan de slag kunnen moeten we weer een aantal dingen bijleren.

Arrays

In de vorige tutorial hebben we het al even over arrays gehad. Arrays waren die ladekasten met variabelen, ofwel een variabelen waarin meerdere variabelen kunnen. Als we nu zo'n ladekast van 3 bij 3 variabelen kunnen maken zijn we klaar... gelukkig kan dat! Zoals je weet moet je spullen in een array stoppen door ze met komma's gescheiden tussen accolades te plaatsen. Dat komt er dan zo uit te zien:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
// Maak een char-array
char raster[3][3] =
{ {' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '}
};
return 0;
}

Zoals je kunt zien stoppen we eigenlijk 3 arrays in 1 andere array. Als je dit op deze manier opmaakt is het duidelijk wat je doet. Je hoeft niet steeds witregels en inspringen te gebruiken, maar het helpt wel om duidelijk te maken wat er gebeurd. We hebben nu 3 arrays die allemaal 3 waarden bevatten.

Misschien is het je opgevallen dat deze array een char-array is. We hebben de char in de vorige tutorial al heel even behandeld: de char is een los teken. We hebben nu 9 spaties in de array gestopt. Ook opvallend is dat je hier enkele aanhalingstekens moet gebruiken in plaats van dubbele. (dus ' in plaats van ") Je gebruikt de dubbele altijd bij strings en de enkele bij chars. Straks plaatsen we de kruisjes of rondjes op de plaats waar ze horen, ze vervangen dan de spaties in de array.

Controleren of er 3 kruisjes op een rij staan

Het plaatsen van het kruisje is niet zo'n probleem, dus ik ga verder met het controleren of er 3 kruisjes op een rij staan. Dit is wat lastiger, omdat je hier weer met arrays moet gaan werken. Er zijn 3 mogelijkheden om 3 kruisjes op een rij te krijgen: een rijtje van boven naar beneden, een rijtje van links naar rechts en een schuin rijtje. We moeten al deze mogelijkheden controleren. We beginnen met de rijtjes van links naar rechts.

Meerdere dingen tegelijk controleren

We moeten nu controleren of alledrie de vakjes een x bevatten. Daar is een speciaal teken voor, &&. Met && kun je 2 of meer voorwaarden aan elkaar binden. Zie het onderstaande voorbeeld:

if(variabele1 = "ja" && variabele2 = "nee")
{cout << "Dit krijg je alleen te zien als zowel variabele 1 ja is en variabele 2 nee is"; }

Oke, nu kunnen we echt aan de slag. Kijk goed naar de code hieronder:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
// Maak een char-array
char raster[3][3] =
{ {'x', 'x', 'x'},
{'0', 'x', '0'},
{'x', '0', 'x'}
};

// Ok, we hebben nu een gevulde array. Laten we controleren of er een rijtje
// van links naar rechts inzit. Hiervoor moeten we alledrie de rijtjes controleren

if(raster[0][0] == 'x' && raster[0][1] == 'x' && raster[0][2] == 'x')
{cout << "Ja! Het eerste rijtje is een rijtje met x-en" << endl; }

if(raster[1][0] == 'x' && raster[1][1] == 'x' && raster[1][2] == 'x')
{cout << "Ja! Het tweede rijtje is een rijtje met x-en" << endl; }

if(raster[2][0] == 'x' && raster[2][1] == 'x' && raster[2][2] == 'x')
{cout << "Ja! Het derde rijtje is een rijtje met x-en" << endl; }
return 0;
}

Oke, dan hebben we het moeilijkste stukje gehad. We kunnen nu gewoon dezelfde code (met een kleine aanpassing) gebruiken om rijtjes van boven naar beneden en schuine rijtjes op te zoeken.

De computer een rondje laten plaatsen

Dan moet de computer een rondje plaatsen... het is nu nog te moeilijk om een ingewikkeld systeem te maken waarmee de computer onverslaanbaar wordt (waardoor het spel ook helemaal niet meer leuk is) dus we houden het simpel: we laten de computer een rondje op een willekeurige plaats zetten, zolang er maar geen kruisje staat!

Hiervoor gebruiken we ook weer het systeem om willekeurige getallen te maken uit de vorige tutorial, alleen nu hebben we twee getallen tussen de 0 en de 2 nodig. De computer moet controleren of daar al een kruisje staat. Staat er geen kruisje, dan plaatst de computer op die plaats een rondje. Staat er wel een kruisje, dan probeert de computer twee andere willekeurige waarden.

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
// Maak de char-array
char raster[3][3] =
{ {'x', ' ', ' '},
{' ', 'x', ' '},
{' ', ' ', ' '}
};
int max = 3;
// De maximale waarde moet hier 3 zijn, omdat dat betekend dat hij tot 3 gaat, niet tot en met
// We moeten de seed steeds opnieuw maken, anders krijgen we steeds dezelfde getallen!
// Daarom is het handig een aparte variabele voor de seed aan te maken
int seed = time(0);
int toevalsgetal1, toevalsgetal2;

// We starten een lus, omdat dit moet herhalen tot het rondje ergens geplaatst kan worden
do { // Nu wordt het 1e toevalsgetal gekozen
// We maken eerst een nieuwe seed aan, en maken de seed meteen 1 hoger
srand(seed++);
toevalsgetal1 = (static_cast <double> (rand()) / RAND_MAX * max);

// Nu wordt het 2e toevalsgetal gekozen
srand(seed++);
toevalsgetal2 = (static_cast <double> (rand()) / RAND_MAX * max);

// Als er nog niets in het gekozen hokje staat breken we de lus af, anders gaan we door
} while (raster[toevalsgetal1][toevalsgetal2]!=' ');

// De lus is afgebroken, dus blijkbaar stond er niets op de plaats. We plaatsen het rondje
raster[toevalsgetal1][toevalsgetal2]='0';
return 0;
}

Oke, aan de slag!

We hebben nu alle benodigdheden klaarliggen, klaar om het echte programma te maken. We pakken eerst de pseudocode er nog eens bij:

  1. We moeten een opslagruimte hebben waarin we de 9 vakjes kwijtkunnen
  2. Laat de gebruiker het rooster zien
  3. Vraag de gebruiker een plaats voor zijn kruisje te kiezen en controleer of dat kan
  4. Plaats het kruisje op de juiste plaats
  5. Controleer of er 3 kruisjes op een rij zitten
  6. Laat de computer een plaats kiezen om zijn rondje neer te zetten
  7. Plaats het rondje op de juiste plaats
  8. Controleer of er 3 rondjes op een rij zitten
  9. Ga terug naar stap 2

We gaan dit nu stap voor stap afwerken. Zie daarvoor de onderstaande code en het bijbehorende commentaar:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
// Maak de char-array
char raster[3][3] =
{ {' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '}
};
// Maak de andere benodigde variabelen
int horizontaal;
int verticaal;
string gewonnen = "";

// We starten een lus, omdat we dit moeten herhalen totdat het spel gewonnen is
do { // We laten de gebruiker het rooster zien
cout << raster[0][0] << raster[0][1] << raster[0][2] << endl;
cout << raster[1][0] << raster[1][1] << raster[1][2] << endl;
cout << raster[2][0] << raster[2][1] << raster[2][2] << endl;

// We moeten een lus starten om de gebruiker om een plek voor zijn kruisje te vragen
// net zolang tot op die plaats een kruis gezet kan worden
do { // We vragen de gebruiker een kruisje te zetten
cout << "Op welke horizontale rij wil je je kruisje? (1, 2 of 3)" << endl;
cin >> horizontaal;
cout << "Op welke verticale kolom wil je je kruisje? (1, 2 of 3)" << endl;
cin >> verticaal;

// De ingevoerde getallen lopen van 1 tot en met 3, maar dat moet van 0 tot en met 2
// anders kan het niet met de array. We trekken er 1 vanaf met de -- operator
horizontaal--;
verticaal--;
} while (raster[horizontaal][verticaal]!=' ');

// Zolang het niet kan wordt de lus herhaalt. Als de lus is gestopt komen we bij de code
// hieronder, dus het kruisje kan geplaatst worden. We plaatsen het kruisje op de juiste plaats
raster[horizontaal][verticaal]='x'; // Ok, controleer of er 3 horizontaal op een rij zitten

if(raster[0][0] == 'x' && raster[0][1] == 'x' && raster[0][2] == 'x')
{gewonnen = "jij"; }

if(raster[1][0] == 'x' && raster[1][1] == 'x' && raster[1][2] == 'x')
{gewonnen = "jij"; }

if(raster[2][0] == 'x' && raster[2][1] == 'x' && raster[2][2] == 'x')
{gewonnen = "jij"; }
// Controleer of er 3 verticaal op een rij zitten

if(raster[0][0] == 'x' && raster[1][0] == 'x' && raster[2][0] == 'x')
{gewonnen = "jij"; }

if(raster[1][0] == 'x' && raster[1][1] == 'x' && raster[2][1] == 'x')
{gewonnen = "jij"; }

if(raster[2][0] == 'x' && raster[2][1] == 'x' && raster[2][2] == 'x')
{gewonnen = "jij"; }
// Controleer of er 3 schuin op een rij zitten

if(raster[0][0] == 'x' && raster[1][1] == 'x' && raster[2][2] == 'x')
{gewonnen = "jij"; }

if(raster[2][0] == 'x' && raster[1][1] == 'x' && raster[0][2] == 'x')
{gewonnen = "jij"; }

// Tijd voor de computer om een plaats te kiezen
int max = 3;
int seed = time(0);
int toevalsgetal1, toevalsgetal2;

do { srand(seed++);
toevalsgetal1 = (static_cast <double> (rand()) / RAND_MAX * max);

// Nu wordt het 2e toevalsgetal gekozen
srand(seed++);
toevalsgetal2 = (static_cast <double> (rand()) / RAND_MAX * max);

// Als er nog niets in het gekozen hokje staat breken we de lus af, anders gaan we door
} while (raster[toevalsgetal1][toevalsgetal2]!=' ');

// De lus is afgebroken, dus blijkbaar stond er niets op de plaats. We plaatsen het rondje
raster[toevalsgetal1][toevalsgetal2]='0';
} while (gewonnen=="");

// Nu even aangeven wie er gewonnen heeft
if(gewonnen=="jij")
{ cout << "Gefeliciteerd! Je hebt gewonnen!"; }
else
{ cout << "Helaas, de computer was je te slim af!"; }
return 0;
}

Zo, probeer dit eens te compileren, te spelen, en vooral te begrijpen wat er gebeurt. De code is nog niet helemaal af: als de computer wint wordt het spel niet afgesloten. (er wordt niet eens gecontroleerd of de computer gewonnen heeft) Als extra oefening kun je hiervoor code inbouwen. Ook hier kun je voor extra ondersteuning vragen stellen op het forum.