CUSTOMISED
Expert-led training for your team
Dismiss
Learn How to Create a Console-Based Tic Tac Toe Game in C++ from Scratch

19 April 2023

How to Create a Tic Tac Toe Game in C++

Introduction:

Tic Tac Toe is a simple yet classic game that has been enjoyed by people of all ages for generations. It's a perfect game for beginners to start learning programming, and it's also a fun project for experienced programmers to work on. In this tutorial, we will show you how to create a Tic Tac Toe game in C++ using basic programming concepts such as arrays, loops, functions, and conditional statements. We will start with a simple console-based version of the game and gradually add more features to make it more interactive and user-friendly.

Planning and Designing the Game: Before starting to code, it's important to plan and design the game. Tic Tac Toe is a two-player game that involves placing X's and O's on a 3x3 grid to get three in a row. You should consider the following when planning and designing the game:

  • Decide on the user interface: You can create a console-based interface or use a graphics library such as SDL or SFML to create a graphical interface.
  • Determine the game rules: In Tic Tac Toe, the first player to get three of their symbols in a row wins. The row can be horizontal, vertical, or diagonal.
  • Decide on the game flow: The game should start by displaying the empty 3x3 grid. Each player should take turns placing their symbols on the grid until one player wins or the game ends in a tie.
  • Determine the user input: The user should be able to input the position where they want to place their symbol on the grid. This can be done through the keyboard or mouse if a graphical interface is used.

1. Setting up the Project: Once you have a plan and design for the game, you can set up the project. Create a new C++ project and add the necessary libraries for your chosen user interface.

  1. Creating the Game Board: The first step in creating the game is to create the game board. This can be done by creating a 3x3 array to represent the game board. Initialize the array to hold a default character, such as ' '.

 

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

  1. Displaying the Game Board: After creating the game board, you need to display it to the user. If you're using a console-based interface, you can use nested loops to iterate over the array and display each element. If you're using a graphical interface, you can use the library's functions to draw the grid and the symbols.
 

// Console-based interface void displayGameBoard() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { std::cout << gameBoard[i][j]; if (j < 2) { std::cout << "|"; } } std::cout << std::endl; if (i < 2) { std::cout << "-+-+-" << std::endl; } } } // Graphical interface // Use the library's functions to draw the grid and the symbols

  1. Getting User Input: Next, you need to get the user input for each player's turn. If you're using a console-based interface, you can prompt the user to enter the row and column where they want to place their symbol. If you're using a graphical interface, you can use the library's functions to detect the user's click on the grid.
 

// Console-based interface void getPlayerInput(char playerSymbol, int& row, int& col) { std::cout << "Player " << playerSymbol << "'s turn. Enter row (1-3): "; std::cin >> row; std::cout << "Enter column (1-3): "; std::cin >> col; // Subtract 1 from row and col to convert from 1-based to 0-based indexing row--; col--; } // Graphical interface // Use the library's functions to

...detect the user's click on the grid and convert it to the corresponding row and column.

  1. Updating the Game Board: After getting the user input, you need to update the game board with the player's symbol at the selected position. If the position is already occupied, you should prompt the user to enter a different position.
 

void updateGameBoard(char playerSymbol, int row, int col) { if (gameBoard[row][col] == ' ') { gameBoard[row][col] = playerSymbol; } else { std::cout << "Position already occupied. Enter a different position." << std::endl; int newRow, newCol; getPlayerInput(playerSymbol, newRow, newCol); updateGameBoard(playerSymbol, newRow, newCol); } }

  1. Checking for a Win: After updating the game board, you need to check if the current player has won the game. A player wins if they have three of their symbols in a row, either horizontally, vertically, or diagonally.
 

bool checkWin(char playerSymbol) { // Check rows for (int i = 0; i < 3; i++) { if (gameBoard[i][0] == playerSymbol && gameBoard[i][1] == playerSymbol && gameBoard[i][2] == playerSymbol) { return true; } } // Check columns for (int j = 0; j < 3; j++) { if (gameBoard[0][j] == playerSymbol && gameBoard[1][j] == playerSymbol && gameBoard[2][j] == playerSymbol) { return true; } } // Check diagonals if (gameBoard[0][0] == playerSymbol && gameBoard[1][1] == playerSymbol && gameBoard[2][2] == playerSymbol) { return true; } if (gameBoard[0][2] == playerSymbol && gameBoard[1][1] == playerSymbol && gameBoard[2][0] == playerSymbol) { return true; } return false; }

  1. Checking for a Tie: If neither player has won the game after all positions have been filled, the game ends in a tie.
 

bool checkTie() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gameBoard[i][j] == ' ') { return false; } } } return true; }

  1. Game Loop: After implementing the game logic, you can create a game loop that alternates between the two players and updates the game board until a win or a tie occurs.
 

void playGame() { char playerSymbol = 'X'; int row, col; bool gameOver = false; while (!gameOver) { displayGameBoard(); getPlayerInput(playerSymbol, row, col); updateGameBoard(playerSymbol, row, col); if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; gameOver = true; } else if (checkTie()) { std::cout << "Game over. It's a tie!" << std::endl; gameOver = true; } else { // Switch to the other player playerSymbol = (playerSymbol == 'X') ? 'O' : 'X'; } } }

  1. Running the Game: Finally, you can call the playGame() function from the main function to run the game.
 

int main() { playGame(); return 0; }

That's it! You have successfully created a Tic Tac Toe game in C++.

Full code:

#include <iostream> char gameBoard[3][3] = { {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '} }; void displayGameBoard() { std::cout << " 1 2 3" << std::endl; for (int i = 0; i < 3; i++) { std::cout << i+1 << " "; for (int j = 0; j < 3; j++) { std::cout << gameBoard[i][j] << ((j < 2) ? '|' : ' '); } if (i < 2) { std::cout << std::endl << " -----" << std::endl; } } std::cout << std::endl; } void getPlayerInput(char playerSymbol, int& row, int& col) { std::cout << "Player " << playerSymbol << "'s turn. Enter row and column numbers separated by a space: "; std::cin >> row >> col; row--; col--; } void updateGameBoard(char playerSymbol, int row, int col) { if (gameBoard[row][col] == ' ') { gameBoard[row][col] = playerSymbol; } else { std::cout << "Position already occupied. Enter a different position." << std::endl; int newRow, newCol; getPlayerInput(playerSymbol, newRow, newCol); updateGameBoard(playerSymbol, newRow, newCol); } } bool checkWin(char playerSymbol) { // Check rows for (int i = 0; i < 3; i++) { if (gameBoard[i][0] == playerSymbol && gameBoard[i][1] == playerSymbol && gameBoard[i][2] == playerSymbol) { return true; } } // Check columns for (int j = 0; j < 3; j++) { if (gameBoard[0][j] == playerSymbol && gameBoard[1][j] == playerSymbol && gameBoard[2][j] == playerSymbol) { return true; } } // Check diagonals if (gameBoard[0][0] == playerSymbol && gameBoard[1][1] == playerSymbol && gameBoard[2][2] == playerSymbol) { return true; } if (gameBoard[0][2] == playerSymbol && gameBoard[1][1] == playerSymbol && gameBoard[2][0] == playerSymbol) { return true; } return false; } bool checkTie() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (gameBoard[i][j] == ' ') { return false; } } } return true; } void playGame() { char playerSymbol = 'X'; int row, col; bool gameOver = false; while (!gameOver) { displayGameBoard(); getPlayerInput(playerSymbol, row, col); updateGameBoard(playerSymbol, row, col); if (checkWin(playerSymbol)) { std

 

std::cout << "Player " << playerSymbol << " wins!" << std::endl; gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } playerSymbol = (playerSymbol == 'X') ? 'O' : 'X'; } displayGameBoard();

}

int main() { playGame(); return 0; }

 

This is a basic implementation of Tic Tac Toe. You can further improve the game by adding features such as: - Keeping track of the score - Allowing players to choose their symbols - Adding a computer player as an opponent By adding more features, you can create a more challenging and engaging game.

  • Keeping track of the score: To keep track of the score, you can create a separate variable for each player to store their score. Then, you can update the score whenever a player wins a game. For example:
 

int playerXScore = 0; int playerOScore = 0; void playGame() { // ... while (!gameOver) { // ... if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; if (playerSymbol == 'X') { playerXScore++; } else { playerOScore++; } gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } // ... } // ... }

You can display the score after each game by adding the following lines of code to the playGame() function:

 

std::cout << "Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl;

  • Allowing players to choose their symbols: To allow players to choose their symbols, you can modify the getPlayerInput() function to prompt the player to enter their preferred symbol ('X' or 'O'). Then, you can pass the selected symbol to the playGame() function. For example:
 

void getPlayerInput(char& playerSymbol, int& row, int& col) { std::cout << "Enter your preferred symbol ('X' or 'O'): "; std::cin >> playerSymbol; std::cout << "Player " << playerSymbol << "'s turn. Enter row and column numbers separated by a space: "; std::cin >> row >> col; row--; col--; } void playGame() { char playerXSymbol, playerOSymbol; int row, col; bool gameOver = false; getPlayerInput(playerXSymbol, row, col); playerOSymbol = (playerXSymbol == 'X') ? 'O' : 'X'; char playerSymbol = playerXSymbol; // ... }

  • Adding a computer player as an opponent: To add a computer player as an opponent, you can create a separate function to generate random moves for the computer player. Then, you can modify the playGame() function to alternate between the human player and the computer player. For example:
 

void getComputerInput(char& playerSymbol, int& row, int& col) { row = rand() % 3; col = rand() % 3; while (gameBoard[row][col] != ' ') { row = rand() % 3; col = rand() % 3; } } void playGame() { char playerXSymbol, playerOSymbol; int row, col; bool gameOver = false; std::cout << "Enter your preferred symbol ('X' or 'O'): "; std::cin >> playerXSymbol; playerOSymbol = (playerXSymbol == 'X') ? 'O' : 'X'; char playerSymbol = playerXSymbol; while (!gameOver) { displayGameBoard(); if (playerSymbol == playerXSymbol) { getPlayerInput(playerSymbol, row, col); } else { getComputerInput(playerSymbol, row, col); std::cout << "Computer player chooses row " << row+1 << " and column " << col+1 << std::endl; } update

 

if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; if (playerSymbol == playerXSymbol) { playerXScore++; } else { playerOScore++; } gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } playerSymbol = (playerSymbol == playerXSymbol) ? playerOSymbol : playerXSymbol; } displayGameBoard(); std::cout << "Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl;

}

 

In this implementation, the computer player selects a random unoccupied cell on the game board. If the selected cell is already occupied, the computer player selects another cell randomly. You can further improve the computer player by adding strategies to make it more challenging to beat. These are just some examples of how you can extend the basic implementation of Tic Tac Toe in C++. With some creativity and programming skills, you can add even more features to create an engaging and enjoyable game.

to replay the game: To allow players to replay the game, you can add a loop to the main() function that prompts the player to choose whether they want to play again after the game is over. If the player chooses to play again, you can reset the game board and scores and start a new game. For example:

 

int main() { srand(time(NULL)); char choice = 'y'; while (choice == 'y' || choice == 'Y') { resetGameBoard(); int playerXScore = 0; int playerOScore = 0; playGame(playerXScore, playerOScore); std::cout << "Do you want to play again? (y/n) "; std::cin >> choice; } return 0; }

  • Adding a feature to save and load the game: To allow players to save and load the game, you can create a separate function to save the game board and scores to a file, and another function to load the saved data from the file. The save function can write the game board and scores to a text file, and the load function can read the data from the file and update the game board and scores. For example:
 

void saveGame(int playerXScore, int playerOScore) { std::ofstream file("saved_game.txt"); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { file << gameBoard[i][j]; if (j < 2) { file << " "; } } file << std::endl; } file << playerXScore << " " << playerOScore << std::endl; file.close(); } void loadGame(int& playerXScore, int& playerOScore) { std::ifstream file("saved_game.txt"); if (file.is_open()) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { file >> gameBoard[i][j]; } } file >> playerXScore >> playerOScore; file.close(); } }

You can then modify the playGame() function to prompt the player to choose whether they want to save or load the game before or after each turn. For example:

 

void playGame(int& playerXScore, int& playerOScore) { // ... char playerSymbol = playerXSymbol; bool gameOver = false; std::cout << "Enter your preferred symbol ('X' or 'O'): "; std::cin >> playerXSymbol; playerOSymbol = (playerXSymbol == 'X') ? 'O' : 'X'; while (!gameOver) { displayGameBoard(); std::cout << "Enter 's' to save game or 'l' to load game, or enter row and column numbers separated by a space: "; char choice; std::cin >> choice; if (choice == 's' || choice == 'S') { saveGame(playerXScore, playerOScore); } else if (choice == 'l' || choice == 'L') { loadGame(playerXScore, playerOScore); } else { if (playerSymbol == playerXSymbol) { getPlayerInput(playerSymbol, row, col); } else { getComputerInput(playerSymbol, row, col); std::cout << "Computer player chooses row " << row+1 <<

 

<< " and column " << col+1 << std::endl; } gameBoard[row][col] = playerSymbol; if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; if (playerSymbol == playerXSymbol) { playerXScore++; } else { playerOScore++; } gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } playerSymbol = (playerSymbol == playerXSymbol) ? playerOSymbol : playerXSymbol; } } displayGameBoard(); std::cout << "Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl;

}

 

With these additional features, your Tic Tac Toe game in C++ is now more complete and user-friendly. Of course, there are many other features you can add to enhance the game further, such as a graphical user interface, sound effects, and online multiplayer capabilities. However, this should give you a good starting point to build on and explore further.

  • Adding a feature to choose player symbols: By default, the game assigns 'X' to the human player and 'O' to the computer player. However, you can add a feature that allows the human player to choose their preferred symbol. This can be done by modifying the playGame() function to prompt the player to enter their preferred symbol before the game starts, and then assigning the other symbol to the computer player. For example:
 

void playGame(int& playerXScore, int& playerOScore) { // ... char playerSymbol = playerXSymbol; std::cout << "Enter your preferred symbol ('X' or 'O'): "; std::cin >> playerXSymbol; playerOSymbol = (playerXSymbol == 'X') ? 'O' : 'X'; bool gameOver = false; while (!gameOver) { displayGameBoard(); if (playerSymbol == playerXSymbol) { getPlayerInput(playerSymbol, row, col); } else { getComputerInput(playerSymbol, row, col); std::cout << "Computer player chooses row " << row+1 << " and column " << col+1 << std::endl; } gameBoard[row][col] = playerSymbol; if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; if (playerSymbol == playerXSymbol) { playerXScore++; } else { playerOScore++; } gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } playerSymbol = (playerSymbol == playerXSymbol) ? playerOSymbol : playerXSymbol; } displayGameBoard(); std::cout << "Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl; }

  • Adding a feature to keep track of scores: To keep track of the players' scores throughout multiple games, you can add two variables to the main() function to store the scores for player X and player O, respectively. These variables can then be passed to the playGame() function by reference so that they can be updated after each game. For example:
 

int main() { srand(time(NULL)); int playerXScore = 0; int playerOScore = 0; while (true) { resetGameBoard(); playGame(playerXScore, playerOScore); std::cout << "Do you want to play again? (y/n) "; char choice; std::cin >> choice; if (choice != 'y' && choice != 'Y') { break; } } std::cout << "Final Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl; return 0; }

  • Adding a feature to allow the player to quit the game: To allow the player to quit the game at any time, you can modify the getPlayerInput() function to accept a special input (such as -1 for both row and column) to indicate that the player wants to quit the game. You can then check for this input in the playGame() function and end the game if it is received. For example:
 

bool getPlayerInput(char symbol, int& row, int& col) { std::cout << "Enter row and column numbers separated by a space (or - daniel@jbinternational.co.uk

 

void playGame(int& playerXScore, int& playerOScore) { // ... bool gameOver = false; while (!gameOver) { displayGameBoard(); if (playerSymbol == playerXSymbol) { if (!getPlayerInput(playerSymbol, row, col)) { std::cout << "Player quit the game!" << std::endl; return; } } else { getComputerInput(playerSymbol, row, col); std::cout << "Computer player chooses row " << row+1 << " and column " << col+1 << std::endl; } gameBoard[row][col] = playerSymbol; if (checkWin(playerSymbol)) { std::cout << "Player " << playerSymbol << " wins!" << std::endl; if (playerSymbol == playerXSymbol) { playerXScore++; } else { playerOScore++; } gameOver = true; } else if (checkTie()) { std::cout << "Tie game!" << std::endl; gameOver = true; } playerSymbol = (playerSymbol == playerXSymbol) ? playerOSymbol : playerXSymbol; } displayGameBoard(); std::cout << "Score: " << "Player X: " << playerXScore << " Player O: " << playerOScore << std::endl; }

With these additional features, your Tic Tac Toe game in C++ is now more complete and user-friendly. Of course, there are many other features you can add to enhance the game further, such as a graphical user interface, sound effects, and online multiplayer capabilities. However, this should give you a good starting point to build on and explore further.

Conclusion:

Creating a Tic Tac Toe game in C++ is a fun and rewarding project for programmers of all levels. It's a great way to practice basic programming concepts and learn new skills while having fun. In this tutorial, we have shown you how to create a simple console-based version of the game and gradually added more features to make it more interactive and user-friendly. We hope you find this tutorial helpful and that it inspires you to explore more programming projects in the future.

JBI Training offers a number of courses to get you started in C++ or to advanced your knowledge. Our Training courses are taught by expert instructors. 

Resources for C++:

  1. C++ documentation on cppreference.com: https://en.cppreference.com/w/cpp This website provides a comprehensive reference for the C++ language and its standard library. It includes detailed documentation on C++ syntax, data types, functions, algorithms, and more.

  2. C++ documentation on Microsoft Docs: https://docs.microsoft.com/en-us/cpp/ This website provides documentation and tutorials for C++ development with Microsoft Visual Studio. It covers topics such as language features, programming techniques, debugging, and optimization.

  3. C++ documentation on GNU.org: https://gcc.gnu.org/onlinedocs/ This website provides documentation for the GNU Compiler Collection (GCC), which is a popular compiler for C++ and other programming languages. It includes detailed information on C++ language features and library functions.

  4. C++ Standard documentation on ISO.org: https://www.iso.org/standard/79358.html This website provides the official documentation for the C++ language standard, which is developed and maintained by the International Organization for Standardization (ISO). It includes the technical specifications for the language and its library functions.

  5. C++ documentation on the C++ Foundation: https://isocpp.org/ The C++ Foundation is a non-profit organization that promotes the use and development of the C++ language. Their website includes a variety of resources for C++ programmers, including tutorials, articles, and news updates.

 

About the author: Daniel West
Tech Blogger & Researcher for JBI Training

CONTACT
+44 (0)20 8446 7555

[email protected]

SHARE

 

Copyright © 2023 JBI Training. All Rights Reserved.
JB International Training Ltd  -  Company Registration Number: 08458005
Registered Address: Wohl Enterprise Hub, 2B Redbourne Avenue, London, N3 2BS

Modern Slavery Statement & Corporate Policies | Terms & Conditions | Contact Us

POPULAR

Rust training course                                                                          React training course

Threat modelling training course   Python for data analysts training course

Power BI training course                                   Machine Learning training course

Spring Boot Microservices training course              Terraform training course

Kubernetes training course                                                            C++ training course

Power Automate training course                               Clean Code training course