In this article, we will learn how to develop a tic-tac-toe game in C++. Tic-tac-toe is a game played between two players usually with paper and pencil but here, we will create a C++ program that will display the game on the console screen and players can use different keys from the keyboard to play it.

Before we start, let's understand some rules to play the game:
Rules of Tic-Tac-Toe
Following are the rules that define how to play the tic tac toe game:
- A player can put only a single letter X or O in the 3 x 3 grid in each chance.
- Both players will get chances alternatively one after another till someone wins or draws.
- To win this game, the player must create a horizontal, vertical, or diagonal line consisting of three same letters.
- The game is drawn, if all grids are filled with X or O letters but no line is made.
Feature of Tic-Tac-Toe in C++
This game provides the following features:
- This game is developed on a 3x3 grid.
- This game is designed for two players.
- Every player may choose a letter between X and O.
- Both players will get their chances to turn by turn.
Components of the Game
The game is made of the following components that include the functions and data structures to provide the basic operations of the game.
1. Game Board
The game board is managed by the Board class which contains:
- A 3x3 character grid to represent the board.
- A counter to track filled cells.
2. Player Management
Players are represented by the Player class which stores:
- The player's symbol (X or O)
- The player's name
3. Movement Of Player
The Board
class includes methods to handle player moves:
drawBoard()
to display the current state of the boardisValidMove()
to check if a move is validmakeMove()
to update the board with a player's move
How to check if the input is valid or not?
- Valid input: If the cell is empty and is within the boundary (0-2 for internal tracking, 1-3 for user input)
- Invalid input: If the cell has already been filled with another letter or is outside the bounds
4. Game Logic
The TicTacToe class manages the overall game logic:
- Handles player turns
- Processes user input
- Checks for win/draw conditions
5. Win, Lose or Draw
The Board class includes methods to check game status:
- checkWin() to determine if a player has won
- isFull() to check if the board is full (a draw)
The draw condition is checked in the play() method of the TicTacToe class when the board is full and no player has won.
C++ Program for Tic Tac Toe Game
Below is the complete code for a basic console-based Tic-Tac-Toe game in C++:
C++
#include <iostream>
#include <string>
using namespace std;
// Player class to represent a player in game
class Player {
private:
char symbol;
string name;
public:
// Constructor
Player(char sym = 'X', string n = "Player X") : symbol(sym), name(n) {}
// Getter methods
char getSymbol() const { return symbol; }
string getName() const { return name; }
};
// Board class to manage game board
class Board {
private:
char grid[3][3];
int filledCells; // Counter for filled cells
public:
// Constructor to initialize the board
Board() : filledCells(0) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
grid[i][j] = ' ';
}
}
}
// Method to display the board
void drawBoard() const {
cout << "-------------" << endl;
for (int i = 0; i < 3; i++) {
cout << "| ";
for (int j = 0; j < 3; j++) {
cout << grid[i][j] << " | ";
}
cout << endl << "-------------" << endl;
}
}
// Method to check if a move is valid
bool isValidMove(int row, int col) const {
return (row >= 0 && row < 3 && col >= 0 && col < 3 && grid[row][col] == ' ');
}
// Method to make a move
void makeMove(int row, int col, char symbol) {
if (isValidMove(row, col)) {
grid[row][col] = symbol;
filledCells++; // Increment counter when a cell is filled
}
}
// Method to check for a win
bool checkWin(char symbol) const {
// Check rows
for (int i = 0; i < 3; i++) {
if (grid[i][0] == symbol && grid[i][1] == symbol && grid[i][2] == symbol) {
return true;
}
}
// Check columns
for (int i = 0; i < 3; i++) {
if (grid[0][i] == symbol && grid[1][i] == symbol && grid[2][i] == symbol) {
return true;
}
}
// Check diagonals
if (grid[0][0] == symbol && grid[1][1] == symbol && grid[2][2] == symbol) {
return true;
}
if (grid[0][2] == symbol && grid[1][1] == symbol && grid[2][0] == symbol) {
return true;
}
return false;
}
// Method to check if board is full using the counter
bool isFull() const {
return filledCells == 9;
}
// Method to get the number of filled cells
int getFilledCellsCount() const {
return filledCells;
}
};
// Game class to manage the game logic
class TicTacToe {
private:
Board board;
Player players[2];
int currentPlayerIndex;
public:
// Constructor
TicTacToe() : currentPlayerIndex(0) {
players[0] = Player('X', "Player X");
players[1] = Player('O', "Player O");
}
// Method to get the current player
Player& getCurrentPlayer() {
return players[currentPlayerIndex];
}
// Method to switch turns
void switchTurn() {
currentPlayerIndex = (currentPlayerIndex + 1) % 2;
}
// Method to play the game
void play() {
int row, col;
cout << "Welcome to Tic-Tac-Toe!" << endl;
while (!board.isFull()) {
// Display the board
board.drawBoard();
Player& currentPlayer = getCurrentPlayer();
// Get valid input
while (true) {
cout << currentPlayer.getName() << " (" << currentPlayer.getSymbol()
<< "), enter row (1-3) and column (1-3): ";
cin >> row >> col;
row--; col--; // Convert to 0-indexed
if (board.isValidMove(row, col)) {
break;
} else {
cout << "Invalid move. Try again." << endl;
}
}
// Make move
board.makeMove(row, col, currentPlayer.getSymbol());
// Check for win
if (board.checkWin(currentPlayer.getSymbol())) {
board.drawBoard();
cout << currentPlayer.getName() << " wins!" << endl;
return;
}
// Switch turns
switchTurn();
}
// Game ended in a draw
board.drawBoard();
cout << "It's a draw!" << endl;
}
};
int main() {
// Creating game object
TicTacToe game;
// Starting the game
game.play();
return 0;
}
Output
Welcome to Tic-Tac-Toe!
-------------
| | | |
-------------
| | | |
-------------
| | | |
-------------
Player X (X), enter row (1-3) and column (1-3): 2 2
-------------
| | | |
-------------
| | X | |
-------------
| | | |
-------------
Player O (O), enter row (1-3) and column (1-3): 1 1
-------------
| O | | |
-------------
| | X | |
-------------
| | | |
-------------
Player X (X), enter row (1-3) and column (1-3): 3 1
-------------
| O | | |
-------------
| | X | |
-------------
| X | | |
-------------
Player O (O), enter row (1-3) and column (1-3): 1 3
-------------
| O | | O |
-------------
| | X | |
-------------
| X | | |
-------------
Player X (X), enter row (1-3) and column (1-3): 3 3
-------------
| O | | O |
-------------
| | X | |
-------------
| X | | X |
-------------
Player O (O), enter row (1-3) and column (1-3): 1 2
-------------
| O | O | O |
-------------
| | X | |
-------------
| X | | X |
-------------
Player O wins!