Validity of a given Tic-Tac-Toe board configuration

Last Updated : 21 Jul, 2026

A Tic-Tac-Toe board of size 3X3 is given after all the moves are played, i.e., all nine spots are filled. Find out if the given board is valid, i.e., is it possible to reach this board position after a set of moves or not.
Note that every arbitrarily filled grid of 9 spaces isn’t valid, e.g., a grid filled with 3 X and 6 O isn’t a valid situation because each player needs to take alternate turns.

Note:  The game starts with X.

tictactoe

Input:
board[] = {'X', 'X', 'O',
'O', 'O', 'X',
'X', 'O', 'X'};
Output: Valid
Explanation: This is a valid board.

Input:
board[] = {'O', 'X', 'X',
'O', 'X', 'X',
'O', 'O', 'X'};
Output: Invalid
Explanation: Both X and O cannot win.

Try It Yourself
redirect icon

Count Moves and Check Winning Configurations - O(1) Time and O(1) Space

The idea is to first count the number of X and O moves to ensure the move sequence is valid. Then, check all eight possible winning lines for both players. Since the board is completely filled and X always starts, the board is valid only if:

  • X = O + 1
  • Both players do not win simultaneously.
  • If O wins, it must be the only winner.
  • If X wins, it must also be the only winner.
  • If no one wins, the board is also valid.

Working of Approach:

  • Count the number of 'X' and 'O' on the board and ensure that X has exactly one more move than O, since the board is completely filled and X always starts.
  • Check all 8 possible winning combinations and count how many winning lines are formed by X and O.
  • If only X has one winning line, or only O has one winning line, the board is valid according to the move count.
  • If neither player has a winning line, the board is also valid.
  • Otherwise (both players win or any invalid configuration), return false.

Let us understand with an example:
Input: board[] = {'X', 'X', 'O', 'O', 'O', 'X', 'X', 'O', 'X'};

  • Count the symbols on the board: xCount = 5 and oCount = 4. Since xCount = oCount + 1, the move count is valid.
  • Check all 8 possible winning combinations for X. No winning line is found, so cx = 0.
  • Check all 8 possible winning combinations for O. No winning line is found, so co = 0.
  • Since neither player has a winning line (cx = 0 and co = 0), the condition !co && !cx becomes true.
  • Therefore, the function returns true, and the output is "Valid".
C++
#include <iostream>
using namespace std;

// This matrix stores all possible winning
// combinations in Tic-Tac-Toe.
int win[8][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, {0, 4, 8}, {2, 4, 6}};

// Returns the number of winning combinations
// formed by the given player.
int isCWin(char *board, char c)
{

    int cnt = 0;

    // Check all possible winning combinations
    for (int i = 0; i < 8; i++)
    {
        if (board[win[i][0]] == c && board[win[i][1]] == c && board[win[i][2]] == c)
            cnt++;
    }

    return cnt;
}

bool isValid(char board[9])
{

    int xCount = 0, oCount = 0;

    // Count the number of X's and O's
    for (int i = 0; i < 9; i++)
    {
        if (board[i] == 'X')
            xCount++;
        else if (board[i] == 'O')
            oCount++;
    }

    int cx = isCWin(board, 'X');
    int co = isCWin(board, 'O');

    // X always plays first, so X must have
    // exactly one more move than O.
    if (xCount != oCount + 1)
        return false;

    // Only O wins
    if (cx == 0 && co == 1)
        return true;

    // Only X wins
    if (co == 0 && cx == 1)
        return true;

    // No player wins
    if (cx == 0 && co == 0)
        return true;

    return false;
}

int main()
{

    char board[9] = {'X', 'X', 'O', 'O', 'O', 'X', 'X', 'O', 'X'};

    if (isValid(board))
        cout << "Valid";
    else
        cout << "Invalid";

    return 0;
}
Java
public class GFG {
    // This matrix stores all possible winning
    // combinations in Tic-Tac-Toe.
    static int[][] win
        = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
            { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 },
            { 0, 4, 8 }, { 2, 4, 6 } };

    // Returns the number of winning combinations
    // formed by the given player.
    static int isCWin(char[] board, char c)
    {
        int cnt = 0;

        // Check all possible winning combinations
        for (int i = 0; i < 8; i++) {
            if (board[win[i][0]] == c
                && board[win[i][1]] == c
                && board[win[i][2]] == c)
                cnt++;
        }

        return cnt;
    }

    static boolean isValid(char[] board)
    {
        int xCount = 0, oCount = 0;

        // Count the number of X's and O's
        for (int i = 0; i < 9; i++) {
            if (board[i] == 'X')
                xCount++;
            else if (board[i] == 'O')
                oCount++;
        }

        int cx = isCWin(board, 'X');
        int co = isCWin(board, 'O');

        // X always plays first, so X must have
        // exactly one more move than O.
        if (xCount != oCount + 1)
            return false;

        // Only O wins
        if (cx == 0 && co == 1)
            return true;

        // Only X wins
        if (co == 0 && cx == 1)
            return true;

        // No player wins
        if (cx == 0 && co == 0)
            return true;

        return false;
    }

    public static void main(String[] args)
    {
        char[] board = { 'X', 'X', 'O', 'O', 'O',
                         'X', 'X', 'O', 'X' };

        if (isValid(board))
            System.out.println("Valid");
        else
            System.out.println("Invalid");
    }
}
Python
# Returns the number of winning combinations
# formed by the given player.
def isCWin(board, c):
    win = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
    cnt = 0

    # Check all possible winning combinations
    for i in range(8):
        if board[win[i][0]] == c and board[win[i][1]] == c and board[win[i][2]] == c:
            cnt += 1

    return cnt

def isValid(board):
    xCount = 0
    oCount = 0

    # Count the number of X's and O's
    for i in range(9):
        if board[i] == 'X':
            xCount += 1
        elif board[i] == 'O':
            oCount += 1

    cx = isCWin(board, 'X')
    co = isCWin(board, 'O')

    # X always plays first, so X must have
    # exactly one more move than O.
    if xCount!= oCount + 1:
        return False

    # Only O wins
    if cx == 0 and co == 1:
        return True

    # Only X wins
    if co == 0 and cx == 1:
        return True

    # No player wins
    if cx == 0 and co == 0:
        return True

    return False

if __name__ == '__main__':
    board = ['X', 'X', 'O', 'O', 'O', 'X', 'X', 'O', 'X']

    if isValid(board):
        print('Valid')
    else:
        print('Invalid')
C#
using System;

class GFG {
    // This matrix stores all possible winning
    // combinations in Tic-Tac-Toe.
    static int[, ] win
        = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
            { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 },
            { 0, 4, 8 }, { 2, 4, 6 } };

    // Returns the number of winning combinations
    // formed by the given player.
    static int isCWin(char[] board, char c)
    {
        int cnt = 0;

        // Check all possible winning combinations
        for (int i = 0; i < 8; i++) {
            if (board[win[i, 0]] == c
                && board[win[i, 1]] == c
                && board[win[i, 2]] == c)
                cnt++;
        }

        return cnt;
    }

    static bool isValid(char[] board)
    {
        int xCount = 0, oCount = 0;

        // Count the number of X's and O's
        for (int i = 0; i < 9; i++) {
            if (board[i] == 'X')
                xCount++;
            else if (board[i] == 'O')
                oCount++;
        }

        int cx = isCWin(board, 'X');
        int co = isCWin(board, 'O');

        // X always plays first, so X must have
        // exactly one more move than O.
        if (xCount != oCount + 1)
            return false;

        // Only O wins
        if (cx == 0 && co == 1)
            return true;

        // Only X wins
        if (co == 0 && cx == 1)
            return true;

        // No player wins
        if (cx == 0 && co == 0)
            return true;

        return false;
    }

    static void Main(string[] args)
    {
        char[] board = { 'X', 'X', 'O', 'O', 'O',
                         'X', 'X', 'O', 'X' };

        if (isValid(board))
            Console.WriteLine("Valid");
        else
            Console.WriteLine("Invalid");
    }
}
JavaScript
// Returns the number of winning combinations
// formed by the given player.
function isCWin(board, c)
{
    const win = [
        [ 0, 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8 ], [ 0, 3, 6 ],
        [ 1, 4, 7 ], [ 2, 5, 8 ], [ 0, 4, 8 ], [ 2, 4, 6 ]
    ];
    let cnt = 0;

    // Check all possible winning combinations
    for (let i = 0; i < 8; i++) {
        if (board[win[i][0]] === c && board[win[i][1]] === c
            && board[win[i][2]] === c)
            cnt++;
    }

    return cnt;
}

function isValid(board)
{
    let xCount = 0, oCount = 0;

    // Count the number of X's and O's
    for (let i = 0; i < 9; i++) {
        if (board[i] === "X")
            xCount++;
        else if (board[i] === "O")
            oCount++;
    }

    const cx = isCWin(board, "X");
    const co = isCWin(board, "O");

    // X always plays first, so X must have
    // exactly one more move than O.
    if (xCount !== oCount + 1)
        return false;

    // Only O wins
    if (cx === 0 && co === 1)
        return true;

    // Only X wins
    if (co === 0 && cx === 1)
        return true;

    // No player wins
    if (cx === 0 && co === 0)
        return true;

    return false;
}

// Driver Code
const board =
    [ "X", "X", "O", "O", "O", "X", "X", "O", "X" ];

if (isValid(board))
    console.log("Valid");
else
    console.log("Invalid");

Output
Valid
Comment