1 | //Rick van der Zwet
|
---|
2 | //Pascal de Vos
|
---|
3 | //Programeeropgave 4, Nim Spel
|
---|
4 |
|
---|
5 | #include <iostream>
|
---|
6 | #include <ctime>
|
---|
7 | #include <cstdlib>
|
---|
8 |
|
---|
9 | using namespace std;
|
---|
10 |
|
---|
11 | //constanten
|
---|
12 | const int MaxStapels = 4; //Maximale Aantal Stapels
|
---|
13 | const int MaxAantal = 4; //Maximale Aantal Lucifers
|
---|
14 |
|
---|
15 |
|
---|
16 |
|
---|
17 | //creeer random getal met behulp van de random functie;
|
---|
18 | int RandomGetal(int Min, int Max){
|
---|
19 | return ( Min + int( double(Max + 1 - Min) * rand()/(RAND_MAX+1.0)) );
|
---|
20 | } //RandomGetal
|
---|
21 |
|
---|
22 |
|
---|
23 |
|
---|
24 | //Zorgt dat de gebruiker enkel getallen <= Max in kan voeren
|
---|
25 | int VoerInGetal(int Min, int Max){
|
---|
26 | int x = 0;
|
---|
27 | do {
|
---|
28 | if(!(cin >> x)) {
|
---|
29 | cout << "Enkel Cijfers aub" << endl;
|
---|
30 | cin.clear();
|
---|
31 | cin.ignore(10000,'\n');
|
---|
32 | }
|
---|
33 | else if (x > Max) {
|
---|
34 | cout << "Te groot getal" << endl;
|
---|
35 | }
|
---|
36 | else if (x < Min) {
|
---|
37 | cout << "Te klein getal" << endl;
|
---|
38 | }// end if
|
---|
39 | } // end do
|
---|
40 | while((x < Min) or (x > Max));
|
---|
41 | return x;
|
---|
42 | } //end VoerInGetal
|
---|
43 |
|
---|
44 |
|
---|
45 |
|
---|
46 | //Class die gebruikt wordt om terugzetten te realiseren
|
---|
47 | class NimData{
|
---|
48 | public:
|
---|
49 | NimData( ); //creator
|
---|
50 | ~NimData( ) { };
|
---|
51 | int StapelNummer; //Nummer van de stapel waar het
|
---|
52 | int AantalEraf; //AantalEraf af is gegaan
|
---|
53 | NimData * VorigeZet_pt; //Pointer naar de zet ervoor, maakt stapelen mogelijk
|
---|
54 | };// end NimData
|
---|
55 |
|
---|
56 | NimData::NimData( ){
|
---|
57 | StapelNummer = 0;
|
---|
58 | AantalEraf = 0;
|
---|
59 | VorigeZet_pt = NULL;
|
---|
60 | }// end NimData::NimData
|
---|
61 |
|
---|
62 |
|
---|
63 |
|
---|
64 | class NimSpel{
|
---|
65 | public:
|
---|
66 | NimSpel( ); //creator
|
---|
67 | ~NimSpel( ) { }; //destructor
|
---|
68 | void NimSpelen( ); //Main programma
|
---|
69 | private:
|
---|
70 | NimData * LaatsteZet_pt; //Pointer naar gegevens laatste zet
|
---|
71 | int AantalZetten; //aantal zetten dat gedaan is
|
---|
72 | int Stapels[MaxStapels]; //aantal luicifers per stapel
|
---|
73 | int SpelerAanBeurt; //speler die aan de beurt is
|
---|
74 | //2 spelers, nummer 1 is de speler, nummer 2 is computer
|
---|
75 | double WinstArray[MaxAantal + 1][3]; //slim berekende winst array voor computer 'ai'
|
---|
76 | //[0] = totaal aantal mogelijkheden, [1] = aantal winnen, [2] = aantal verliezen
|
---|
77 |
|
---|
78 | void PakWeg(int Groep, int Aantal); //Haal Aantal uit Stapels[Groep]
|
---|
79 | void ZetTerug(int AantalStappen); //Ga AantalStappen terug
|
---|
80 | void SpelerKiest ( ); //Invoerscherm voor gebruiker
|
---|
81 | void ComputerNiveauSlim(int * StapelNummer, int * Aantal); //Computer berekening
|
---|
82 | void ComputerKiest (int Niveau); //ComputerHandelingen
|
---|
83 | void DrukAf( ); //Druk Spel af
|
---|
84 | bool SpelAfgelopen( ); // Kijken af alles afgelopen is
|
---|
85 | }; //end NimSpel
|
---|
86 |
|
---|
87 |
|
---|
88 |
|
---|
89 | //init van de groepen array
|
---|
90 | NimSpel::NimSpel( ){
|
---|
91 | LaatsteZet_pt = NULL;
|
---|
92 | AantalZetten = 0;
|
---|
93 | SpelerAanBeurt = 1;
|
---|
94 |
|
---|
95 | for(int i = 0; i < MaxStapels; i++) {
|
---|
96 | Stapels[i] = MaxAantal;
|
---|
97 | } //end for
|
---|
98 |
|
---|
99 | //Bedacht en getest algoritme
|
---|
100 | WinstArray[0][0] = 1;
|
---|
101 | WinstArray[0][1] = 0;
|
---|
102 | WinstArray[0][2] = 1;
|
---|
103 | WinstArray[1][0] = 1;
|
---|
104 | WinstArray[1][1] = 1;
|
---|
105 | WinstArray[1][2] = 0;
|
---|
106 | WinstArray[2][0] = 1;
|
---|
107 | WinstArray[2][1] = 1;
|
---|
108 | WinstArray[2][2] = 0;
|
---|
109 | for(int i = 3; i < MaxAantal + 1; i++){
|
---|
110 | WinstArray[i][0] = WinstArray[i-1][0] + WinstArray[i-2][0];
|
---|
111 | WinstArray[i][1] = WinstArray[i-1][2] + WinstArray[i-2][2];
|
---|
112 | WinstArray[i][2] = WinstArray[i][0] - WinstArray[i][1];
|
---|
113 | }
|
---|
114 | } //end NimSpel::NimSpel
|
---|
115 |
|
---|
116 |
|
---|
117 |
|
---|
118 | void NimSpel::PakWeg(int StapelNummer, int Aantal){
|
---|
119 | NimData * temp_pt; //
|
---|
120 | temp_pt = new NimData; //
|
---|
121 | temp_pt->VorigeZet_pt = LaatsteZet_pt; //Zetten onthouden
|
---|
122 | LaatsteZet_pt = temp_pt; //
|
---|
123 | LaatsteZet_pt->StapelNummer = StapelNummer; //
|
---|
124 | LaatsteZet_pt->AantalEraf = Aantal; //
|
---|
125 |
|
---|
126 | AantalZetten++; //Max Zetten bijhouden
|
---|
127 |
|
---|
128 | Stapels[StapelNummer] = Stapels[StapelNummer] - Aantal;
|
---|
129 | } //end NimSpel::NimSpel
|
---|
130 |
|
---|
131 |
|
---|
132 |
|
---|
133 | void NimSpel::ZetTerug(int AantalStappen) {
|
---|
134 | NimData * temp_pt;
|
---|
135 | for(int i = 0; i < AantalStappen; i++) {
|
---|
136 | temp_pt = LaatsteZet_pt;
|
---|
137 | Stapels[temp_pt->StapelNummer] = Stapels[temp_pt->StapelNummer] + temp_pt->AantalEraf;
|
---|
138 | AantalZetten--;
|
---|
139 | LaatsteZet_pt = temp_pt->VorigeZet_pt;
|
---|
140 | delete temp_pt;
|
---|
141 | } //end for
|
---|
142 | } //end NimSpel::ZetTerug
|
---|
143 |
|
---|
144 |
|
---|
145 |
|
---|
146 | void NimSpel::SpelerKiest( ){
|
---|
147 | int StapelNummer, Aantal, AantalStappen = 0;
|
---|
148 |
|
---|
149 | cout << "Maximaal terug te zetten zetten: " << AantalZetten << endl
|
---|
150 | << "'0' om niet terug te zetten" << endl
|
---|
151 | << "Aantal zetten: ";
|
---|
152 | AantalStappen = VoerInGetal(0, AantalZetten);
|
---|
153 |
|
---|
154 | if (AantalStappen == 0) {
|
---|
155 | do{
|
---|
156 | cout << "Speler aan de beurt" << endl;
|
---|
157 | cout << "Welke stapel [0-" << (MaxStapels - 1) << "] : ";
|
---|
158 | StapelNummer = VoerInGetal(0, MaxStapels - 1);
|
---|
159 | cout << "Hoeveel [1-2] : ";
|
---|
160 | Aantal = VoerInGetal(1, 2);
|
---|
161 | if (Stapels[StapelNummer] - Aantal < 0){
|
---|
162 | cout << Stapels[StapelNummer] << endl;
|
---|
163 | cout << "Geen Geldige Combinatie, probeer opnieuw";
|
---|
164 | } //end if
|
---|
165 | } //end do
|
---|
166 | while(Stapels[StapelNummer] - Aantal < 0);
|
---|
167 | PakWeg(StapelNummer, Aantal);
|
---|
168 | }
|
---|
169 | else { //Ga AantalStappen terug zetten
|
---|
170 | ZetTerug(AantalStappen);
|
---|
171 | SpelerAanBeurt = SpelerAanBeurt - 1 + (AantalStappen%2); //ivm met onevenaantal terug zetten
|
---|
172 | }// end if
|
---|
173 | } //end NimSpel::SpelerKiest
|
---|
174 |
|
---|
175 |
|
---|
176 |
|
---|
177 | void NimSpel::ComputerNiveauSlim(int * StapelNummer, int * Aantal) {
|
---|
178 | double KansMax, KansMet1, KansMet2 = 0; //tempvariablen, voor het bepalen van de max
|
---|
179 | for(int i = 0; i < MaxStapels; i++) {
|
---|
180 | if (Stapels[i] > 0) {
|
---|
181 | KansMet1 = WinstArray[Stapels[i]-1][2] / WinstArray[Stapels[i]-2][0];
|
---|
182 | }
|
---|
183 | else {
|
---|
184 | KansMet1 = 0;
|
---|
185 | }//end if
|
---|
186 |
|
---|
187 | if (Stapels[i] > 1) {
|
---|
188 | KansMet2 = WinstArray[Stapels[i]-2][2] / WinstArray[Stapels[i]-2][0];
|
---|
189 | }
|
---|
190 | else {
|
---|
191 | KansMet2 = 0;
|
---|
192 | }//end if
|
---|
193 |
|
---|
194 | if(KansMet1 > KansMax) {
|
---|
195 | *Aantal = 1;
|
---|
196 | *StapelNummer = i;
|
---|
197 | KansMax = KansMet1;
|
---|
198 | }//end if
|
---|
199 |
|
---|
200 | if(KansMet2 > KansMax) {
|
---|
201 | *Aantal = 2;
|
---|
202 | *StapelNummer = i;
|
---|
203 | KansMax = KansMet2;
|
---|
204 | }//end if
|
---|
205 | }//end for
|
---|
206 | }// end NimSpel::ComputerNiveauSlim
|
---|
207 |
|
---|
208 |
|
---|
209 |
|
---|
210 | void NimSpel::ComputerKiest(int Niveau) {
|
---|
211 | int StapelNummer = 0; //Voor het geval alles op verliezen staat ;-)
|
---|
212 | int Aantal = 1; //
|
---|
213 | char wait; //loze char ivm met Wachten om ENTER invoer.
|
---|
214 |
|
---|
215 | cout << "Computer Kiest..." << endl;
|
---|
216 | switch (Niveau) {
|
---|
217 | case 1: //random keuze
|
---|
218 | do {
|
---|
219 | StapelNummer = RandomGetal(0, (MaxStapels-1));
|
---|
220 | Aantal = RandomGetal(1, 2);
|
---|
221 | } //end do
|
---|
222 | while(Stapels[StapelNummer] - Aantal < 0);
|
---|
223 | break;
|
---|
224 | case 2: //slimme keuze
|
---|
225 | ComputerNiveauSlim(&StapelNummer, &Aantal);
|
---|
226 | break;
|
---|
227 | default: //dedug keuze
|
---|
228 | StapelNummer = 0;
|
---|
229 | Aantal = 2;
|
---|
230 | break;
|
---|
231 | } //end switch
|
---|
232 |
|
---|
233 | cout << "Stapel: " << StapelNummer << endl;
|
---|
234 | cout << "Aantal: " << Aantal << endl;
|
---|
235 | cout << "Druk op ENTER...";
|
---|
236 | cin.clear();
|
---|
237 | cin.ignore(10000,'\n');
|
---|
238 | cin.get(wait);
|
---|
239 | PakWeg(StapelNummer, Aantal);
|
---|
240 | } //end NimSpel::Computerkiest
|
---|
241 |
|
---|
242 |
|
---|
243 |
|
---|
244 | void NimSpel::DrukAf( ){
|
---|
245 | system("clear"); //OS Dependent Line, for windows use 'system("cls");' instead.
|
---|
246 | cout << endl << " : ";
|
---|
247 | for(int i = 0; i < MaxStapels; i++) {
|
---|
248 | if (i < 10) {cout << " " << i << " | ";} else { cout << i << " | ";}
|
---|
249 | }//end for
|
---|
250 | for(int i = 1; i <= MaxAantal; i++) {
|
---|
251 | cout << endl;
|
---|
252 | if (i < 10) {cout << " " << i << " : ";} else { cout << i << " : ";}
|
---|
253 | for(int j = 0; j < MaxStapels; j++) {
|
---|
254 | if (i <= Stapels[j]) { cout << "XX | ";} else { cout << " | ";}
|
---|
255 | }//end for
|
---|
256 | }//end for
|
---|
257 | cout << endl << endl;
|
---|
258 | }//end NimSpelDrukAf
|
---|
259 |
|
---|
260 |
|
---|
261 |
|
---|
262 | bool NimSpel::SpelAfgelopen( ){
|
---|
263 | for(int i = 0; i < MaxStapels; i++) {
|
---|
264 | if (Stapels[i] > 0) { //als er nog ergens waardes aanwezig zijn
|
---|
265 | return (false);
|
---|
266 | }//end if
|
---|
267 | }//end if
|
---|
268 | return (true);
|
---|
269 | }//end NimSpelAfgelopen
|
---|
270 |
|
---|
271 |
|
---|
272 |
|
---|
273 | void NimSpel::NimSpelen( ){
|
---|
274 | int Niveau = 0; //
|
---|
275 | cout << endl //
|
---|
276 | << "Geef het niveau aan" << endl //
|
---|
277 | << "1) Random " << endl //Niveau bepalen
|
---|
278 | << "2) Winnend Spelen " << endl;//
|
---|
279 | Niveau =VoerInGetal(1,2); //
|
---|
280 |
|
---|
281 | while (not(SpelAfgelopen( ))) { //Zolang spel niet afgelopen
|
---|
282 | DrukAf( ); //Druk bord af
|
---|
283 | if (SpelerAanBeurt == 1) { //a1) Speler 1 aan de beurt
|
---|
284 | SpelerKiest( ); //a2) Speler Doorwerken, keuzes enz.
|
---|
285 | SpelerAanBeurt++; //a3) Computer aan de beurt
|
---|
286 | }
|
---|
287 | else if (SpelerAanBeurt == 2) { //b1) Computer aan de Beurt
|
---|
288 | ComputerKiest(Niveau); //b2) Computer op Niveau laten spelen
|
---|
289 | SpelerAanBeurt = 1; //b3) Speler aan de beurt
|
---|
290 | } //end if
|
---|
291 | } //end while
|
---|
292 | if (SpelerAanBeurt == 2) { //ivm met regels a3,b3
|
---|
293 | cout << "Voila uw heeft GEWONNEN" << endl;
|
---|
294 | }
|
---|
295 | else {
|
---|
296 | cout << "DE COMPUTER IS DE BESTE !!!" <<endl;
|
---|
297 | }//end if
|
---|
298 | } //end NimSpel::NimSpelen
|
---|
299 |
|
---|
300 |
|
---|
301 |
|
---|
302 | int main( ){
|
---|
303 | srand(time(0)); //elke keer andere random begin waarde
|
---|
304 | NimSpel Spel1; //nieuw spel
|
---|
305 | Spel1.NimSpelen(); //spelen
|
---|
306 | }// end main
|
---|
307 |
|
---|
308 |
|
---|