//Rick van der Zwet //Pascal de Vos //Programeeropgave 4, Nim Spel #include #include #include using namespace std; //constanten const int MaxStapels = 4; //Maximale Aantal Stapels const int MaxAantal = 4; //Maximale Aantal Lucifers //creeer random getal met behulp van de random functie; int RandomGetal(int Min, int Max){ return ( Min + int( double(Max + 1 - Min) * rand()/(RAND_MAX+1.0)) ); } //RandomGetal //Zorgt dat de gebruiker enkel getallen <= Max in kan voeren int VoerInGetal(int Min, int Max){ int x = 0; do { if(!(cin >> x)) { cout << "Enkel Cijfers aub" << endl; cin.clear(); cin.ignore(10000,'\n'); } else if (x > Max) { cout << "Te groot getal" << endl; } else if (x < Min) { cout << "Te klein getal" << endl; }// end if } // end do while((x < Min) or (x > Max)); return x; } //end VoerInGetal //Class die gebruikt wordt om terugzetten te realiseren class NimData{ public: NimData( ); //creator ~NimData( ) { }; int StapelNummer; //Nummer van de stapel waar het int AantalEraf; //AantalEraf af is gegaan NimData * VorigeZet_pt; //Pointer naar de zet ervoor, maakt stapelen mogelijk };// end NimData NimData::NimData( ){ StapelNummer = 0; AantalEraf = 0; VorigeZet_pt = NULL; }// end NimData::NimData class NimSpel{ public: NimSpel( ); //creator ~NimSpel( ) { }; //destructor void NimSpelen( ); //Main programma private: NimData * LaatsteZet_pt; //Pointer naar gegevens laatste zet int AantalZetten; //aantal zetten dat gedaan is int Stapels[MaxStapels]; //aantal luicifers per stapel int SpelerAanBeurt; //speler die aan de beurt is //2 spelers, nummer 1 is de speler, nummer 2 is computer double WinstArray[MaxAantal + 1][3]; //slim berekende winst array voor computer 'ai' //[0] = totaal aantal mogelijkheden, [1] = aantal winnen, [2] = aantal verliezen void PakWeg(int Groep, int Aantal); //Haal Aantal uit Stapels[Groep] void ZetTerug(int AantalStappen); //Ga AantalStappen terug void SpelerKiest ( ); //Invoerscherm voor gebruiker void ComputerNiveauSlim(int * StapelNummer, int * Aantal); //Computer berekening void ComputerKiest (int Niveau); //ComputerHandelingen void DrukAf( ); //Druk Spel af bool SpelAfgelopen( ); // Kijken af alles afgelopen is }; //end NimSpel //init van de groepen array NimSpel::NimSpel( ){ LaatsteZet_pt = NULL; AantalZetten = 0; SpelerAanBeurt = 1; for(int i = 0; i < MaxStapels; i++) { Stapels[i] = MaxAantal; } //end for //Bedacht en getest algoritme WinstArray[0][0] = 1; WinstArray[0][1] = 0; WinstArray[0][2] = 1; WinstArray[1][0] = 1; WinstArray[1][1] = 1; WinstArray[1][2] = 0; WinstArray[2][0] = 1; WinstArray[2][1] = 1; WinstArray[2][2] = 0; for(int i = 3; i < MaxAantal + 1; i++){ WinstArray[i][0] = WinstArray[i-1][0] + WinstArray[i-2][0]; WinstArray[i][1] = WinstArray[i-1][2] + WinstArray[i-2][2]; WinstArray[i][2] = WinstArray[i][0] - WinstArray[i][1]; } } //end NimSpel::NimSpel void NimSpel::PakWeg(int StapelNummer, int Aantal){ NimData * temp_pt; // temp_pt = new NimData; // temp_pt->VorigeZet_pt = LaatsteZet_pt; //Zetten onthouden LaatsteZet_pt = temp_pt; // LaatsteZet_pt->StapelNummer = StapelNummer; // LaatsteZet_pt->AantalEraf = Aantal; // AantalZetten++; //Max Zetten bijhouden Stapels[StapelNummer] = Stapels[StapelNummer] - Aantal; } //end NimSpel::NimSpel void NimSpel::ZetTerug(int AantalStappen) { NimData * temp_pt; for(int i = 0; i < AantalStappen; i++) { temp_pt = LaatsteZet_pt; Stapels[temp_pt->StapelNummer] = Stapels[temp_pt->StapelNummer] + temp_pt->AantalEraf; AantalZetten--; LaatsteZet_pt = temp_pt->VorigeZet_pt; delete temp_pt; } //end for } //end NimSpel::ZetTerug void NimSpel::SpelerKiest( ){ int StapelNummer, Aantal, AantalStappen = 0; cout << "Maximaal terug te zetten zetten: " << AantalZetten << endl << "'0' om niet terug te zetten" << endl << "Aantal zetten: "; AantalStappen = VoerInGetal(0, AantalZetten); if (AantalStappen == 0) { do{ cout << "Speler aan de beurt" << endl; cout << "Welke stapel [0-" << (MaxStapels - 1) << "] : "; StapelNummer = VoerInGetal(0, MaxStapels - 1); cout << "Hoeveel [1-2] : "; Aantal = VoerInGetal(1, 2); if (Stapels[StapelNummer] - Aantal < 0){ cout << Stapels[StapelNummer] << endl; cout << "Geen Geldige Combinatie, probeer opnieuw"; } //end if } //end do while(Stapels[StapelNummer] - Aantal < 0); PakWeg(StapelNummer, Aantal); } else { //Ga AantalStappen terug zetten ZetTerug(AantalStappen); SpelerAanBeurt = SpelerAanBeurt - 1 + (AantalStappen%2); //ivm met onevenaantal terug zetten }// end if } //end NimSpel::SpelerKiest void NimSpel::ComputerNiveauSlim(int * StapelNummer, int * Aantal) { double KansMax, KansMet1, KansMet2 = 0; //tempvariablen, voor het bepalen van de max for(int i = 0; i < MaxStapels; i++) { if (Stapels[i] > 0) { KansMet1 = WinstArray[Stapels[i]-1][2] / WinstArray[Stapels[i]-2][0]; } else { KansMet1 = 0; }//end if if (Stapels[i] > 1) { KansMet2 = WinstArray[Stapels[i]-2][2] / WinstArray[Stapels[i]-2][0]; } else { KansMet2 = 0; }//end if if(KansMet1 > KansMax) { *Aantal = 1; *StapelNummer = i; KansMax = KansMet1; }//end if if(KansMet2 > KansMax) { *Aantal = 2; *StapelNummer = i; KansMax = KansMet2; }//end if }//end for }// end NimSpel::ComputerNiveauSlim void NimSpel::ComputerKiest(int Niveau) { int StapelNummer = 0; //Voor het geval alles op verliezen staat ;-) int Aantal = 1; // char wait; //loze char ivm met Wachten om ENTER invoer. cout << "Computer Kiest..." << endl; switch (Niveau) { case 1: //random keuze do { StapelNummer = RandomGetal(0, (MaxStapels-1)); Aantal = RandomGetal(1, 2); } //end do while(Stapels[StapelNummer] - Aantal < 0); break; case 2: //slimme keuze ComputerNiveauSlim(&StapelNummer, &Aantal); break; default: //dedug keuze StapelNummer = 0; Aantal = 2; break; } //end switch cout << "Stapel: " << StapelNummer << endl; cout << "Aantal: " << Aantal << endl; cout << "Druk op ENTER..."; cin.clear(); cin.ignore(10000,'\n'); cin.get(wait); PakWeg(StapelNummer, Aantal); } //end NimSpel::Computerkiest void NimSpel::DrukAf( ){ system("clear"); //OS Dependent Line, for windows use 'system("cls");' instead. cout << endl << " : "; for(int i = 0; i < MaxStapels; i++) { if (i < 10) {cout << " " << i << " | ";} else { cout << i << " | ";} }//end for for(int i = 1; i <= MaxAantal; i++) { cout << endl; if (i < 10) {cout << " " << i << " : ";} else { cout << i << " : ";} for(int j = 0; j < MaxStapels; j++) { if (i <= Stapels[j]) { cout << "XX | ";} else { cout << " | ";} }//end for }//end for cout << endl << endl; }//end NimSpelDrukAf bool NimSpel::SpelAfgelopen( ){ for(int i = 0; i < MaxStapels; i++) { if (Stapels[i] > 0) { //als er nog ergens waardes aanwezig zijn return (false); }//end if }//end if return (true); }//end NimSpelAfgelopen void NimSpel::NimSpelen( ){ int Niveau = 0; // cout << endl // << "Geef het niveau aan" << endl // << "1) Random " << endl //Niveau bepalen << "2) Winnend Spelen " << endl;// Niveau =VoerInGetal(1,2); // while (not(SpelAfgelopen( ))) { //Zolang spel niet afgelopen DrukAf( ); //Druk bord af if (SpelerAanBeurt == 1) { //a1) Speler 1 aan de beurt SpelerKiest( ); //a2) Speler Doorwerken, keuzes enz. SpelerAanBeurt++; //a3) Computer aan de beurt } else if (SpelerAanBeurt == 2) { //b1) Computer aan de Beurt ComputerKiest(Niveau); //b2) Computer op Niveau laten spelen SpelerAanBeurt = 1; //b3) Speler aan de beurt } //end if } //end while if (SpelerAanBeurt == 2) { //ivm met regels a3,b3 cout << "Voila uw heeft GEWONNEN" << endl; } else { cout << "DE COMPUTER IS DE BESTE !!!" <