tic tac toe

Hi I have made this simple tic tac toe game for my project for school. At the moment the game only ends when there is a winner. I have tried loads of things to try and get the game to end if it is a draw but they either don't do anything or make the game stop early. Does anyone have any idea of what I can do because I can't think of anything else.
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
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
#include <iostream>
#include <string>

using namespace std;

void printGrid(char grid[3][3])
{
	for (int j = 0; j <= 2; j++) {
		for (int k = 0; k <= 2; k++) {
			cout << grid[j][k] << "\t";
			if (k == 2)
			{
				cout << "\n";
			}

		}


	}
}

void printFirstGrid(int numgrid[3][3])
{
	for (int j = 0; j <= 2; j++) {
		for (int k = 0; k <= 2; k++) {
			cout << numgrid[j][k] << "\t";
			if (k == 2)
			{
				cout << "\n";
			}

		}


	}
}

int win(char grid[3][3]) {

		if (grid[0][0] == 'O' && grid[0][1] == 'O' && grid[0][2] == 'O' || grid[1][0] == 'O' && grid[1][1] == 'O' && grid[1][1] == 'O' && grid[1][2] == 'O' || grid[2][0] == 'O' && grid[2][1] == 'O' && grid[2][2] == 'O' || grid[0][0] == 'O' && grid[1][1] == 'O' && grid[2][2] == 'O' || grid[0][0] == 'O' && grid[1][0] == 'O' && grid[2][0] == 'O' || grid[0][1] == 'O' && grid[1][1] == 'O' && grid[2][1] == 'O' || grid[0][2] == 'O' && grid[1][2] == 'O' && grid[2][2] == 'O' || grid[0][2] == 'O' && grid[1][1] == 'O' && grid[2][0] == 'O') {
			return 1;
		}
		if (grid[0][0] == 'X' && grid[0][1] == 'X' &&  grid[0][2] == 'X' || grid[1][0] == 'X' && grid[1][1] == 'X'  && grid[1][2] == 'X' || grid[2][0] == 'X' && grid[2][1] == 'X' && grid[2][2] == 'X' || grid[0][0] == 'X' && grid[1][1] == 'X' && grid[2][2] == 'X' || grid[0][0] == 'X' && grid[1][0] == 'X' && grid[2][0] == 'X' || grid[0][1] == 'X' && grid[1][1] == 'X' && grid[2][1] == 'X' || grid[0][2] == 'X' && grid[1][2] == 'X' && grid[2][2] == 'X' || grid[0][2] == 'X' && grid[1][1] == 'X' && grid[2][0] == 'X') {
			return 2;
		}
	
}

void player1Turn(char grid[3][3]) {
	int player1choice;
	cout << "PLAYER 1 CHOOSE A NUMBER FROM GRID:\n" << endl;
	cin >> player1choice;

	if (player1choice == 1) {
		grid[0][0] = 'O';
	}
	else if (player1choice == 2) {
		grid[0][1] = 'O';
	}
	else if (player1choice == 3) {
		grid[0][2] = 'O';
	}
	else if (player1choice == 4) {
		grid[1][0] = 'O';
	}
	else if (player1choice == 5) {
		grid[1][1] = 'O';
	}
	else if (player1choice == 6) {
		grid[1][2] = 'O';
	}
	else if (player1choice == 7) {
		grid[2][0] = 'O';
	}
	else if (player1choice == 8) {
		grid[2][1] = 'O';
	}
	else if (player1choice == 9) {
		grid[2][2] = 'O';
	}

	if (player1choice == 'X' || player1choice == 'O') {
		cout << "\n SPACE ALREADY CHOSEN TRY AGAIN \n" << endl;
		cin >> player1choice; 

	}
printGrid(grid);
}

void player2turn(char grid[3][3]) {
	int player2choice;
	cout << "PLAYER 2 CHOOSE A NUMBER FROM GRID:\n" << endl;
	cin >> player2choice;

	if (player2choice == 1) {
		grid[0][0] = 'X';
	}
	else if (player2choice == 2) {
		grid[0][1] = 'X';
	}
	else if (player2choice == 3) {
		grid[0][2] = 'X';
	}
	else if (player2choice == 4) {
		grid[1][0] = 'X';
	}
	else if (player2choice == 5) {
		grid[1][1] = 'X';
	}
	else if (player2choice == 6) {
		grid[1][2] = 'X';
	}
	else if (player2choice == 7) {
		grid[2][0] = 'X';
	}
	else if (player2choice == 8) {
		grid[2][1] = 'X';
	}
	else if (player2choice == 9) {
		grid[2][2] = 'X';
	}

	if (player2choice == 'X', player2choice == 'O') {
		cout << "\n SPACE ALREADY CHOSEN TRY AGAIN \n" << endl;
		cin >> player2choice;

	}
	
    printGrid(grid);
}

int main() {
	int numgrid[3][3] = {
		{ 1 ,2 ,3 },
		{ 4, 5, 6 },
		{ 7, 8, 9 } };

	char grid[3][3] = {
		{' ' , ' ' , ' ' },
		{' ', ' ', ' ' },
		{' ', ' ', ' '} };

	cout << "\n NAUGHTS AND CROSSES\n" << endl;
	cout << "---------------------\n" << endl;

	printGrid(grid);
	cout << "--------------------\n" << endl;

	printFirstGrid(numgrid);
	cout << "--------------------\n" << endl;
	cout << "\nPLAYER 1 = O\n" << endl;
	cout << "PLAYER 2 = X \n" << endl;

	bool stillPlaying = true;
	while (stillPlaying = true) {

		player1Turn(grid);
		cout << "------------------" << endl;
		printFirstGrid(numgrid);
		cout << "------------------" << endl;
		win(grid);

		player2turn(grid);
		cout << "------------------" << endl;
		printFirstGrid(numgrid);
		cout << "------------------" << endl;
		win(grid);


		int result = win(grid);

		if (result == 1) {
			cout << "\n GAME OVER - PLAYER 1 HAS WON\n" << endl;
			bool stillPlaying = false;
			break;
		}
		else if (result == 2) {
			cout << "\n GAME OVER - PLAYER 2 HAS WON \n" << endl;
			bool stillPlaying = false;
			break;
		}

	}
		return 0; 
}
  

Hello sophiemarisa,

Just looking at the program it looks to me that you have checked if there is a win, but have done nothing to deal with it being a tie.

I am thinking of a nested for loop to to check the array to see if all the elements are filled. Or checking the array to see if either player has a move left.

Hope that helps.

Andy
You can create a function to check if it is a draw and inside your while loop call it if it is not a win.
Or you create a more general function GetResult() that either returns the winner or 3 for draw.

BTW while (stillPlaying = true) The comparison operator is == not =
You also could use enums for the different states like:
1
2
3
4
5
6
7
8
9
10
11
12
enum class GameState
{
  Running,
  Over
};

enum class GameResult
{
  NaughtWon, // 'o'
  CrossWon,  // 'x'
  Draw
};
you could use an int to count turns. When the int reaches 9 and no one is a winner the game is a tie and ends.
I added this to my win function but it makes the game stop at random times

if (grid[0][0] == 'X' || grid[0][0] == 'O' && grid[0][1] == 'X' || grid[0][1] == 'O' && grid[0][2] == 'X' || grid[0][2] == 'O' && grid[1][0] == 'X' || grid[1][0] == 'O' && grid[1][1] == 'X' || grid[1][1] == 'O' && grid[1][2] == 'X' || grid[1][2] == 'O' && grid[2][0] == 'X' || grid[2][0] == 'O' && grid[2][1] == 'X' || grid[2][1] == 'O' && grid[2][2] == 'X' || grid[2][2] == 'O') {
return 3;
}

is there no way I could do it like this?
My goodness, that is some knotty code. You could work out something like that, but please don't.
Hello sophiemarisa,

Before I dig into these if statements I thought I would give you a different look at what you did and ask if you see any difference or problem?

I want to make some changes here because my first did not show a winner when it should have.

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
int win(char grid[3][3])
{

	if (grid[0][0] == 'O' && grid[0][1] == 'O' && grid[0][2] == 'O' ||
	    grid[1][0] == 'O' && grid[1][1] == 'O' && grid[1][1] == 'O' &&
	    grid[1][2] == 'O' || grid[2][0] == 'O' && grid[2][1] == 'O' &&
	    grid[2][2] == 'O' || grid[0][0] == 'O' && grid[1][1] == 'O' &&
	    grid[2][2] == 'O' || grid[0][0] == 'O' && grid[1][0] == 'O' &&
	    grid[2][0] == 'O' || grid[0][1] == 'O' && grid[1][1] == 'O' &&
	    grid[2][1] == 'O' || grid[0][2] == 'O' && grid[1][2] == 'O' &&
	    grid[2][2] == 'O' || grid[0][2] == 'O' && grid[1][1] == 'O' &&
	    grid[2][0] == 'O')
	{  //<--- Not really needed, but OK.
		return 1;
	}  //<--- Not really needed, but OK.

	if (grid[0][0] == 'X' && grid[0][1] == 'X' &&  grid[0][2] == 'X' ||
	    grid[1][0] == 'X' && grid[1][1] == 'X'  && grid[1][2] == 'X' ||
	    grid[2][0] == 'X' && grid[2][1] == 'X' && grid[2][2] == 'X' ||
	    grid[0][0] == 'X' && grid[1][1] == 'X' && grid[2][2] == 'X' ||
	    grid[0][0] == 'X' && grid[1][0] == 'X' && grid[2][0] == 'X' ||
	    grid[0][1] == 'X' && grid[1][1] == 'X' && grid[2][1] == 'X' ||
	    grid[0][2] == 'X' && grid[1][2] == 'X' && grid[2][2] == 'X' ||
	    grid[0][2] == 'X' && grid[1][1] == 'X' && grid[2][0] == 'X')
	{  //<--- Not really needed, but OK.
		return 2;
	}  //<--- Not really needed, but OK.

}


And this is what I changed it to:
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
int win(char grid[3][3])
{

	if (grid[0][0] == 'O' && grid[0][1] == 'O' && grid[0][2] == 'O' ||  // <--- Rows Wins.
	    grid[1][0] == 'O' && grid[1][1] == 'O' && grid[1][2] == 'O' ||
	    grid[2][0] == 'O' || grid[2][1] == 'O' && grid[2][2] == 'O' ||

	    grid[2][2] == 'O' || grid[0][0] == 'O' && grid[1][1] == 'O' ||  // <--- Diaginal OK.
		
	    grid[0][2] == 'O' || grid[1][1] == 'O' && grid[2][0] == 'O' ||  // <--- Other Diaginal wrong. Have changed.
		
	    grid[0][0] == 'O' || grid[0][1] == 'O' && grid[0][2] == 'O' ||  // <--- Colomns wins.
	    grid[0][1] == 'O' || grid[1][1] == 'O' && grid[2][1] == 'O' ||
	    grid[0][2] == 'O' || grid[1][2] == 'O' && grid[2][2] == 'O')
	    //grid[2][0] == 'O')  // <--- Not needed.
	{  //<--- Not really needed, but OK.
		return 1;
	}  //<--- Not really needed, but OK.

	if (grid[0][0] == 'X' && grid[0][1] == 'X' &&  grid[0][2] == 'X' ||  // <--- Rows Wins.
	    grid[1][0] == 'X' && grid[1][1] == 'X'  && grid[1][2] == 'X' ||
	    grid[2][0] == 'X' && grid[2][1] == 'X' && grid[2][2] == 'X' ||

	    grid[0][0] == 'X' && grid[1][1] == 'X' && grid[2][2] == 'X' ||  // <--- Diaginal OK.

	    grid[0][2] == 'X' && grid[1][1] == 'X' && grid[2][0] == 'X' ||  // <--- Other Diaginal wrong. Have changed

	    grid[0][0] == 'X' && grid[1][0] == 'X' && grid[2][0] == 'X' ||  // <--- Colomns wins.
	    grid[0][1] == 'X' && grid[1][1] == 'X' && grid[2][1] == 'X' ||
	    grid[0][2] == 'X' && grid[1][2] == 'X' && grid[2][2] == 'X')
	{  //<--- Not really needed, but OK.
		return 2;
	}  //<--- Not really needed, but OK.

}


Hope that helps,

Andy

Edit:
Last edited on
thank you so much that layout is a lot clearer to see everything
please can you still help me with the if statements I've been trying to do it but I'm still not getting anywhere.
Thank you
Hello sophiemarisa,

It is nice that the compiler does not care about white space. It makes changing things around easier.

After I made the changes and tested the program I found that the section for columns was not quite right I had to go through the subscripts and make some changes for it to work right.

I also fount that the if statement for "O" had some "||" that needed changed to "&&" along with putting some () around the logical and statements.

Eventually I add a second parameter to the "win" function of "std::size_t& count" to keep track of the number of turns. and a third if statement that returns 3 if the count is 7.

So far all my testing appears to work.

I moved the definition of "result" to the top of main.

Then after each player's turn I put result = win(grid, count); followed by the if/else if statements to determine who won with the last else if for a tie. All this is duplicated for player two.

Hope this helps,

Andy
Hi is there any way you can show me your code or just guide me on how to add that in because I've never seen that before so I don't know to really use it. If not it's not a problem thank you for all the help.

Thank you,
Sophie
Hello sophiemarisa,

This is what I did in the main function:

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
int main()
{
	char numgrid[3][3] = {
		{ '1' ,'2' ,'3' },
		{ '4', '5', '6' },
		{ '7', '8', '9' } };

	char grid[3][3] = {
		{ ' ' , ' ' , ' ' },
		{ ' ', ' ', ' ' },
		{ ' ', ' ', ' ' } };

	int result{};
	std::size_t count{};

	std::cout << "\n NAUGHTS AND CROSSES\n" << std::endl;
	std::cout << "---------------------\n" << std::endl;

	printGrid(grid);
	std::cout << "--------------------\n" << std::endl;

	printFirstGrid(numgrid);
	std::cout << "--------------------\n" << std::endl;
	std::cout << "\nPLAYER 1 = O\n" << std::endl;
	std::cout << "PLAYER 2 = X \n" << std::endl;

	bool stillPlaying = true;

	while (stillPlaying)
	{

		player1Turn(grid, numgrid);
		std::cout << "------------------" << std::endl;
		printFirstGrid(numgrid);
		std::cout << "------------------" << std::endl;

		result = win(grid, count);

		if (result == 1)
		{
			std::cout << "\n GAME OVER - PLAYER 1 HAS WON\n" << std::endl;
			bool stillPlaying = false;
			break;
		}
		else if (result == 2)
		{
			std::cout << "\n GAME OVER - PLAYER 2 HAS WON \n" << std::endl;
			bool stillPlaying = false;
			break;
		}
		else if (result == 3)
		{
			std::cout << "\n THE GAME IS A TIE.\n" << std::endl;
			break;
		}

		player2turn(grid, numgrid);
		std::cout << "------------------" << std::endl;
		printFirstGrid(numgrid);
		std::cout << "------------------" << std::endl;
		result = win(grid, count);


		if (result == 1)
		{
			std::cout << "\n GAME OVER - PLAYER 1 HAS WON\n" << std::endl;
			bool stillPlaying = false;
			break;
		}
		else if (result == 2)
		{
			std::cout << "\n GAME OVER - PLAYER 2 HAS WON \n" << std::endl;
			bool stillPlaying = false;
			break;
		}
		else if (result == 3)
		{
			std::cout << "\n THE GAME IS A TIE.\n" << std::endl;
			break;
		}
	}
	return 0;
}


And this is my revised code for "win" function

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
int win(char grid[3][3], std::size_t& count)
{

	if ((grid[0][0] == 'O' && grid[0][1] == 'O' && grid[0][2] == 'O') ||  // <--- Rows Wins.
		(grid[1][0] == 'O' && grid[1][1] == 'O' && grid[1][2] == 'O') ||
		(grid[2][0] == 'O' && grid[2][1] == 'O' && grid[2][2] == 'O') ||

		(grid[2][2] == 'O' && grid[0][0] == 'O' && grid[1][1] == 'O') ||  // <--- Diaginal OK.
		
		(grid[0][2] == 'O' && grid[1][1] == 'O' && grid[2][0] == 'O') ||  // <--- Other Diaginal wrong. Have changed.
		
		(grid[0][0] == 'O' && grid[1][0] == 'O' && grid[2][0] == 'O') ||  // <--- Colomns wins.
		(grid[0][1] == 'O' && grid[1][1] == 'O' && grid[2][1] == 'O') ||
		(grid[0][2] == 'O' && grid[1][2] == 'O' && grid[2][2] == 'O'))
		//grid[2][0] == 'O')  // <--- Not needed.
	{  //<--- Not really needed, but OK.
		return 1;
	}  //<--- Not really needed, but OK.

	if ((grid[0][0] == 'X' && grid[0][1] == 'X' && grid[0][2] == 'X') ||  // <--- Rows Wins.
		(grid[1][0] == 'X' && grid[1][1] == 'X' && grid[1][2] == 'X') ||
		(grid[2][0] == 'X' && grid[2][1] == 'X' && grid[2][2] == 'X') ||

		(grid[0][0] == 'X' && grid[1][1] == 'X' && grid[2][2] == 'X') ||  // <--- Diaginal OK.

		(grid[0][2] == 'X' && grid[1][1] == 'X' && grid[2][0] == 'X') ||  // <--- Other Diaginal wrong. Have changed

		(grid[0][0] == 'X' && grid[1][0] == 'X' && grid[2][0] == 'X') ||  // <--- Colomns wins.
		(grid[0][1] == 'X' && grid[1][1] == 'X' && grid[2][1] == 'X') ||
		(grid[0][2] == 'X' && grid[1][2] == 'X' && grid[2][2] == 'X'))
	{  //<--- Not really needed, but OK.
		return 2;
	}  //<--- Not really needed, but OK.

	count++;
	if (count == 7) { return 3; }

	return 0;
}


I changed the "numgrid" array to a char and used it in the "player..." functions like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void player1Turn(char grid[3][3], char numgrid[3][3])
{
	int player1choice;
	std::cout << "PLAYER 1 CHOOSE A NUMBER FROM GRID:\n" << std::endl;
	std::cin >> player1choice;

	if (player1choice == 1)
	{
		grid[0][0] = 'O';
		numgrid[0][0] = ' ';
	}
	else if (player1choice == 2)
	{
		grid[0][1] = 'O';
		numgrid[0][1] = ' ';
	}
        // The rest of the code goes here 


The added line will erase the number used. I would have used a switch/case in place of all the if/else if statements.

Hope that helps,

Andy
Hello i believe i may have a similar problem but not exactly a tic tac toe game. I am just starting a C++ class and my teacher gave the following as an assignment.

For this assignment, you will design a game called . In this game there is one player who
is playing against the computer. The game presents the player with a grid with numbers shown in a 3 x 3 chart.

At the start of the game, the game will print a message to explain to the player,
welcome them, and ask them for three initials of the player’s name. The game will then use a random
number generator to generate six numbers between 1 and 9. The player will NOT be shown the six
numbers. The game will use the six numbers to place the initials twice in the chart at the given positions.


What i am particularly confused about is how exactly to create the grid or display the grid and and generate the numbers or letters.

Any type of help would be appreciated, thanks in advance.
@loskers,

Welcome to the forum.

It is not nice invade someone else's topic with your question or problem. It is better to start your own topic, so that the help is directed to your needs.

I realize that your problem may be similar, but you can use it for ideas.

I will look for your own topic and we can go from there.

Andy
Thank you so much Andy you've helped me so much :)
I'm sorry and thanks will create one right now
Topic archived. No new replies allowed.