-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGame.cpp
187 lines (164 loc) · 4.32 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
#include <string>
#include <vector>
#include "Game.h"
using namespace std;
/**
* Construct a Tic Toe Game where one human user can play against the Computer's AI.
*
*/
Game::Game () {
size = 3;
initializeBoard();
}
/**
* Called from constructor and startNewGame().
*/
void Game::initializeBoard () {
board.clear();
for (int r = 0; r < size; r++) {
vector<char> row{'_', '_', '_'};
board.push_back(row);
}
}
/**
* Select the given move and toggle between X and O player.
* Precondition row and col are both 0, 1 or 2
*
* @param row The row the player moves to
* @param col The column the player moves to column
* @param testing Passed the value of true during testing
*/
void Game::humanMove (int row, int col) {
board[row][col] = 'O';
}
/**
* Let the computer player chose the last available square. This is a very weak strategy.
* Consider having the computer look for its own win and if not found, and look for a block.
* Currently a loop an available square, one that has not been selected using random row and column.
* A board[row][col] that equals '_' insteadof 'X' or 'O'
*/
Game::square Game::computerMove () {
Game::square result;
// initialize random seed:
srand (time(NULL));
int times = 0;
while(true) {
// generate a random integer 0, 1, or 2
int r = rand() % 3;
int c = rand() % 3;
times++;
if(board[r][c] == '_' ) {
result.row = r;
result.col = c;
board[r][c] = 'X';
break;
}
}
return result;
}
/**
* Provide a textual version of this tic tac toe board to help debug.
*
* @return The current state of this tic tac board showing 'X', 'O', or '_' in each square
*/
string Game::toString() {
string result;
for (int r = 0; r < size; r++) {
for (int c = 0; c < size; c++) {
result = result + board[r][c] + " ";
}
result += "\n";
}
return result;
}
/**
* Since we have access to the selections '_' or 'O' or 'X' in the 2D array,
* we need to know if the human player has clicked an already selected square
* @return The state of this one square.
*/
bool Game::squareAvailable(int row, int column) {
return board[row][column] == '_';
}
/**
* Let users know if a game ended in a tie
*
* @return True if the current state of this game is tied
*/
bool Game::tied () {
return maxMovesRemaining() == 0 && !didWin('X') &&
!didWin('O');
}
/**
* Let a strategy know how many moves can still be.
* I found I needed this when implementing a strategy and for testing.
* It's not really needed to build the game
*
* @return How many locations have not been taken.
*/
int Game::maxMovesRemaining () {
int result = 0;
for (int r = 0; r < size; r++) {
for (int c = 0; c < size; c++) {
if (board[r][c] == '_')
result++;
}
}
return result;
}
/**
* Let others know the game is not yet over
*/
bool Game::stillRunning () {
return !tied() and !didWin('X') and !didWin('O');
}
/**
* Decide if either of the two players have won.
*
* return True if the playerChar ('O' or 'X' for computer) wins
*/
bool Game::didWin (char playerChar) {
return wonByRow(playerChar) ||
wonByCol(playerChar) ||
wonByDiagonal(playerChar);
}
// Helper functions
bool Game::wonByRow (char playerChar) {
for (int r = 0; r < size; r++) {
int rowSum = 0;
for (int c = 0; c < size; c++)
if (board[r][c] == playerChar)
rowSum++;
if (rowSum == size)
return true;
}
return false;
}
bool Game::wonByCol (char playerChar) {
for (int c = 0; c < size; c++) {
int colSum = 0;
for (int r = 0; r < size; r++)
if (board[r][c] == playerChar)
colSum++;
if (colSum == size)
return true;
}
return false;
}
bool Game::wonByDiagonal (char playerChar) {
// Check Diagonal from upper left to lower right
int sum = 0;
for (int r = 0; r < size; r++)
if (board[r][r] == playerChar)
sum++;
if (sum == size)
return true;
// Check Diagonal from upper right to lower left
sum = 0;
for (int r = size - 1; r >= 0; r--)
if (board[size - r - 1][r] == playerChar)
sum++;
if (sum == size)
return true;
// No win on either diagonal
return false;
}