What's wrong with my code? Tic Tac Toe

//
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
 Tic Tac Toe.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

// global constants
const char X = 'X';
const char O = 'O';
const char EMPTY = ' ';
const char TIE = 'T';
const char NO_ONE = 'N';

// function prototypes
void instructions();
char askYesNo(string question);
int askNumber(string question, int high, int low = 0);
char humanPiece();
char opponent(char piece);
void displayBoard(const vector<char>& board);
char winner(const vector<char>& board);
bool isLegal(const vector<char>& board, char human);
int computerMove(vector<char> board, char computer);
void announceWinner(char winner, char computer, char human);

// main function

int _tmain(int argc, _TCHAR* argv[])
{
	int move;
	const int NUM_SQUARES = 9;
	vector<char> board(NUM_SQUARES, EMPTY);

	instructions();
	char human = humanPiece();
	char computer = opponent(human);
	char turn = X;
	displayBoard(board);

	while (winner(board) == NO_ONE)
	{
		if (turn == human)
		{
			move = humanMove(board, human);
			board[move] = human;
		}
		else
		{
			move = computerMove(board, computer);
			board[move] = computer;
		}
		displayBoard(board);
		turn = opponent(turn);
	}

	announceWinner(winner(board), computer, human);

	return 0;
}

void instructions()
{
	cout << "Welcome to the ultimate man-machine showdown: Tic-Tac-Toe.\n";
	cout << "--where human brain is pit against silicon processor\n\n";

	cout << "Make your move known by entering a number, 0 - 8.  The number\n";
	cout << "corresponds to the desired board position, as illustrated:\n\n";

	cout << "		0 | 1 | 2\n";
	cout << "		-----\n";
	cout << "		3 | 4 | 5\n";
	cout << "		-----\n";
	cout << "		6 | 7 | 8\n\n";

	cout << "Prepare yourself, human.  The battle is about to begin.\n\n";
}

char askYesNo(string question)
{
	char response;
	do
	{
		cout << question << " (y/n): ";
		cin >> response;
	}
	while (response != 'y' && response != 'n');

	return response;
}

int askNumber(string question, int high, int low)
{
	int number;
	do
	{
		cout << question << " (" << low << " - " << high << "): ";
		cin >> number;
	}
	while (number > high || number < low);

	return number;
}

char humanPiece()
{
	char go_first = askYesNo("Do you require the first move?");
	if (go_first == 'y')
	{
		cout << "\nThen take the first move.  You will need it\n";
		return X;
	}
	else
	{
		cout << "\nYour bravery will be your undoing...  I will go first.\n";
		return 0;
	}
}

char opponent(char piece)
{
	if (piece == X)
		return O;
	else
		return X;
}

void displayBoard(const vector<char>& board)
{
	cout << "\n\t" << board[0] " | " << board[1] << " | " << board[2];
	cout << "\n\t" << "----";
	cout << "\n\t" << board[3] << " | " << board[4] << " | " << board[5];
	cout << "\n\t" << "----";
	cout << "\n\t" << board[6] << " | " << board[7] << " | " << board[8];
	cout << "\n\t";
}

char winner(const vector<char>& board)
{
	// all possible winning rows
	const int WINNING_ROWS[8][3] = { {0, 1, 2},
										{3, 4, 5},
										{6, 7, 8},
										{0, 3, 6},
										{1, 4, 7},
										{2, 5, 8},
										{0, 4, 8},
										{2, 4, 6} };
	const int TOTAL_ROWS = 8;

	// if any winning row as three values that are the same (and NOT EMPTY),
	// then we have a winner
	for(int row = 0; row < TOTAL_ROWS; ++row)
	{
		if ( (board[WINNING_ROWS[row][0]] != EMPTY) &&
			 (board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) &&
			 (board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]) )
		{
			return board[WINNING_ROWS[row][0]];
		}

	// since nobody has won, check for a tie (no empty squares left)
	if (count(board.begin(), board.end(), EMPTY) == 0)
		return TIE;

	// since nobody has won and it isn't a tie, the game ain't over
	return NO_ONE;
}

inline bool isLegal(int move, const vector<char>& board)
{
	return (board[move] == EMPTY);
}

int humanMove(const vector<char>& board, char human)
{
	int move = askNumber("Where will you move?", (board.size() - 1));
	while (!isLegal(move, board))
	{
		cout << "\nThat sqaure is already occupied, foolish human.\n";
		move = askNumber("Where will you move?", (board.size() - 1));
	}
	cout << "Fine...\n";
	return move;
}

int computerMove(vector<char> board, char computer)
{
	cout << "I shall take square number ";

	// if computer can win on next move, make that move
	for(int move = 0; move < board.size(); ++move)
	{
		if (isLegal(move, board))
		{
			board[move] = computer;
			if (winner(board) == computer)
			{
				cout << move << endl;
				return move;
			}
			// done checking this move, undo it
			board[move] = EMPTY;
		}
	}

	// if human can win on next move, block that move
	char human = opponent(computer);
	for(int move = 0; move < board.size(); ++move)
	{
		if (isLegal(move, board))
		{
			board[move] = human;
			if (winner(board) == human)
			{
				cout << move << endl;
				return move;
			}
			// done checking this move, undo it
			board[move] = EMPTY;
		}
	}

	// the bestmoves to make, in order
	const int BEST_MOVES[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
	// since no one can win on next move, pick best open square
	for(int i = 0; i < board.size(); ++i)
	{
		int move = BEST_MOVES[i];
		if (isLegal(move, board))
		{
			cout << move << endl;
			return move;
		}
	}
}

void announceWinner(char winner, char computer, char human)
{
	if (winner == computer)
	{
		cout << winner << "'s won!\n";
		cout << "As I predicted, human, I am trimphunt once more -- proof\n";
		cout << "that computers are superior to humans in all regards.\n";
	}
	else if (winner == human)
	{
		cout << winner << "'s won!\n";
		cout << "No, no!  It cannot be!  Somehow you tricked me, human.\n";
		cout << "But never gain!  I, the computer, so swear it!\n";
	}
	else
	{
		cout << "It's a tie.\n";
		cout << "You were most lucky, human, and somehow manage to tie me.\n";
		cout << "Celebrate...  for this is the best you will ever achieve.\n";
	}
}


Can anyone find anything wrong with it? I've checked through it several times and it just won't compile :(.
From a quick read through. You have no function prototype of:
int humanMove(const vector<char>& board, char human);

Line 134:
cout << "\n\t" << board[0] " | " << board[1] << " | " << board[2];

Should be:
cout << "\n\t" << board[0] << " | " << board[1] << " | " << board[2];

Line 161:
(board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]) )

Should be:
(board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]]) )

The for-loop on line 157 is missing a matching brace } on line 165.
Last edited on
Thanks man, it works. I keep seeing those instances of [move] all of the time, but I have no idea what they do. Could you or someone please explain to me what it does? Thank you.

Another query as well:
void displayBoard(const vector<char>& board)
1
2
3
4
5
6
7
8
{
	cout << "\n\t" << board[0] " | " << board[1] << " | " << board[2];
	cout << "\n\t" << "----";
	cout << "\n\t" << board[3] << " | " << board[4] << " | " << board[5];
	cout << "\n\t" << "----";
	cout << "\n\t" << board[6] << " | " << board[7] << " | " << board[8];
	cout << "\n\t";
}


How does the board's in there get the noughts and crosses?
Last edited on
No problem. But I'm guessing this isn't your code?!

And the board from the above code, is populated by the vector, board[ 0 ] etc.
Heh, nah this isn't my code. It's Michael Dawson's code from the "Beginners Guide to C++ Game Programming". Been programming with C++ for about 3 months now though so I'm getting the hang of understanding things, just buying loads of books and getting the hang of it.

What about [move]? :).

Oh and:
move = askNumber("Where will you move?", (board.size() - 1));

(board.size() - 1));

What does the -1 do in this?

Last edited on
board[move] is accessing the board, with the index of move.

move being an index number.

And from a quick read through. I'm guessing that board.size() - 1 is so that you don't 'run off' you allocated memory.

When you declare an array etc. myArray[ 5 ];, you use the array as n-1

This is because an array starts from 0. So 0 - 4 would be 5 indices! (n-1), n being the number for the array creation.
Last edited on
Thank you!
Right one more question:
1
2
3
4
5
6
		if ( (board[WINNING_ROWS[row][0]] != EMPTY) &&
			 (board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) &&
			 (board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]) )
		{
			return board[WINNING_ROWS[row][0]];
		}


See that
return board[WINNING_ROWS[row][0]];

Is that basically else?
No.

The if statement checks to see if the board is empty. If it's not, it checks to see if all 3 indices are the same. If they are the same, it will return a character of the winning symbol. 'X' or 'O'.

return = exit the current function and return a char.

This is used to exit the while loop on line 45. Which will end the game.
Last edited on
I don't suppose you could narrow it down a bit more? :-).
I think that's about as narrow as it gets... lol.

uhm. returning something from a function is the same as assignment.

i.e.
char winningChar = winner( board );

What ever is returned from the function winner( board ) will be saved in the variable winningChar
I think the thing I'm getting confused at is what exactly is returned from return board[WINNING_ROWS[row][0]]; and when does it actually happen.

It only returns at that point if there's a winning line.

Winning lines are these combinations:
1
2
3
4
5
6
7
8
const int WINNING_ROWS[8][3] = { {0, 1, 2},
				{3, 4, 5},
				{6, 7, 8},
				{0, 3, 6},
				{1, 4, 7},
				{2, 5, 8},
				{0, 4, 8},
				{2, 4, 6} };


if ( (board[WINNING_ROWS[row][0]] != EMPTY) ...
So, if it's not empty, a space( ' ' ), then it has to be either an 'X' or 'O'.

So, lets take this winning line:
{0, 1, 2}

Say 0, 1 and 2 contain an 'X'.

1
2
(board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) &&
(board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]) )

If 0 is not empty, which it's not, it has an 'X' in.
AND 0 is the same as 1,
AND 1 is the same as 2 ( Meaning, 0, 1 and 2 contain the same! )
THEN, return 'X', which is the contents of 0( return board[WINNING_ROWS[row][0]]; )
Last edited on
Okay so when you say it returns 'X' it returns X to the screen? Also the [0] [1] [2] is what? Is it 0, 1, 2 in the winning rows?

I get all of the rest of the program but not this.
Last edited on
Line 61:
announceWinner(winner(board), computer, human);

A call to announce the winner.


The announceWinner function:
void announceWinner(char winner, char computer, char human)

This function takes: char, char, char

So, the return of winner( board ) will be sent to the announceWinner function as the first parameter. Which is the returned char.

Also the [0] [1] [2] is what? Is it 0, 1, 2 in the winning rows?

Yes.
Brilliant. Thank you.
No problem! Glad you understand it! (:
Topic archived. No new replies allowed.