Tic Tac Toe - Finding the winner

I'm having trouble getting the bool winner to evaluate to true if p1 selects 1 2 and 3 from the board. Which would be a win. It just keeps going.

This code is not done; In debugging stage.

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
// 6_TicTacToe.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

struct player {
	int move;
}p1[9], p2[9];

void chickenDinner(bool& cont, char squares[], bool& winner) {		// Winner, Winner, Chicken Dinner - Check
		if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		} else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else{
			winner = false;
		}
}

void drawBoard(char squares[]) {
	cout << "\n\n\tTic Tac Toe\n\n";
	cout << "Player 1 (X)\tPlayer 2(O)\n\n";
	cout << "     |     |     " << endl;
	cout << "  " << squares[1] << "  |  " << squares[2] << "  |  " << squares[3] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[4] << "  |  " << squares[5] << "  |  " << squares[6] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[7] << "  |  " << squares[8] << "  |  " << squares[9] << endl << endl << endl;
}


void play(char squares[]) {
	int count = 1;
	bool winner = false;
	while (winner == false) {
		for (int i=0; i<9; i++) {
				bool cont = true;
				if (count % 2 != 0) {
					count++;
					cout << "Player 1 please select a block to mark.";
					cin >> p1[i].move;
					squares[p1[i].move] = 'X';
				}else{
					count--;
					cout << "Player 2 please select a block to mark.";
					cin >> p2[i].move;
					squares[p2[i].move] = 'O';
				}

				while (cont == true) {
					system("cls");
					drawBoard(squares);
					chickenDinner(cont, squares, winner);
					cont = false;
				}

				if (winner == true)
					break;
			}	
	}
	cout << "\n\nPlayer X Wins!" << endl;
}

int main()
{
	char squares[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
	drawBoard(squares);
	play(squares);
	cin.get();
}

Last edited on
Never mind I got it. The increment variable 'i' in the for loop was incrementing twice per player because of the bi-player move setup. Just had to make an indexA and indexB to hold the actual move count. Thanks

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
// 6_TicTacToe.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

struct player {
	int move;
}p1[9], p2[9];

void chickenDinner(bool& cont, char squares[], bool& winner) {		// Winner, Winner, Chicken Dinner - Check
		if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[1].move == 1 && p1[2].move == 2 && p1[3].move == 3){
			winner = true;
		} else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else{
			winner = false;
		}
}

void drawBoard(char squares[]) {
	cout << "\n\n\tTic Tac Toe\n\n";
	cout << "Player 1 (X)\tPlayer 2(O)\n\n";
	cout << "     |     |     " << endl;
	cout << "  " << squares[1] << "  |  " << squares[2] << "  |  " << squares[3] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[4] << "  |  " << squares[5] << "  |  " << squares[6] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[7] << "  |  " << squares[8] << "  |  " << squares[9] << endl << endl << endl;
}


void play(char squares[]) {
	int count = 1;
	bool winner = false;
	int indexA = 0;
	int indexB = 0;
	while (winner == false) {
		for (int i=0; i<9; i++) {
				bool cont = true;
				if (count % 2 != 0) {
					indexA++;
					count++;
					cout << "Player 1 please select a block to mark.";
					cin >> p1[indexA].move;
					squares[p1[indexA].move] = 'X';
				}else{
					indexB++;
					count--;
					cout << "Player 2 please select a block to mark.";
					cin >> p2[indexB].move;
					squares[p2[indexB].move] = 'O';
				}

				while (cont == true) {
					system("cls");
					drawBoard(squares);
					chickenDinner(cont, squares, winner);
					cont = false;
				}

				if (winner == true)
					break;
			}	
	}
	cout << "\n\nPlayer X Wins!" << endl;
}

int main()
{
	char squares[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
	drawBoard(squares);
	play(squares);
	cin.get();
}
Last edited on
You inspired me! lmao.

I lost loads of code a while back, so I'm going to re-make this! (:
Last edited on
One problem I can already see is that you define your squares array as squares[10], but you only have 9 places that you can choose from on a Tic Tac Toe board. It would be something along the lines of squares[9] and you'd choose a value from 0 - 8.

I feel like you are making things much too complicated for yourself by using a struct to create players and their move choices. Plus, there is nowhere in your code that I can see where you check to make sure that the square chosen is not already occupied by the other player. Running this sort of code would go on forever, because player two could choose a spot that player one has chosen and your code would write over the previous choice.

I think you'd do a lot better by making a single position array that would keep track of the positions of the board, whether player one would place an 'X' and player 2 would place an 'O', something like this:

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
 
//Array declaration
char position[3][3]]; //3x3 board size
//Declare choices made by players
int row, col = 0;

//Initialize the array to empty spaces using an array

//If player 1 turn, place an X.  For example a clear board displays as
//|---+---+---|
//|   |   |   |
//|---+---+---|
//|   |   |   |
//|---+---+---|
//|   |   |   |
//|---+---+---|

//If player 1 chose row 1, col 1, it would place an X in the first spot
//(position[0][0])
//The new board would be drawn like this:
//|---+---+---|
//| X |   |   |
//|---+---+---|
//|   |   |   |
//|---+---+---|
//|   |   |   |
//|---+---+---|
//This way, when you go to check for a winning move you can easily do it by doing a statement like this:

//if (position[0][0] == "X" && position[1][0] == "X" && position[2][0] == "X")
//     return true;

//You can continue this pattern for all other winning combinations. 
This probably makes more sense, but I am practicing with objects. Also, I'm not sure how I will do my redundancy checks, but that's half the fun...
Last edited on
You're using data structures, not objects.
Good to know lol thanks
Last edited on
I have made the redundancy check function checkMark(). It accepts the players move input, the other players data structure and the index as arguments. However, It doesn't seem to be working and I'm not sure if I passed the parameters correctly.

The while (used == true) loop in lines 57 and 66 keeps looping after first input..

I think I need to take a rest for the day, I'm just reaching now... I think I burned out a fuse in my brain

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
#include "stdafx.h"
#include <iostream>
using namespace std;

struct player {
	int move;
} p1[9], p2[9];

bool checkMarks(int move, player p[], int index){    // Function under construction -- Previous used square check
	for (int i=0; i < 9; i++){
		if (move == p[i].move)
			return true;
	}
	return false;
}

void chickenDinner(char squares[], bool& winner) {		// Function under construction -- Winner, Winner, Chicken Dinner - Check
		if (p1[0].move == 0 && p1[1].move == 1 && p1[2].move == 2){
			winner = true;
		}else if (p1[1].move == 0 && p1[2].move == 1 && p1[3].move == 2){
			winner = true;
		} else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else if (p1[0].move == 1 && p1[1].move == 2 && p1[2].move == 3){
			winner = true;
		}else{
			winner = false;
		}
}

void drawBoard(char squares[]) {
	cout << "\n\n\tTic Tac Toe\n\n";
	cout << "Player 1 (X)\tPlayer 2(O)\n\n";
	cout << "     |     |     " << endl;
	cout << "  " << squares[0] << "  |  " << squares[1] << "  |  " << squares[2] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[3] << "  |  " << squares[4] << "  |  " << squares[5] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[6] << "  |  " << squares[7] << "  |  " << squares[8] << endl << endl << endl;
}


void play(char squares[]) {
	int count = 1;
	bool winner = false;
	int indexP1 = 0;
	int indexP2 = 0;
	bool used = true;
	while (winner == false) {
		for (int i=0; i<9; i++) {
				bool cont = true;
				if (count % 2 != 0) {
					while (used == true) {
						cout << "\aPlayer 1 please select a block to mark.";
						cin >> p1[indexP1].move;
						used = checkMarks(p1[indexP1].move, p2, indexP1);
					}
					squares[p1[indexP1].move] = 'X';
					indexP1++;
					count++;
				}else{
					while (used == true) {
						cout << "\aPlayer 2 please select a block to mark.";
						cin >> p2[indexP2].move;
						used = checkMarks(p2[indexP2].move, p1, indexP2);
					}
					squares[p2[indexP2].move] = 'O';
					indexP2++;
					count--;
				}

				while (cont == true) {
					system("cls");
					drawBoard(squares);
					chickenDinner(squares, winner);
					cont = false;
				}

				if (winner == true)
					break;
			}	
	}
	cout << "\n\nPlayer X Wins!" << endl;
}

int main()
{
	char squares[9] = { '0', '1', '2', '3', '4', '5', '6', '7', '8' };
	drawBoard(squares);
	play(squares);
	cin.get();
}
Last edited on
Sorry - I also figured out why my checkMarks() wasn't working. I had the original bool used variable defined as true outside of the loops, where it should have been defined inside.
This code doesn't allow p1 to overwrite any previous marked squares, which I want.. But p2 can overwrite them. Why is this? The code is the same for each instance.

1
2
3
4
5
6
7
8
9
10
11
struct player {
	int move;
} p1[9], p2[9];

bool checkMarks(int move, player p[], int index){
	for (int i=0; i < index; i++){
		if (move == p[i].move)
			return true;
	}
	return false;
}


starting at lines 11 and 20 here, the lines after 11 do stop p1 from selecting p2's previous positions, but lines after 20 don't stop p2 from selecting p1's previous positions. Why?
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
void play(char squares[]) {
	int count = 1;
	bool winner = false;
	int indexP1 = 0;
	int indexP2 = 0;
	while (winner == false) {
		for (int i=0; i<9; i++) {
				bool used = true;
				bool cont = true;
				if (count % 2 != 0) {
					while (used == true) {
						cout << "Player 1 please select a block to mark.";
						cin >> p1[indexP1].move;
						used = checkMarks(p1[indexP1].move, p2, indexP1);
					}
					squares[p1[indexP1].move] = 'X';
					indexP1++;
					count++;
				}else{
					while (used == true) {
						cout << "Player 2 please select a block to mark.";
						cin >> p2[indexP2].move;
						used = checkMarks(p2[indexP2].move, p1, indexP2);
					}
					squares[p2[indexP2].move] = 'O';
					indexP2++;
					count--;
				}

				while (cont == true) {
					system("cls");
					drawBoard(squares);
					chickenDinner(squares, winner);
					cont = false;
				}

				if (winner == true)
					break;
			}	
	}
	cout << "\n\nPlayer X Wins!" << endl;
}
Last edited on
Finished the tic tac toe game. woo! Just have that one bug where p1 cant select p2 previous selections as designed, but p2 CAN (unfortunately) select p1's previous selections

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
// 6_TicTacToe.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

struct player {
	int move;
} p1[9], p2[9];

bool checkMarks(int move, player p[], int index){		// Check if move exists in history
	for (int i=0; i < index; i++){
		if (move == p[i].move)
			return true;
	}
	return false;
}

bool chickenDinner(char squares[], bool& winner, char mark) {		// Winner, Winner, Chicken Dinner - Check
	if (squares[0] == mark && squares[1] == mark && squares[2] == mark) {
		return true;
	}else if (squares[3] == mark && squares[4] == mark && squares[5] == mark){
		return true;
	}else if (squares[6] == mark && squares[7] == mark && squares[8] == mark){
		return true;
	}else if (squares[0] == mark && squares[4] == mark && squares[8] == mark){
		return true;
	}else if (squares[2] == mark && squares[4] == mark && squares[6] == mark){
		return true;
	}else if (squares[0] == mark && squares[3] == mark && squares[6] == mark){
		return true;
	}else if (squares[1] == mark && squares[4] == mark && squares[7] == mark){
		return true;
	}else if (squares[2] == mark && squares[5] == mark && squares[8] == mark){
		return true;
	}else{
		return false;
	}
}

void drawBoard(char squares[]) {		// Board
	system("cls");
	cout << "\n\n\tTic Tac Toe\n\n";
	cout << "Player 1 (X)\tPlayer 2(O)\n\n";
	cout << "     |     |     " << endl;
	cout << "  " << squares[0] << "  |  " << squares[1] << "  |  " << squares[2] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[3] << "  |  " << squares[4] << "  |  " << squares[5] << endl;
	cout << "_____|_____|_____" << endl;
	cout << "     |     |     " << endl;
	cout << "  " << squares[6] << "  |  " << squares[7] << "  |  " << squares[8] << endl << endl << endl;
}


void play(char squares[]) {			// Get player moves and load other functions
	drawBoard(squares);
	int count = 1;
	bool winner = false;
	int indexP1 = 0;
	int indexP2 = 0;
	char mark = 'Z';
	int player = 0;
	while (winner == false) {
		for (int i=0; i<9; i++) {
				bool used = true;
				bool cont = true;
				if (count % 2 != 0) {
					mark = 'X';
					while (used == true || p1[indexP1].move > 8) {
						cout << "\aPlayer 1 (X) please select a block to mark.";
						cin >> p1[indexP1].move;
						used = checkMarks(p1[indexP1].move, p2, indexP1);
					}
					squares[p1[indexP1].move] = 'X';
					indexP1++;
					count++;
				}else{
					mark = 'O';
					while (used == true|| p1[indexP1].move > 8) {
						cout << "\aPlayer 2 (O) please select a block to mark.";
						cin >> p2[indexP2].move;
						used = checkMarks(p2[indexP2].move, p1, indexP2);
					}
					squares[p2[indexP2].move] = 'O';
					indexP2++;
					count--;
				}

				while (cont == true) {
					drawBoard(squares);
					winner = chickenDinner(squares, winner, mark);
					cont = false;
				}

				if (winner == true && mark == 'X'){
					player = 1;
					break;
				}else if (winner == true && mark == 'O'){
					player = 2;
					break;
				}
			}	
	}
	cout << "\n\n\a\a\a\aPlayer " << player << " wins!\n\n" << endl;
}

int main()
{
	char squares[9] = { '0', '1', '2', '3', '4', '5', '6', '7', '8' };
	play(squares);
	cin.get();
}
Last edited on
Just check to see if the board is not default.

Check the players move against the current board. If the board is equal it the players move, then it hasn't been done yet, as the board would contain an X or an O.
Ok Good idea - I'm trying this method. But, I don't get why 'used' is evaluating to true in my loop. I put test outputs within the loop to see if squares and p1.move are equal, and they appear to be equal, so used should be evaluating to false? Not sure why this isn't working...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
				if (count % 2 != 0) {
					mark = 'X';
					while (used == true || p1[indexP1].move > 8) {
						cout << "\aPlayer 1 (X) please select a block to mark.";
						cin >> p1[indexP1].move;
						if (p1[indexP1].move == squares[p1[indexP1].move]) {			// WORK ON THIS
							used = false;
						}else{
							cout << "p1 [" << indexP1 << "].move = " << p1[indexP1].move << endl;
							cout << "squares [" << indexP1 << "] = " << squares[p1[indexP1].move] << endl;
							used = true;
						}
					}
					squares[p1[indexP1].move] = 'X';
					indexP1++;
					count++;
Sorry, I'm finding it hard to follow your code. I don't understand why you used an array for the player moves.

I made mine now. I did the same as you, with the board. 1-9.

This is how I checked it:
https://www.dropbox.com/sh/1rimb0pnxvu52r7/y5vtyDsCYd?m

It's in gameBoard.cpp - Line 39.

int winC[ 8 ][ 3 ] is all possible winning combinations.
When it checks, it checks to see if all are the same. If they are, they must have been changed from the default.

I'm going out for a while, but I'll take another look at yours again! (:
Last edited on
I used array for player moves so I could keep a history of the moves by each player and print it at the end. I didn't think about 1 multidimensional array. I'm glad I could inspire you. Gotta run to class. (My favorite game is still the Bracketing search where the computer guesses user number from 0 to 100 in 7 moves or less)
aha! I made that yesterday too! Was it you asking in the forums about how to get it in 7 guesses, or something?

Here's some of the stuff I have made:
http://sites.google.com/site/davevisone/home/cplusplus

Made most of my stuff because of posts on this forum! I get bored a lot.

I'll have a look at your code now. (:
This line is your problem( line 13 ):
for (int i=0; i < index; i++){

You're not checking the last index of player two each time.
i <= index


Another problem. You're not actually checking the board for the current players moves.

i.e.
Player one can continuously place an 'X' in the same place, as can player two!


So, I wrote the above, then couldn't help myself, but to re-write your code! lol. Sorry!

This will check the board, instead of players moves. But your moves are still being saved.
1
2
3
4
5
6
7
8
9
bool checkMarks(int move, char squares[]){		// Check if move exists in history
	// move + '0' - This converts the int to a char with the same value. i.e. int 5, will be char '5'.
	// squares[ move ] - This will check the index of the number entered.
	//		User enters '1', squares[ 1 ] hasn't been used, so it's sill '1'.
	if( ( move + '0' ) == squares[ move ] )
		return false;

	return true;
}


The call now looks like:
used = checkMarks(p2[indexP2].move, squares);
Lynx yes, the bracketing search program thread was mine. I am knocking out each one of these beginner exercises to improve my abilities. I'm getting most of these done without much intervention from this forum, so I know I'm understanding the language better with each exercise.

And yes - that small if condition rewrite worked wonders. I did not know of this functionality (move + '0' ) - What is this, it seems like a new concept to me that I should learn.

Now it's on to Dungeon Crawl, which looks the best yet. Thanks again Lynx!

I hope my take on the tic tac toe program was decent when compared to others.
Last edited on
To be honest, I never knew about ( move + '0' ) until last night, when I was looking through my code, to re-write your's. And I couldn't remember where I did the comparison on the array, so I looked through the internet, aha!

I just check the code, and it will only work on single digits!
1
2
3
4
5
6
7
8
9
10
int main()
{
	int integer = 6; // Change this to > 9 and you start running thought the ascii table

	char character = ( integer + '0' );

	std::cout << "Char is: " << character << '\n';

	return 0;
}

Ascii table: http://www.asciitable.com/

I'm going to look up on this ( move + '0' ) now.

I got around this by using stringstream:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool gameBoard::move( const char &mv, const char &plChar )
{
	int idx = 0;

	std::stringstream ss( &mv );
	ss >> idx;	

	if( board[ idx - 1 ] == mv )
	{
		board[ idx - 1 ] = plChar;
		return true;
	}
	
	return false;
}
Topic archived. No new replies allowed.