Galgje in C++

Ok, genoeg over de basis van C++. Het is nu tijd om echt aan de slag te gaan! Met niet al te veel theorie kunnen we galgje in C++ gaan programmeren. We moeten wel een paar dingen bijleren voordat we aan de slag kunnen. Voor diegene die het nog niet weten: bij galgje is het de bedoeling dat je een woord raad door steeds letters te vragen. Als de letter in het woord voorkomt wordt deze op de juiste plaats opgeschreven. Je mag niet meer dan een bepaald aantal keer een letter fout raden.

Het stappenplan

Omdat galgje programmeren voor een beginnende programmeur best een aardig klusje is is het handig het programma eerst in pseudocode te schrijven. Je kunt hierover meer lezen in de tutorial over pseudocode. Het komt eropneer dat je een stappenplan maakt van wat het programma allemaal doet. Allereerst moet er een woord worden gekozen, de gebruiker moet om letters worden gevraagd, de letters moeten worden nagezocht in het woord en op de juiste plaats weergegeven. De pseudocode ziet er dan als volgt uit:

  1. Kies een woord uit een lijstje
  2. Tel het aantal letters in het woord en laat het zien
  3. Laat de gebruiker een letter invoeren
  4. Controleer of de letter in het woord staat
  5. Zo ja: geef de letters weer op de juiste plaats(en)
  6. Zo nee: geef het aantal fouten weer
  7. Ga terug naar stap 2 als het woord nog niet geraden is

Het laten kiezen van een woord door de computer

Om een woord te kunnen kiezen moet de computer een getal kiezen tussen de 0 en het aantal woorden in het lijstje. Hiervoor heb je een aparte functie in C++. Deze gaan we nu behandelen. Computers kunnen eigenlijk niet zomaar een getal kiezen. Gelukkig is daar een trucje op bedacht. Elke computer heeft een rij met schijnbaar willekeurig cijfers tot zijn beschikking. Als je vervolgens een seed kiest (een bepaald nummer om in de lijst mee te beginnen) kun je een willkeurig getal krijgen.

Deze functie geeft een getal terug tussen 0 en een getal dat per compiler verschilt. Ook dit kun je met een trucje omzetten naar een getal tussen 0 en een getal dat jij kiest. Dit gaat op de volgende manier:

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

int main()
{
// Voer hier het maximum in
int max = 20;

// We stellen een seed in met behulp van de tijd
srand(time(0));

// Nu wordt het toevalsgetal "gekozen"
// static_cast zorgt ervoor dat de waarde die uit rand() komt omgezet wordt
// naar een double waarde. Dat moet, omdat anders de berekening foutloopt
// en er alleen maar 0 uitkomt. Probeer het maar eens zonder!
int toevalsgetal = (static_cast <double> (rand()) / RAND_MAX * max);

// En alles komt op het scherm
cout << toevalsgetal << endl;

return 0;
}

Zoals je ziet is dat een redelijk stukje code. De uitleg van elke opdracht staat in het commentaar ervoor. Als je dit programma heel snel een aantal keer achter elkaar gebruikt zul je zien dat er een aantal keer dezelfde waarde uitkomt. Dat komt omdat de seed steeds op de tijd ingesteld wordt, en die is in seconden nauwkeurig. De hierbovenstaande generator gaan we gebruiker in ons galgje programma. (zonder al dat commentaar trouwens)

Het tellen van het aantal letters en het opzoeken van letters

Voor het bewerken van tekst heb je speciale functies. Deze functies horen bij het string-type variabele. Daarom moet je ze op een andere manier dan gewone functie gebruiken. Gelukkig is dit niet zo heel moeilijk te begrijpen. Kijk naar het volgende voorbeeld.

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

int main()
{
// We maken een string aan en stoppen er een woord in
string woord = "computer";
// En we laten aan de gebruiker zien hoe lang dit woord is
cout << "De lengte van dit woord is " << woord.length() << " tekens" << endl;
return 0;
}

Zoals je kunt zien moet je gewoon de naam van de string gebruiken en daar met een punt de functie erachter plakken. Waarom dit zo werkt ga je nog leren, dat is nu niet belangrijk. Het oproepen en het plaatsen van letters in een string is bijna net zo eenvoudig als het bovenstaande. Ook hier weer een voorbeeld:

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

int main()
{
// We maken een string aan en stoppen er een woord in
string woord = "computer";
// En we laten aan de gebruiker zien welke letter de 3e is
cout << "De 3e letter van dit woord is " << woord[2] << endl;
return 0;
}

Waarschijnlijk valt het je op dat we de 3e letter met woord[2] ophalen. Dat komt omdat computer beginnen met tellen bij 0, en niet bij 1. Als je dus de eerste letter wilt hebben, dan moet je woord[0] gebruiken. (probeer maar eens!)

Het weergeven van de gerade letters op het scherm

Om de gebuiker te laten zien welke letters er al geraden zijn is het handig om een 2e string te hebben die in eerste instantie alleen maar punten bevat. Als de gebruiker dan een letter raad moet het programma de letters op de juiste plekken zetten. Dit gaat net zo makkelijk als het lezen van een teken op een bepaalde plaats in een string. Zie hiervoor het onderstaande voorbeeld.

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

int main()
{
// We maken een string aan en stoppen er een woord in
string woord = "computer";
// We vervangen de 5e letter door een o
woord[4]='o';
// En we laten het zien
cout << "Dit woord is nu " << woord << endl;
return 0;
}

Ook hier moet je weer oppassen met tellen!

Het werken met arrays, char's en bools

Dan is er nog een laatste ding wat je moet weten. We hebben tot nu toe verschillende soorten variabelen behandeld, zoals de string, de integer en de float. Je kunt ook een soort lijst van variabelen maken, een array. Als je een variabele ziet als een laatje waar je een getal in kunt stoppen kun je een array als een ladekast zien. We hebben de array nodig om de woorden in op te slaan waaruit we een woord kiezen. We gaan het binnenkort nog uitgebreider over arrays hebben, het is nu alleen belangrijk te weten hoe ze werken.

Je moet bij het aanwijzen van een array aangeven hoeveel variabelen erin moeten passen. We nemen nu een lijstje van 10 woorden. (je kunt er natuurlijk zelf meer van maken) Je moet ook aangeven welk type variabelen er in de array moeten. In dit geval gaan er strings in.

Je kunt meteen een "rij" met spullen in de array stoppen door te beginnen met een accolade (het {-teken), alle dingen van elkaar te scheiden met komma's en vervolgens af te sluiten met een accolade (het }-teken). Je kunt de waarde op dezelfde manier uit een array halen als we net bij de strings een bepaalde letter ophaalden. Zie het volgende voorbeeld.

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

int main()
{
// We maken een array met woorden. Zoals je ziet is dit een array met strings
// De accolades geven het begin en het einde van de reeks aan en de komma's scheiden de woorden van elkaar
string woordenlijst[10] = {"computer","printer","schroevendraaier","muziek","boek","website","rekenmachine","toetsenbord","internet","muis"};
// Nu laten we het 3e element uit de lijst zien. Ook hier moet je oppassen met tellen
cout << woordenlijst[2] << endl;
return 0;
}

Dan is er ook nog het variabele type char. Char is een losse letter of cijfer. Als laatste gaan we ook nog de bool gebruiken. In de bool zit alleen de waarde true (waar) of false (niet waar). We gebruiken deze om te kijken of de letter in het woord zit. Zo niet, dan is deze bool false en tellen we er een fout bij.

Hopelijk kun je het bijbenen, want het tempo ligt behoorlijk hoog. Mocht je het niet snappen, vraag het dan even op het forum.

En dan...

Dan kunnen we eindelijk aan het programma beginnen. Je kunt het denk ik ook eerst zelf proberen te maken.

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

int main()
{
// Ok, we beginnen met het maken van een array en daar de woorden in te stoppen
// Daarna maken we alle andere gebruikte variabelen aan
string woordenlijst[10] = {"computer","printer","schroevendraaier","muziek","boek","website","rekenmachine","toetsenbord","internet","muis"};
int fouten = 0;
bool letter_komt_voor = false;
char letter; string woord;
string geraden;

// We gaan een willekeurig getal opzoeken
srand(time(0));
int toevalsgetal = (static_cast <double> (rand()) / RAND_MAX * 9);

// We hebben nu een getal dat van 0 tot 9 loopt. We halen het uit de lijst
// en stoppen het in de variabele woord
woord = woordenlijst[toevalsgetal];

// Nu moeten we in geraden een aantal punten stoppen. Dit doen we met een lus
// Met geraden = geraden + "." plakken we een punt aan het eind van de string
for(int i = 0;i < woord.length(); i++)
{ geraden = geraden + "."; }

// We laten de punten zien en vragen de gebruiker om een letter
// Dit stuk moet herhaald worden, dus we beginnen hier een lus
do{ cout << geraden << endl << "Welke letter? ";
cin >> letter;
// Ok, we hebben nu een letter. We gaan de hele string aflopen
for(int i = 0;i < woord.length(); i++)
{ if(woord[i] == letter)
{ // Als de letter voorkomt plaatsen we die letter
// Op de juiste plaats in de geraden string
// en zetten we de bool op true
geraden[i] = letter;
letter_komt_voor = true;
}
}
// Ok, nu hebben we de letters op de juiste plaats. Nu het aantal fouten
// Controleren en eventueel een nieuwe fout toevoegen
if(letter_komt_voor == false)
{ // Letter komt niet voor, tel fout erbij op en laat zien
fouten++;
cout << "Fout! Je hebt nu al " << fouten << " fouten gemaakt! Je mag er 15 maken" << endl;
// Controleer of de gebruiker hangt. Zo ja, sluit dan af
if(fouten > 15)
{ cout << "Je hangt!" << endl;
exit(0);
}
}
else
{ // Letter komt wel voor, zet bool terug op false
letter_komt_voor = false;
cout << "Dat is goed!" << endl;
}
// Ok, we zijn klaar. Controleer of het woord al geraden is
// en herhaal anders de lus
} while(geraden != woord);
return 0;
}

Klaar!

Zo, dat was een hele klus. Ik kan me voorstellen dat sommige onderdelen onduidelijk zijn. Je kunt altijd extra hulp vragen op het forum als je het niet snapt. Ik hoop in ieder geval dat je het wel snapt zodat je verder kunt naar de volgende tutorial.