C++ Tic Tac Toe Game
- C++ Tic Tac Toe Game
- Step 1: Create a Function That Draws a 3-by-3 Grid
- Step 2: Ask User to Enter Row and Column Numbers
- Step 3: Check if Position Entered by User Is Occupied
- Step 4: Create a Function to Check Game Winner
This tutorial will discuss creating the tic tac toe game using conditional statements and loops in C++.
C++ Tic Tac Toe Game
Tic tac toe is a game of two players in which each player marks a place inside a 3-by-3 grid, and the player who successfully places three marks on a straight horizontal, vertical, or diagonal line will be the winner of the game. An example image of the game is shown below.
We can see that player X is the winner of the tic tac toe game because the three markers of player X are in a straight diagonal line. To create the same game in C++, we have to use the same algorithm to play the game using a pen and paper.
Using the pen, we draw the 3-by-3 grid on the paper, and then each player turns to place a marker inside the grid in the unoccupied space. When one player manages to place three markers in a straight line, that player will win the game, and the game will be over.
If none of the players place three markers in a straight line or all the places inside the grid are occupied, the game will be over with a tie. We can use the same algorithm to create the tic tac toe game in C++.
In the first step, we have to create a function drawing a 3-by-3 grid. In the second step, we have to take input from the user in the form of row and column numbers and check if the input is valid.
In the third step, we have to check if the position entered by the user is occupied or not, and if it is not occupied, we will place the marker of the player inside the grid at the position entered by the user, and if the place is occupied, we will ask the player to enter another position. If all the positions are occupied, we will end the game and announce that it’s a tie.
In the fourth step, we will check if three markers of any of the players are in a straight line or not. If the markers of a player are in a straight line, we will end the game and announce the player name who won the game, and if the markers are not in a straight line, we will go back to the second step and repeat.
Step 1: Create a Function That Draws a 3-by-3 Grid
Now let’s start creating the game from the first step in which we have to draw a 3-by-3 board. We can draw a board using a combination of pipe characters |
and dash characters -
from the keyboard.
We can use the dash characters -
to draw the horizontal line and the pipe character |
to draw the vertical line present in a grid, and we can use numbers to mark the row and column number of the grid. For example, let’s use C++ cout()
function to draw the 3-by-3 grid.
See the code below.
#include <iomanip>
#include <iostream>
using namespace std;
void drawGameBoard(char Gameboard[][3]);
int main() {
char Gameboard[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
drawGameBoard(Gameboard);
return 0;
}
void drawGameBoard(char Gameboard[][3]) {
cout << " 1 2 3" << endl;
cout << " -------------" << endl;
cout << " 1"
<< " | " << Gameboard[0][0] << " | " << Gameboard[0][1] << " | "
<< Gameboard[0][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 2"
<< " | " << Gameboard[1][0] << " | " << Gameboard[1][1] << " | "
<< Gameboard[1][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 3"
<< " | " << Gameboard[2][0] << " | " << Gameboard[2][1] << " | "
<< Gameboard[2][2] << " | " << endl;
cout << " -------------" << endl;
}
Output:
1 2 3
-------------
1 | | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
The above code uses the endl
statement to move the cursor to the new line. In the above output, the numbers played vertically to represent the row number, and the horizontal numbers represent the column number.
Step 2: Ask User to Enter Row and Column Numbers
In the second step, we can ask the user to enter the row and the column number in which the user wants to place its marker. We will use a conditional statement to check the user input, and if the row or column number is not in the range of 1 to 3, we will display an error and ask the user to enter the input again.
We will use a loop to take the input from the user, and the loop will continue until the user enters a valid row and column number. For example, let’s use a while
loop and an if-else
statement to take input from the user.
See the code below.
#include <iomanip>
#include <iostream>
using namespace std;
void drawGameBoard(char Gameboard[][3]);
int main() {
int Boardrow;
int Boardcolumn;
bool is_Boardrow;
bool is_Boardcolumn;
char Gameboard[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
drawGameBoard(Gameboard);
is_Boardrow = false;
while (!is_Boardrow) {
cout << "BoardRow: ";
cin >> Boardrow;
if (Boardrow == 1 || Boardrow == 2 || Boardrow == 3) {
is_Boardrow = true;
} else {
cout << endl << "Invalid Boardrow!" << endl;
}
}
is_Boardcolumn = false;
while (!is_Boardcolumn) {
cout << "BoardColumn: ";
cin >> Boardcolumn;
if (Boardcolumn == 1 || Boardcolumn == 2 || Boardcolumn == 3) {
is_Boardcolumn = true;
} else {
cout << endl << "Invalid Boardcolumn!" << endl;
}
}
return 0;
}
void drawGameBoard(char Gameboard[][3]) {
cout << " 1 2 3" << endl;
cout << " -------------" << endl;
cout << " 1"
<< " | " << Gameboard[0][0] << " | " << Gameboard[0][1] << " | "
<< Gameboard[0][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 2"
<< " | " << Gameboard[1][0] << " | " << Gameboard[1][1] << " | "
<< Gameboard[1][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 3"
<< " | " << Gameboard[2][0] << " | " << Gameboard[2][1] << " | "
<< Gameboard[2][2] << " | " << endl;
cout << " -------------" << endl;
}
Output:
1 2 3
-------------
1 | | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
BoardRow: 5
Invalid Boardrow!
BoardRow: 1
BoardColumn: 6
Invalid Boardcolumn!
BoardColumn: 2
In the above code, we used two integers, Boardrow
and Boardcolumn
, to store the user input. We used two Boolean variables, is_boardRow
and is_boardColumn
, to store the status of the input.
We will set the two Boolean variables to false
, and the loop will repeat itself and ask the user to enter the row and column number, and when the entered number is valid, the Boolean will be set to true
, and the loop will break. We have used two loops, one for the row number and the other for the column number.
The above output shows that when we enter an invalid row or column number, the code displays an invalid row or column number and will ask the user to enter the input again.
Step 3: Check if Position Entered by User Is Occupied
In the third step, we have to place the players’ marker at the position the user entered, but before that, we have to check whether the entered position is occupied.
If the position is occupied, we will ask the user to enter another position, and if the position is not occupied, we will place the player’s marker inside the board at the entered position.
We will have to change the player after one player successfully places a marker on the game board or grid. For example, let’s use a loop and condition statements to place the marker on the board.
See the code below.
#include <iomanip>
#include <iostream>
using namespace std;
void drawGameBoard(char Gameboard[][3]);
char checkGameWinner3by3(char Gameboard[][3]);
int main() {
char Gameboard[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
char Gameplayer = 'X';
char Gamewinner = ' ';
int Boardrow;
int Boardcolumn;
bool is_Validmove;
bool is_Boardrow;
bool is_Boardcolumn;
cout << "************ TIC TAC TOE Game ************\n";
while (Gamewinner == ' ') {
is_Validmove = false;
is_Boardrow = false;
is_Boardcolumn = false;
drawGameBoard(Gameboard);
cout << "GamePlayer ";
if (Gameplayer == 'X') {
cout << 'X';
} else {
cout << 'O';
}
cout << "'s turn:" << endl;
is_Validmove = false;
while (!is_Validmove) {
is_Boardrow = false;
while (!is_Boardrow) {
cout << "BoardRow: ";
cin >> Boardrow;
if (Boardrow == 1 || Boardrow == 2 || Boardrow == 3) {
is_Boardrow = true;
} else {
cout << endl << "Invalid Boardrow!" << endl;
}
}
is_Boardcolumn = false;
while (!is_Boardcolumn) {
cout << "BoardColumn: ";
cin >> Boardcolumn;
if (Boardcolumn == 1 || Boardcolumn == 2 || Boardcolumn == 3) {
is_Boardcolumn = true;
} else {
cout << endl << "Invalid Boardcolumn!" << endl;
}
}
if (Gameboard[Boardrow - 1][Boardcolumn - 1] == ' ') {
Gameboard[Boardrow - 1][Boardcolumn - 1] = Gameplayer;
is_Validmove = true;
if (Gameplayer == 'X') {
Gameplayer = 'O';
} else {
Gameplayer = 'X';
}
} else {
cout << "The selected space is occupied!" << endl;
cout << "Select a different space:" << endl << endl;
drawGameBoard(Gameboard);
}
}
cout << endl;
}
system("pause");
return 0;
}
void drawGameBoard(char Gameboard[][3]) {
cout << " 1 2 3" << endl;
cout << " -------------" << endl;
cout << " 1"
<< " | " << Gameboard[0][0] << " | " << Gameboard[0][1] << " | "
<< Gameboard[0][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 2"
<< " | " << Gameboard[1][0] << " | " << Gameboard[1][1] << " | "
<< Gameboard[1][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 3"
<< " | " << Gameboard[2][0] << " | " << Gameboard[2][1] << " | "
<< Gameboard[2][2] << " | " << endl;
cout << " -------------" << endl;
}
Output:
************ TIC TAC TOE Game ************
1 2 3
-------------
1 | | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
GamePlayer X's turn:
BoardRow: 1
BoardColumn: 1
1 2 3
-------------
1 | X | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
GamePlayer O's turn:
BoardRow: 2
BoardColumn: 2
1 2 3
-------------
1 | X | | |
-------------
2 | | O | |
-------------
3 | | | |
-------------
GamePlayer X's turn:
BoardRow:
In the above code, we used another Boolean variable, is_validMove
, to save the status of the entered position. The Boolean will be set to false
, and the while
loop will repeat itself; the Boolean is set to true
, and we will set it true
if the user enters a position that is not already occupied.
We have used another variable, Gamewinner
, which is set to an empty string, and this will be used in the next step to declare the winner and stop the game.
Below the while
loop, which takes input from the user, we used an if-else
statement to check the entered position inside the Gameboard
array, and if the position is free, we will add the player’s marker and set the is_validmove
Boolean to true
, and we will change the player, and if the space is not free, we will display that the space is occupied and will ask the user to enter another space or position and after that, we will draw the game board.
We can see in the above output that the player markers are being placed inside the game board.
Step 4: Create a Function to Check Game Winner
In the last step, we will make a function to check the game winner. To check the game winner, we must check each row, column and diagonal entry of the grid or game board.
If any of the rows, columns or diagonal entries of the board have three same markers, we will return that marker, and if none of them have three markers, we will return an empty string.
We will save the output of the game winner function inside the Gamewinner
variable, and the main loop will stop if there is a game winner; otherwise, it will continue.
If there is a winner, we will announce it and end the game; otherwise, the game will be a tie. For example, let’s create the game winner function using for
loops and conditional statements.
See the code below.
#include <iomanip>
#include <iostream>
using namespace std;
void drawGameBoard(char Gameboard[][3]);
char checkGameWinner3by3(char Gameboard[][3]);
int main() {
char Gameboard[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
char Gameplayer = 'X';
char Gamewinner = ' ';
int Boardrow;
int Boardcolumn;
bool is_Validmove;
bool is_Boardrow;
bool is_Boardcolumn;
cout << "************ TIC TAC TOE Game ************\n";
while (Gamewinner == ' ') {
is_Validmove = false;
is_Boardrow = false;
is_Boardcolumn = false;
drawGameBoard(Gameboard);
cout << "GamePlayer ";
if (Gameplayer == 'X') {
cout << 'X';
} else {
cout << 'O';
}
cout << "'s turn:" << endl;
is_Validmove = false;
while (!is_Validmove) {
is_Boardrow = false;
while (!is_Boardrow) {
cout << "BoardRow: ";
cin >> Boardrow;
if (Boardrow == 1 || Boardrow == 2 || Boardrow == 3) {
is_Boardrow = true;
} else {
cout << endl << "Invalid Boardrow!" << endl;
}
}
is_Boardcolumn = false;
while (!is_Boardcolumn) {
cout << "BoardColumn: ";
cin >> Boardcolumn;
if (Boardcolumn == 1 || Boardcolumn == 2 || Boardcolumn == 3) {
is_Boardcolumn = true;
} else {
cout << endl << "Invalid Boardcolumn!" << endl;
}
}
if (Gameboard[Boardrow - 1][Boardcolumn - 1] == ' ') {
Gameboard[Boardrow - 1][Boardcolumn - 1] = Gameplayer;
is_Validmove = true;
if (Gameplayer == 'X') {
Gameplayer = 'O';
} else {
Gameplayer = 'X';
}
} else {
cout << "The selected space is occupied!" << endl;
cout << "Select a different space:" << endl << endl;
drawGameBoard(Gameboard);
}
}
cout << endl;
Gamewinner = checkGameWinner3by3(Gameboard);
if (Gamewinner == 'X' || Gamewinner == 'O') {
drawGameBoard(Gameboard);
cout << "Congratulations! GamePlayer ";
if (Gamewinner == 'X') {
cout << 'X';
} else {
cout << 'O';
}
cout << " is the Gamewinner!" << endl;
} else if (Gamewinner == 'T') {
drawGameBoard(Gameboard);
cout << "It's a tie!" << endl;
}
}
system("pause");
return 0;
}
void drawGameBoard(char Gameboard[][3]) {
cout << " 1 2 3" << endl;
cout << " -------------" << endl;
cout << " 1"
<< " | " << Gameboard[0][0] << " | " << Gameboard[0][1] << " | "
<< Gameboard[0][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 2"
<< " | " << Gameboard[1][0] << " | " << Gameboard[1][1] << " | "
<< Gameboard[1][2] << " | " << endl;
cout << " -------------" << endl;
cout << " 3"
<< " | " << Gameboard[2][0] << " | " << Gameboard[2][1] << " | "
<< Gameboard[2][2] << " | " << endl;
cout << " -------------" << endl;
}
char checkGameWinner3by3(char Gameboard[][3]) {
for (int i = 0; i < 3; i++) {
if (Gameboard[i][0] == Gameboard[i][1] &&
Gameboard[i][0] == Gameboard[i][2]) {
return Gameboard[i][0];
}
}
for (int i = 0; i < 3; i++) {
if (Gameboard[0][i] == Gameboard[1][i] &&
Gameboard[0][i] == Gameboard[2][i]) {
return Gameboard[0][i];
}
}
if (Gameboard[0][0] == Gameboard[1][1] &&
Gameboard[1][1] == Gameboard[2][2]) {
return Gameboard[0][0];
}
if (Gameboard[0][2] == Gameboard[1][1] &&
Gameboard[1][1] == Gameboard[2][0]) {
return Gameboard[0][2];
}
return ' ';
}
Output:
************ TIC TAC TOE Game ************
1 2 3
-------------
1 | | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
GamePlayer X's turn:
BoardRow: 1
BoardColumn: 1
1 2 3
-------------
1 | X | | |
-------------
2 | | | |
-------------
3 | | | |
-------------
GamePlayer O's turn:
BoardRow: 2
BoardColumn: 1
1 2 3
-------------
1 | X | | |
-------------
2 | O | | |
-------------
3 | | | |
-------------
GamePlayer X's turn:
BoardRow: 2
BoardColumn: 2
1 2 3
-------------
1 | X | | |
-------------
2 | O | X | |
-------------
3 | | | |
-------------
GamePlayer O's turn:
BoardRow: 3
BoardColumn: 1
1 2 3
-------------
1 | X | | |
-------------
2 | O | X | |
-------------
3 | O | | |
-------------
GamePlayer X's turn:
BoardRow: 3
BoardColumn: 3
1 2 3
-------------
1 | X | | |
-------------
2 | O | X | |
-------------
3 | O | | X |
-------------
Congratulations! GamePlayer X is the Gamewinner!
In the code, we can see the checkGameWinner3by3()
function, which accepts the board as input and contains two for
loops and two if
statements. The for
loops are used to check the rows and columns, and the if
statements are used to check the diagonal entries.