-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGame.cpp
414 lines (397 loc) · 16.3 KB
/
Game.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
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
#include "Game.h"
#include <iostream>
#include <string>
using namespace std;
Game::Game(Player p1, Player p2){//constructor for new game
board = new Board;
p1ptr = new Player(p1.getName());
p2ptr = new Player(p2.getName());
currentPlayer = p1ptr;
waitingPlayer = p2ptr;
p1ptr->setColor('B');
p2ptr->setColor('W');
}
Game::Game(Player p1, Player p2, int current) {//constructor for loading from a save
board = new Board;
p1ptr = new Player(p1.getName());
int p1s = p1.getScore(), p2s = p2.getScore();
p1ptr->setScore(p1s);
p2ptr = new Player(p2.getName());
p2ptr->setScore(p2s);
currentPlayer = (current==1)? p1ptr : p2ptr;
waitingPlayer = (current==1)? p2ptr : p1ptr;
p1ptr->setColor('B');
p2ptr->setColor('W');
}
Board* Game::getBoard() {
return board;
}
Game* Game::start() {
string p1n, p2n; // input strings for player names
cout << "Please enter player 1's name" << endl;
cin >> p1n;
cout << "Please enter player 2's name" << endl;
cin >> p2n;
Player p1(p1n); // create players
Player p2(p2n);
char answer;
int answer2, error = 0, error2 = 0;
cout << "\nWould you like to start a game with the standard positions or with non-standard positions? (y/n)\n";
do {//check for incorrect input
cin >> answer;
if (answer != 'y' && answer != 'n'){
cout << "\nIncorrect input! This must be 'y' or 'n'. Please try again.\n";
}
else {
error++;
}
} while (error == 0);
string fileName;
switch (answer){
case 'y':{
cout << endl << "Staring game with standard initial positions" << endl;
fileName = "Regular.txt";
break;
}
case 'n':{
cout << endl << "Which of the non-standard positions would you like? Choose from 1-4." << endl;
do{
cin >> answer2;
if (answer2 != 1 && answer2 != 2 && answer2 != 3 && answer2 != 4){
cout << "\nIncorrect input! This must be a number between 1 and 4.\n";
}
else{
error2++;
}
} while (error2 == 0);
fileName = "NS-";
fileName += to_string(answer2);
fileName += ".txt";
cout << endl << "Staring game with non-standard position set " << answer2 << "." << endl;
break;
}
default: {
cout << "\nCongrats! I don't know how you broke it this bad.\n";
}
}
Game* current = new Game(p1, p2); // construct new game with players
string gameSave; // create string to save savegame file data
fstream inFile; // create savegame fstream object
inFile.open(fileName.c_str());
getline(inFile, gameSave); // get data from savegame file
current->board->loadFromSave(current->board, gameSave); // load save data to game board
inFile.close(); // close savegame file
return current;
}
Game* Game::load() {
string saveName; // create string to find savegame file
cout << "Enter savegame number" << endl;
cin >> saveName; // determine desired save file
saveName += ".txt";
string gameSave, p1n, p2n, temp, current;
int p1s=0, p2s=0, i=0;
fstream inFile; // create fstream object
inFile.open(saveName, ios::in); // open savegame file
Game* game = nullptr;
while(getline(inFile, gameSave)){
switch (i){
case 0: {//get save file info for player 1
int z = 0;
temp = "";
while (gameSave[z] != ' ') {
p1n += gameSave[z];
z++;
}
z = gameSave.length();
while (gameSave[z-1] != ' ') {
temp += gameSave[z-1];
z--;
}
p1s = stoi(temp);
break;
}
case 1: {//get save file info for player 2
int z = 0;
temp = "";
while (gameSave[z] != ' ') {
p2n += gameSave[z];
z++;
}
z = gameSave.length();
while (gameSave[z-1] != ' ') {
temp += gameSave[z-1];
z--;
}
p2s = stoi(temp);
break;
}
case 2:{//determine current player from save file
current = gameSave;
break;
}
case 3:{//construct the players and the game from the info from the save file
Player p1(p1n, p1s);
Player p2(p2n, p2s);
int currentInt = stoi(current);
game = new Game(p1, p2, currentInt);
game->getBoard()->loadFromSave(game->getBoard(),gameSave);
break;
}
default:{
cout << "\nCongrats! I don't know how you broke it this bad. Please check the savegame file you entered to ensure everything is right.\n";
}
}
i++;
}
inFile.close(); // close savegame file
return game;
}
Player* Game::getCurrentPlayer() {
return currentPlayer;
}
void Game::switchPlayer() {
Player* temp = currentPlayer; // save current player temporarily
currentPlayer = waitingPlayer; // set other player as current
waitingPlayer = temp; // set current as waiting
}
void Game::TakeTurn(Game* gamePoint) {
Board *temp = new Board; // create temp board
gamePoint->getBoard()->copyBoard(temp);
int playable, ctr = 0;
playable = gamePoint->getBoard()->playables(temp,
gamePoint->getCurrentPlayer()); // manipulate temp to return a board with playable positions shown
if (playable != 0) { // check if player has moves, switch players if not.
temp->DrawBoard(temp); // draw the temp board
char colStr;
int line, colInt = -1;
string flips;
do {//checking correct inputs
cout << "Please enter the position you would like to play (example: a 1):" << endl;
cin >> colStr; // take position inputs from the player
cin >> line;
switch (colStr) { // translate string input to coordinate number
case 'a': {
colInt = 0;
break;
}
case 'b': {
colInt = 1;
break;
}
case 'c': {
colInt = 2;
break;
}
case 'd': {
colInt = 3;
break;
}
case 'e': {
colInt = 4;
break;
}
case 'f': {
colInt = 5;
break;
}
case 'g': {
colInt = 6;
break;
}
case 'h': {
colInt = 7;
break;
}
default: {
cout << "\nIncorrect column input! Column must be a letter between a-h. Please try again.\n";
}
}
if ((0 <= colInt) && (colInt <= 7) && (1 <= line) && (line <= 8)) {
ctr++;
} else {
cout << "\nIncorrect line input! Line must be a number between 1-8. Please try again.\n";
}
} while (ctr == 0);
line--;
if (temp->BoardArray[line][colInt].getPiece() == '*') { // check if the position is playable
gamePoint->getBoard()->BoardArray[line][colInt].setPiece(
gamePoint->currentPlayer->getColor()); // play position
flips = temp->checkerFlips(colInt, line, temp,
gamePoint->currentPlayer); // take position coordinates for flipping
if (flips.length() != 0) { // check if checker returned flipping positions
/* The flipper returns a string of coordinates, with each pair being a coordinate (i.e. in 2734,
* the coordinates are [2][7] and [3][4]). These coordinates are the pieces that are at the edge
* of the line that will be flipped by the move. The for loop below looks for the first two numbers,
* turns them to ints and uses these ints to find the board position. Then it calculates the
* relative position of the coordinate returned to the coordinate that was played. It then uses
* the result to find which pieces are to be flipped as a result of the move.
*/
for (int k = 0; k < flips.length(); k += 2) {//take positions from checker and flip
string strc(1, flips[k]); // take positions,
int c = stoi(strc); // and turn to ints.
string strl(1, flips[k + 1]);
int l = stoi(strl);
if (abs(colInt - c) == 0 && abs(line - l) != 0) {
/* the above statement checks if the returned coordinate is on the same column as the played piece.
* If it is, then the appropriate pieces on the line are flipped.*/
if (l > line) { // check which coordinate is bigger
for (int i = line + 1; i < l; i++) {
gamePoint->getBoard()->BoardArray[i][colInt].setPiece(currentPlayer->getColor());
}
} else if (line > l) {
for (int i = l + 1; i < line; i++) {
gamePoint->getBoard()->BoardArray[i][colInt].setPiece(currentPlayer->getColor());
}
}
} else if (abs(colInt - c) != 0 && abs(line - l) == 0) {
/* the above statement checks if the returned coordinate is on the same line as the played piece.
* If it is, then the appropriate pieces on the line are flipped.*/
if (colInt > c) {
for (int i = c + 1; i <= colInt; i++) {
gamePoint->getBoard()->BoardArray[line][i].setPiece(currentPlayer->getColor());
}
} else if (c > colInt) {
for (int i = colInt + 1; i <= c; i++) {
gamePoint->getBoard()->BoardArray[line][i].setPiece(currentPlayer->getColor());
}
}
} else if (abs(colInt - c) != 0 && abs(line - l) != 0) {
/* If neither the same column nor line, then the piece is on the diagonal.
* The statements below flips the diagonal*/
if (l > line) {
if (colInt > c) {
for (int i = line + 1, j = c + 1; i < l && j < colInt; i++, j++) {
gamePoint->getBoard()->BoardArray[i][j].setPiece(currentPlayer->getColor());
}
} else if (c > colInt) {
for (int i = line + 1, j = colInt + 1; i < l && j < c; i++, j++) {
gamePoint->getBoard()->BoardArray[i][j].setPiece(currentPlayer->getColor());
}
}
} else if (line > l) {
if (colInt > c) {
for (int i = l + 1, j = c + 1; i < line && j < colInt; i++, j++) {
gamePoint->getBoard()->BoardArray[i][j].setPiece(currentPlayer->getColor());
}
} else if (c > colInt) {
for (int i = l + 1, j = colInt + 1; i < line && j < c; i++, j++) {
gamePoint->getBoard()->BoardArray[i][j].setPiece(currentPlayer->getColor());
}
}
}
}
}
}
}
gamePoint->getBoard()->DrawBoard(); // the board is drawn again to show the board state after the move
gamePoint->currentPlayer->setScore(
gamePoint->getBoard()->countPoints(gamePoint->getBoard(), gamePoint->currentPlayer));
gamePoint->waitingPlayer->setScore(
gamePoint->getBoard()->countPoints(gamePoint->getBoard(), gamePoint->waitingPlayer));
cout << endl << "Your turn is over." << endl;
gamePoint->switchPlayer();
delete temp;
} else { // if player doesn't have a move, turn is over
delete temp; // the temp board is deleted
int *temp2 = gamePoint->getEndGamePtr(); // increments counter under the game object that determines when a game is over
*temp2 = 1 + *temp2;
int choice, error = 0;
cout << endl << "No valid moves! Please choose one of the following options. (1,2,3)\n\n1. End turn\n\n2. End game\n\n3. Save game" << endl;
cin >> choice;
do {
switch (choice) {
case 1: {
gamePoint->switchPlayer(); // the players are switched
gamePoint->play(gamePoint);
error++;
break;
}
case 2: {
int *eGP;
eGP = gamePoint->getEndGamePtr();
*eGP += 1;
error++;
break;
}
case 3: {
save(gamePoint);
break;
}
default:{
cout << "\nIncorrect input! Please enter a number between 1 and 3." << endl;
}
}
} while (error == 0);
}
}
void Game::play(Game* gamePoint) {
int choice, error=0;
cout << "Player " << gamePoint->getCurrentPlayer()->getName() << "'s turn.\n" <<"\nWhat would you like to do? (1,2,3)\n\n1. Make a move\n\n2. End game\n\n3. Save game" << endl;
cin >> choice;
do{
switch (choice) {
case 1:{
gamePoint->TakeTurn(gamePoint);
error++;
break;
}
case 2:{
int* tempPtr;
tempPtr = gamePoint->getEndGamePtr();
*tempPtr = 3;
error++;
break;
}
case 3:{
save(gamePoint);
error++;
break;
}
default: {
cout << "\nIncorrect input! Please enter a number between 1 and 3." << endl;
}
}
} while(error == 0);
}
void Game::save(Game *gamePoint) {
string counterStr;
int counter;
ifstream saveGameCounter;
saveGameCounter.open("saveGameCounter.txt", ios::in);
getline(saveGameCounter, counterStr);
counter = stoi(counterStr);
saveGameCounter.close();
remove("saveGameCounter.txt");
counter++;
ofstream newSaveGameCounter;
newSaveGameCounter.open("saveGameCounter.txt", ios::out);
newSaveGameCounter << counter;
newSaveGameCounter.close();
counterStr += ".txt";
ofstream outFile;
outFile.open(counterStr, ios::out);
string p1data = gamePoint->getPlayer1Ptr()->getName() + " " + to_string(gamePoint->getPlayer1Ptr()->getScore()) + "\n";
string p2data = gamePoint->getPlayer2Ptr()->getName() + " " + to_string(gamePoint->getPlayer2Ptr()->getScore()) + "\n";
string currentPlayerData;
if (gamePoint->currentPlayer == gamePoint->getPlayer1Ptr()){
currentPlayerData = "1\n";
}
else if (gamePoint->currentPlayer == gamePoint->getPlayer2Ptr()){
currentPlayerData = "2\n";
}
string boardData = gamePoint->getBoard()->getBoardData(gamePoint->getBoard());
outFile << p1data;
outFile << p2data;
outFile << currentPlayerData;
outFile << boardData;
outFile.close();
}
Player* Game::getPlayer1Ptr() {
return p1ptr;
}
Player* Game::getPlayer2Ptr() {
return p2ptr;
}
int* Game::getEndGamePtr(){
return endGamePtr;
}