Tic Tac Toe Game in C (original) (raw)

Last Updated : 23 Jul, 2025

Tic Tac Toe is a game that was popularly played on paper or pen using the board. This is a fun game played by people of all ages. But now the digital version is becoming popular to have fun on the same game with friends. In this article, we will learn to write a program that allows a person to play tic tac toe against the computer.

Tic-Tac-Toe-Game-in-C

Components of Tic Tac Toe Game

The working of tic tac toe game is same as traditional tic tac toe having following components:

Note: The program uses the algorithm discussed here to find the best possible move for the computer to make the game competitive.

Implementation of Tic-Tac-Toe Game

C `

#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define COMPUTER 1 #define HUMAN 2 #define SIDE 3 #define COMPUTERMOVE 'O' #define HUMANMOVE 'X'

// ---------------- Intelligent Moves start

struct Move { int row, col; };

char player = 'x', opponent = 'o';

// This function returns true if there are moves // remaining on the board. It returns false if // there are no moves left to play. bool isMovesLeft(char board[3][3]) { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (board[i][j] == '_') return true; return false; }

// This is the evaluation function int evaluate(char b[3][3]) { // Checking for Rows for X or O victory. for (int row = 0; row < 3; row++) { if (b[row][0] == b[row][1] && b[row][1] == b[row][2]) { if (b[row][0] == player) return +10; else if (b[row][0] == opponent) return -10; } }

// Checking for Columns for X or O victory.
for (int col = 0; col < 3; col++) {
    if (b[0][col] == b[1][col]
        && b[1][col] == b[2][col]) {
        if (b[0][col] == player)
            return +10;

        else if (b[0][col] == opponent)
            return -10;
    }
}

// Checking for Diagonals for X or O victory.
if (b[0][0] == b[1][1] && b[1][1] == b[2][2]) {
    if (b[0][0] == player)
        return +10;
    else if (b[0][0] == opponent)
        return -10;
}

if (b[0][2] == b[1][1] && b[1][1] == b[2][0]) {
    if (b[0][2] == player)
        return +10;
    else if (b[0][2] == opponent)
        return -10;
}

// Else if none of them have won then return 0
return 0;

}

// This is the minimax function. It considers all // the possible ways the game can go and returns // the value of the board int minimax(char board[3][3], int depth, bool isMax) { int score = evaluate(board);

// If Maximizer has won the game return his/her
// evaluated score
if (score == 10)
    return score;

// If Minimizer has won the game return his/her
// evaluated score
if (score == -10)
    return score;

// If there are no more moves and no winner then
// it is a tie
if (isMovesLeft(board) == false)
    return 0;

// If this maximizer's move
if (isMax) {
    int best = -1000;

    // Traverse all cells
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            // Check if cell is empty
            if (board[i][j] == '_') {
                // Make the move
                board[i][j] = player;
                int val
                    = minimax(board, depth + 1, !isMax);
                if (val > best) {
                    best = val;
                }

                // Undo the move
                board[i][j] = '_';
            }
        }
    }
    return best;
}

// If this minimizer's move
else {
    int best = 1000;

    // Traverse all cells
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            // Check if cell is empty
            if (board[i][j] == '_') {
                // Make the move
                board[i][j] = opponent;

                // Call minimax recursively and choose
                int val
                    = minimax(board, depth + 1, !isMax);
                if (val < best) {
                    best = val;
                }
                // Undo the move
                board[i][j] = '_';
            }
        }
    }
    return best;
}

}

// This will return the best possible move for the player struct Move findBestMove(char board[3][3]) { int bestVal = -1000; struct Move bestMove; bestMove.row = -1; bestMove.col = -1;

// Traverse all cells, evaluate minimax function for
// all empty cells. And return the cell with optimal
// value.
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        // Check if cell is empty
        if (board[i][j] == '_') {
            // Make the move
            board[i][j] = player;

            // compute evaluation function for this
            // move.
            int moveVal = minimax(board, 0, false);

            // Undo the move
            board[i][j] = '_';

            // If the value of the current move is
            // more than the best value, then update
            // best/
            if (moveVal > bestVal) {
                bestMove.row = i;
                bestMove.col = j;
                bestVal = moveVal;
            }
        }
    }
}

// printf("The value of the best Move is : %d\n\n",
//       bestVal);

return bestMove;

}

// -----------------------------------Intelligent Moves end

// Function to display the game board void showBoard(char board[][SIDE]) { printf("\n\n"); printf("\t\t\t %c | %c | %c \n", board[0][0], board[0][1], board[0][2]); printf("\t\t\t--------------\n"); printf("\t\t\t %c | %c | %c \n", board[1][0], board[1][1], board[1][2]); printf("\t\t\t--------------\n"); printf("\t\t\t %c | %c | %c \n\n", board[2][0], board[2][1], board[2][2]); }

// Function to show the instructions void showInstructions() { printf("\t\t\t Tic-Tac-Toe\n\n"); printf("Choose a cell numbered from 1 to 9 as below " "and play\n\n");

printf("\t\t\t 1 | 2 | 3 \n");
printf("\t\t\t--------------\n");
printf("\t\t\t 4 | 5 | 6 \n");
printf("\t\t\t--------------\n");
printf("\t\t\t 7 | 8 | 9 \n\n");

printf("-\t-\t-\t-\t-\t-\t-\t-\t-\t-\n\n");

}

// Function to initialise the game void initialise(char board[][SIDE], int moves[]) { srand(time(NULL));

// Initially, the board is empty
for (int i = 0; i < SIDE; i++) {
    for (int j = 0; j < SIDE; j++)
        board[i][j] = ' ';
}

// Fill the moves with numbers
for (int i = 0; i < SIDE * SIDE; i++)
    moves[i] = i;

// Randomize the moves
for (int i = 0; i < SIDE * SIDE; i++) {
    int randIndex = rand() % (SIDE * SIDE);
    int temp = moves[i];
    moves[i] = moves[randIndex];
    moves[randIndex] = temp;
}

}

// Function to declare the winner of the game void declareWinner(int whoseTurn) { if (whoseTurn == COMPUTER) printf("COMPUTER has won\n"); else printf("HUMAN has won\n"); }

// Function to check if any row is crossed with the same // player's move int rowCrossed(char board[][SIDE]) { for (int i = 0; i < SIDE; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') return 1; } return 0; }

// Function to check if any column is crossed with the same // player's move int columnCrossed(char board[][SIDE]) { for (int i = 0; i < SIDE; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ') return 1; } return 0; }

// Function to check if any diagonal is crossed with the // same player's move int diagonalCrossed(char board[][SIDE]) { if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ') || (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')) return 1;

return 0;

}

// Function to check if the game is over int gameOver(char board[][SIDE]) { return (rowCrossed(board) || columnCrossed(board) || diagonalCrossed(board)); }

// Function to play Tic-Tac-Toe void playTicTacToe(int whoseTurn) { // A 3*3 Tic-Tac-Toe board for playing char board[SIDE][SIDE]; int moves[SIDE * SIDE];

// Initialise the game
initialise(board, moves);

// Show the instructions before playing
showInstructions();

int moveIndex = 0, x, y;

// Keep playing until the game is over or it is a draw
while (!gameOver(board) && moveIndex != SIDE * SIDE) {
    if (whoseTurn == COMPUTER) {

        char tempBoard[3][3];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] == 'X') {
                    tempBoard[i][j] = 'x';
                }
                else if (board[i][j] == 'O') {
                    tempBoard[i][j] = 'o';
                }
                else {
                    tempBoard[i][j] = '_';
                }
            }
        }
        struct Move thisMove = findBestMove(tempBoard);
        x = thisMove.row;
        y = thisMove.col;

        board[x][y] = COMPUTERMOVE;
        printf("COMPUTER has put a %c in cell %d %d\n",
               COMPUTERMOVE, x, y);
        showBoard(board);
        moveIndex++;
        whoseTurn = HUMAN;
    }
    else if (whoseTurn == HUMAN) {
        int move;
        printf("Enter your move (1-9): ");
        scanf("%d", &move);
        if (move < 1 || move > 9) {
            printf("Invalid input! Please enter a "
                   "number between 1 and 9.\n");
            continue;
        }
        x = (move - 1) / SIDE;
        y = (move - 1) % SIDE;
        if (board[x][y] == ' ') {
            board[x][y] = HUMANMOVE;
            showBoard(board);
            moveIndex++;
            if (gameOver(board)) {
                declareWinner(HUMAN);
                return;
            }
            whoseTurn = COMPUTER;
        }
        else {
            printf("Cell %d is already occupied. Try "
                   "again.\n",
                   move);
        }
    }
}

// If the game has drawn
if (!gameOver(board) && moveIndex == SIDE * SIDE)
    printf("It's a draw\n");
else {
    // Toggling the user to declare the actual winner
    if (whoseTurn == COMPUTER)
        whoseTurn = HUMAN;
    else if (whoseTurn == HUMAN)
        whoseTurn = COMPUTER;

    // Declare the winner
    declareWinner(whoseTurn);
}

}

// Driver program int main() { // Let us play the game with COMPUTER starting first playTicTacToe(COMPUTER);

return 0;

}

`

Output

                     Tic-Tac-Toe

Choose a cell numbered from 1 to 9 as below and play 1 | 2 | 3 -------------- 4 | 5 | 6 -------------- 7 | 8 | 9


COMPUTER has put a O in cell 0 0 O | |
-------------- | |
-------------- | |
Enter your move (1-9): 9 O | |
-------------- | |
-------------- | | X COMPUTER has put a O in cell 0 2 O | | O -------------- | |
-------------- | | X Enter your move (1-9): 2 O | X | O -------------- | |
-------------- | | X COMPUTER has put a O in cell 2 1 O | X | O -------------- | |
-------------- | O | X Enter your move (1-9): 5 O | X | O -------------- | X |
-------------- | O | X COMPUTER has put a O in cell 1 0 O | X | O -------------- O | X |
-------------- | O | X Enter your move (1-9): 6 O | X | O -------------- O | X | X -------------- | O | X COMPUTER has put a O in cell 2 0 O | X | O -------------- O | X | X -------------- O | O | X COMPUTER has won

Functions that are used in above code:

Overall, this program implements a simple single-player Tic tac Toe game with input validation, user interface, winning logic and the game continues until there is a winner or draw.

If you want to implement Tic-Tac-Toe using Java, and Javascript, refer to the articles: