TIC-TAC-TOE Debugging

I need help debugging this code.

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
  #include <iostream>
#include <vector>
#include <iomanip>
#include <string>
using namespace std;

// Change these to match your letters
const char L = 'L';
const char U = 'U';

const int SIZE = 3;
// For testing we might change this to 5 or 7,our code should still work

const int MAXMOVES = SIZE*SIZE;
// The max number of moves is the size of the SIZE by SIZE grid

const int WID = 3;
// can help to align the board


int getNumber(string prompt, int range) {
	if (range > 1) {
		int num = 0;
		while ((num < 1) || (num >(range))) {
			cout << prompt << " (";
			for (int i = 0; i < range; ++i) {
				cout << (i + 1) << " ";
			}
			cout << "): ";
			cin >> num;
			if (cin.fail()) {
				cin.clear(); // unset failbit
				cin.ignore(numeric_limits<streamsize>::max(), '\n'); // skip bad input 
				cout << "Must be between 1 and " << SIZE << "." << endl;
			}
			cout << endl;
		}
		return num - 1;
	}
	else if (range == 1) {
		return 0;
	}
	return -1;
}

int getNum(string prompt) {
	int num = 0;
	bool done = false;
	while (!done) {
		cout << prompt << " ";
		if (cin >> num) {
			done = true;
		}
		if (cin.fail()) {
			cin.clear(); // unset failbit
			cin.ignore(numeric_limits<streamsize>::max(), '\n'); // skip bad input 
			cout << "Must be an integer." << endl;
		}
	}
	return num;
}

void doSeed() {
	int seedVal = -1;
	char inputSeed = 'n'; // asks user if they want to input the random seed

	cout << "Input Seed? (y/n) ";
	cin >> inputSeed;
	cout << endl;

	if (inputSeed == 'y') {
		seedVal = getNum("Seed: ");
	}

	// set seed for random numbers
	if (inputSeed != 'y' || seedVal < 0) {  // seed value must be positive,
											// so if you get a negative value, just use time
		srand(time(NULL));
	}
	else {
		srand(seedVal);
	}

	cin.clear(); // unset failbit
	cin.ignore(numeric_limits<streamsize>::max(), '\n'); // skip bad input 
}

/*
Function: userMove

Query the user for row and column for their move
Ask repeatedly/loop until they choose a location that is still empty
Mark the location with the user's symbol
Use the getNumber function to get the row and column values
exit loop

*/
void userMove(vector< vector<char> >& board) {  //remove for exam
	bool done = false;
	while (!done) {
		int i = getNumber("Which row? ", SIZE);
		int j = getNumber("Which column? ", SIZE);
		if (board.at(i).at(j) == '_') {
			done = true;
			board.at(i).at(j) = L;
		}
		else {
			cout << "(" << (i + 1) << ", " << (j + 1) << ") already taken." << endl;
		}
	}
}

/*
Write this function

Function: computerMove

Randomly create a row and column in the range of the board
Repeat/loop until a location is found that is still empty
Mark the location with the computer's symbol
exit loop
*/
void computerMove(vector< vector<char> >board) { 
	bool done = false;
	while (!done) {
		int i = rand() % 3;
		int j = rand() % 3;

		if (board.at(i).at(j) == 'L' || board.at(i).at(j) == 'U') {
			done = false;
		}
		else {
			board.at(i).at(j) = 'L';
		}
	}
	
}



/*
Write this function

Function: printBoard

outputs the content of the board in a SIZE by SIZE grid

_  _  X
O  _  X
_  O  _

*/

void printBoard(vector<vector<char>>& board) {
	for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			cout << " " << board.at(i).at(j);
			;
		}
		cout << endl;
	}
	cout << endl;
}

/*
Write this function

Function checkRow

Check to see if the character passed in is the
character all the way across a row.
If it is a win, return true
otherwise, return false

*/
bool checkRow(vector< vector<int> >& board, vector<int> called) {
	bool rowWon = false;  
	int i = 0;
	
	while (!rowWon && i < SIZE) {
		rowWon = true; 
		int j = 0;
		while (rowWon && j < SIZE) {
			if (called.at(board.at(i).at(j) - 1) == 0) { 
				rowWon = false; 
			}
			++j;
		}
		++i;
	}
	return rowWon;
}

/*
Write this function

Function checkColumn

Check to see if the character passed in is the
character all the way down a column.
If it is a win, return true
otherwise, return false
*/
bool checkCol(vector< vector<int> >& board, vector<int> called) {
	bool colWon = false;
	int j = 0;

	while (!colWon && j < SIZE) {
		colWon = true;
		int i = 0;
		while (colWon && i < SIZE) {
			if (called.at(board.at(i).at(j) - 1) == 0) {
				colWon = false;
				++i;
			}
			++j;
		}
		return colWon;
	}
}
/*
Write this function

Function checkDiag

Check to see if the character passed in is the
character all the way across a diagonal.
The diagonals are from top-left to bottom-right,
and from bottom-left to top-right.
If it is a win, return true
otherwise, return false
*/
bool checkDiag(vector< vector<int> >& board, vector<int> called) {
	// check diagonal top-left to bottom-right
	int i = 0;  // i is both the row AND the column
	bool diagWon = true;
	while (diagWon && i < SIZE) {
		if (called.at(board.at(i).at(i) - 1) == 0) {
			diagWon = false;
		}
		++i;
	}
	if (diagWon) { // no need to check further if won
		return diagWon;
	}

	// check diagonal bottom-left to top-right
	i = 0;  // row is i, column is last index minus i
	diagWon = true;
	while (diagWon && i < SIZE) {
		if (called.at(board.at(i).at(SIZE - 1 - i) - 1) == 0) {
			// checks 0,4; 1,3; 2,2; 3,1; 4,0 
			diagWon = false;
		}
		++i;
	}
	return diagWon;
}

bool checkWin(vector< vector<char> >& board, vector<int> called) {
	return checkRow(board, called) || checkCol(board, called) || checkDiag(board, called);
}

bool checkCat(int moves) { // i.e. a tie, no more moves to make
	if (moves == MAXMOVES) {
		return true;
	}
	return false; 
}

char getWinner(vector< vector<char> >& board, int moves) {
	if (checkWin(board, L)) {   // see if user wins
		return L;  
	}
	if (checkWin(board, U)) { // see if computer wins
		return U;
	}
	// if no winner yet... check and see if it is a tie game / cat
	if (checkCat(moves)) {
		return 'c';
	}
	// Neither player is a winner and not a tie game so return the blank 
	//   location symbol '_'
	return '_';
}

int main() {
	char playAgain = 'y';
	while (playAgain == 'y') {
		doSeed();
		vector< vector<char> > board(SIZE, vector<char>(SIZE, '_'));
		// initializes the vector with '_' (underscore)
		//  this allows to blank locations to be visible
		cout << "Welcome to Tic Tac Toe" << endl << endl;
		printBoard(board);
		
		// use a char instead of a boolean
		//  when a winner is found, their symbol will be used to indicate
		//  not only that there is a winner, but who won
		char winner = '_';
		// no winner until assigned with appropriate symbol for user or computer
		int moves = 0;
		// we have to count moves so we don't get stuck once we run out
		//    , i.e. fill up the board
		//  if we look for a move when there isn't one, we will end up
		//  in an infinite loop
		while (winner == '_') { // repeat/loop until there is a winner 
                            //  or cat (i.e. a tie)

			if (moves < MAXMOVES) { // only let the user fill a square if there is
                              //   still one empty
				userMove(board);
				moves++;
			}

			if (moves < MAXMOVES) { // only let the computer fill a square if there is
                              //   still one empty
				computerMove(board);
				moves++;
			}

			printBoard(board);

			winner = getWinner(board, moves);
			// set to the winner's symbol or 'c' if cat (i.e. a tie)

		}
		// once we get here a winner was found so
		if (winner == 'c') { // tie
			cout << "CAT!" << endl;
		}
		else { // winner
			cout << winner << " Won!!!" << endl;
		}
		cout << endl << "Play again? (y/n) ";
		cin >> playAgain;
		cin.clear(); // unset failbit
		cin.ignore(numeric_limits<streamsize>::max(), '\n'); // skip bad input 
		playAgain = tolower(playAgain);
	}
	system("pause");
}      
I need help debugging this code.

You might start by telling us whatever it is that makes you believe it needs debugging.
Topic archived. No new replies allowed.