forked from RivkaSchuss/ReversiGame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AbstractGameLogic.cpp
329 lines (303 loc) · 9.19 KB
/
AbstractGameLogic.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
//
// Created by yarin on 06/11/17.
//
#include <iostream>
#include <limits>
#include "AbstractGameLogic.h"
using namespace std;
/**
* Constructor.
* This method build a new object of this kind.
*/
AbstractGameLogic::AbstractGameLogic() : turn(black), running(2) {}
/**
* Destructor.
* This method deletes an object of this kind.
*/
AbstractGameLogic::~AbstractGameLogic() {
}
/**
* This method sets a turn.
* Happens for example when no moves are possible for the player.
* @param currentTurn the new player to play.
*/
void AbstractGameLogic::setTurn(Type currentTurn) {
this->turn = currentTurn;
}
/**
* This method is in charge of the flow of the turn.
* @param board the board of the game.
*/
void AbstractGameLogic::playOneTurn(Board* board) {
int row, col, l = 0;
bool moveCompleted = false;
while (!moveCompleted) {
l = 0;
Location *moves;
moves = getPossibleMoves(board->getTable(), board->getSize());
if (moves == NULL) {
running -= 1;
if (turn == black) {
cout << "X: You have no possible moves!" << endl;
return;
} else {
cout << "O: You have no possible moves!" << endl;
return;
}
}
running = 2;
if (turn == black) {
cout << "X: It's your move." << endl;
} else {
cout << "O: It's your move." << endl;
}
cout << "Your possible moves: ";
while (moves[l].getRow() != 0) {
cout << "(" << moves[l].getRow() << "," << moves[l].getCol() << ") ";
l++;
}
cout << endl;
cout << "Please enter your move row,col:" << endl;
cin >> row >> col;
//validating the input.
while (!cin) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Input isn't valid. Please enter your move row,col:" << endl;
cin >> row >> col;
}
l = 0;
while (moves[l].getRow() != 0) {
if (row == moves[l].getRow() && col == moves[l].getCol()) {
board->getTable()[row][col].updateStatus(this->turn + 1);
flipDeadCell(row,col,board);
moveCompleted = true;
}
l++;
}
if (!moveCompleted) {
cout << "This isn't an option" << endl;
board->print();
}
}
}
/**
* This method returns if the game isn't over yet.
* @return this method returns whether the game ends.
*/
bool AbstractGameLogic::isRunning() {
return this->running;
}
/**
* This method returns the current turn.
* @return the current turn.
*/
Type AbstractGameLogic::getTurn() {
return this->turn;
}
/**
* This method checks the score at the end of the game.
* @param table the table of the board.
* @param size the size of the table.
* @return the player who won.
*/
int AbstractGameLogic::checkScore(Cell **table, int size) {
int counterBlack = 0, counterWhite = 0;
for (int i = 0; i <= size; ++i) {
for (int j = 0; j <= size; ++j) {
if (table[i][j].getStatus() == 1) {
counterBlack++;
} else if (table[i][j].getStatus() == 2){
counterWhite++;
}
}
}
if (counterBlack > counterWhite) {
return 1;
} else if (counterWhite > counterBlack) {
return 2;
}
return 0;
}
/**
* This method is in charge of getting the possible moves.
* This method check all of the possibilities for the next move
* and saves it. If there are no possible moves it returns NULL.
* @param table the table of the board.
* @param size the size of the board.
* @return the possible moves for this player.
*/
Location* AbstractGameLogic::getPossibleMoves(Cell** table, int size) {
//changed dynamically to be the options for the current
// player's cell in the for loop.
Location* subOptions;
//ultimately will store all of the options for moves.
Location* options = new Location(2, 2);
int k = 0, l = 0;
for (int i = 0; i <= size; ++i) {
for (int j = 0; j <= size; ++j) {
if (table[i][j].getStatus() == turn + 1) {
subOptions = this->clearMoveArea(table, size, i, j, 0);
if (subOptions != NULL) {
l = 0;
while (subOptions[l].getRow() != 0) {
if (!moveExist(options, subOptions[l], k)) {
options[k] = subOptions[l];
k++;
}
l++;
}
}
}
}
}
//if there are no possible moves we'll return NULL.
if (k == 0) {
delete options;
return NULL;
} else {
Location* option = new Location(0, 0);
options[k] = *option;
delete option;
return options;
}
}
/**
* This method flips a dead cell.
* @param row the row of the new own cell.
* @param col the col of the new own cell.
* @param board the board of the game.
*/
void AbstractGameLogic::flipDeadCell(int row, int col, Board* board) {
Location* killerOptions;
killerOptions = clearMoveArea(board->getTable(), board->getSize(),
row, col, turn + 1);
if (killerOptions == NULL) {
return;
} else {
int l = 0;
int rowDif = 0, colDif = 0;
Location *flipped;
while (killerOptions[l].getRow() != NULL) {
rowDif = row - killerOptions[l].getRow();
colDif = col - killerOptions[l].getCol();
Place place = whichPlace(rowDif, colDif);
flipped = removeOneDead(place, row, col, board);
flipDeadCell(flipped->getRow(), flipped->getCol(), board);
l++;
delete flipped;
}
}
}
/**
* This method the direction of which the flip happens.
* @param rowDif row of the new cell.
* @param colDif col of the new cell.
* @return returns the direction of the move.
*/
Place AbstractGameLogic::whichPlace(int rowDif, int colDif) {
if (rowDif > 0) {
if (colDif > 0) {
return upLeft;
} else if (colDif == 0) {
return up;
} else if (colDif < 0) {
return upRight;
}
} else if (rowDif == 0) {
if (colDif > 0) {
return west;
} else if (colDif < 0) {
return east;
}
} else if (rowDif < 0) {
if (colDif > 0) {
return downLeft;
} else if (colDif == 0) {
return down;
} else if (colDif < 0) {
return downRight;
}
}
}
/**
* This method flips the dead cell.
* @param place the direction of the move.
* @param row the row of the new cell.
* @param col the col of the new cell.
* @param board the board of the game.
* @return the new flipped cell.
*/
Location* AbstractGameLogic::removeOneDead(Place place, int row, int col, Board* board) {
int rowDead = 0, colDead = 0;
switch(place) {
case up:
rowDead = row - 1;
colDead = col;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case upRight:
rowDead = row - 1;
colDead = col + 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case east:
rowDead = row;
colDead = col + 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case downRight:
rowDead = row + 1;
colDead = col + 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case down:
rowDead = row + 1;
colDead = col;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case downLeft:
rowDead = row + 1;
colDead = col - 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case west:
rowDead = row;
colDead = col - 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
case upLeft:
rowDead = row - 1;
colDead = col - 1;
board->getTable()[rowDead][colDead].
updateStatus(turn + 1);
break;
}
Location* location = new Location(rowDead, colDead);
return location;
}
/**
* This method checks if the possibility is already exists.
* @param options the current list of possible moves.
* @param location the new possibility to be added.
* @param k the number of possibilities for now.
* @return wetheer the move is already exists.
*/
bool AbstractGameLogic::moveExist(Location *options, Location location, int k) {
int l = 0;
while (l <= k) {
if (options[l].getRow() == location.getRow() &&
options[l].getCol() == location.getCol()) {
return true;
}
l++;
}
return false;
}