Building an Unbeatable Tic-Tac-Toe AI with the Minimax Algorithm

Tic-Tac-Toe may seem like a simple game, but did you know that it's actually a great way to dive into the world of AI and algorithms? Today, I'll walk you through how I built a Python-based Tic-Tac-Toe AI that is unbeatable, thanks to the power of the Minimax algorithm.

By the end of this post, you’ll understand how this algorithm works, why it's unbeatable in a game like Tic-Tac-Toe, and how you can set it up yourself!


Getting Started: The Game of Tic-Tac-Toe

Tic-Tac-Toe is a two-player game where each player takes turns marking an empty cell on a 3x3 grid with either an "X" or an "O". The objective is simple: get three of your marks in a row—horizontally, vertically, or diagonally.

For this project, I used Python to create a text-based Tic-Tac-Toe game where you, the human, can play against an AI that is practically impossible to beat!


Setting Up the Project

To get started with this project, all you need is Python and a terminal (I'm using Ubuntu 22.04 on WSL2, but any Linux or Mac environment works).

Step-by-Step Setup

  1. Create the project directory:

     mkdir tictactoe-ai
     cd tictactoe-ai
    
  2. Set up a Python virtual environment:

     python3 -m venv .venv
     source .venv/bin/activate
    
  3. Install dependencies: This project doesn't need many external libraries, but if you'd like to visualize or experiment with the code interactively, you can install Jupyter:

     pip install jupyter
    

How the AI Works

The key to making this Tic-Tac-Toe AI unbeatable lies in the Minimax algorithm, which evaluates all possible game states and ensures the AI picks the optimal move at every turn.

The Minimax Algorithm

At its core, the Minimax algorithm is a recursive method used in game theory to determine the best possible move for a player. It works by maximizing the chances of success for the current player and minimizing the chances of success for the opponent.

Here’s how it breaks down:

  1. Simulate all possible moves: The AI looks at all available moves, "plays" each one, and recursively looks at how the game would progress if it made that move.

  2. Assign scores to game states: Each game state (win, lose, or draw) is assigned a score:

    • +1 for a win for the AI (player "O").

    • -1 for a loss (a win for the human, player "X").

    • 0 for a draw.

  3. Backtrack and select the optimal move: After simulating the entire game tree, the AI chooses the move with the best possible outcome for itself, assuming the opponent is also playing optimally.

Why Minimax is Unbeatable in Tic-Tac-Toe

In a game like Tic-Tac-Toe, the game tree is relatively small compared to more complex games like chess or Go. This means that the AI can evaluate every possible move and its subsequent outcomes in a short time.

  • Full-game analysis: Since Tic-Tac-Toe has a finite number of game states, the Minimax algorithm is able to explore every possible sequence of moves.

  • Perfect decision-making: Given that the AI can evaluate all possible future game states, it will always choose the best move. This makes it unbeatable when both players play optimally.

  • Forced draw: If you also play optimally, the game will always end in a draw. The AI will never make a mistake that leads to a loss.

This means that unless you intentionally make a mistake, you won’t win against the AI. But if you do, the AI will exploit that mistake and win.


Implementing the Minimax Algorithm

Here’s a simplified version of how the Minimax algorithm works in Python.

def minimax(player):
    opponent = 'O' if player == 'X' else 'X'

    # Base case: check if game is won, lost, or drawn
    if check_win('O'):
        return {'position': None, 'score': 1}
    elif check_win('X'):
        return {'position': None, 'score': -1}
    elif check_draw():
        return {'position': None, 'score': 0}

    moves = []

    # Loop through all available spaces
    for i in range(9):
        if board[i] == ' ':
            # Try the move
            board[i] = player
            move = {}
            move['position'] = i

            # Recursively call minimax for the opponent
            if player == 'O':
                result = minimax('X')
                move['score'] = result['score']
            else:
                result = minimax('O')
                move['score'] = result['score']

            # Undo the move
            board[i] = ' '

            # Add move to list of possible moves
            moves.append(move)

    # Return the best move depending on whether the AI is maximizing or minimizing
    if player == 'O':
        best_move = max(moves, key=lambda x: x['score'])
    else:
        best_move = min(moves, key=lambda x: x['score'])

    return best_move

Explaining the Code

  • Base case: The function checks whether the game is over (win, lose, or draw). If the game is over, it assigns a score and returns.

  • Recursive case: The AI simulates each possible move and evaluates the resulting game state using recursion.

  • Maximizing/Minimizing: The AI maximizes its score when it's its turn (player "O") and minimizes the opponent's score (player "X"), ensuring optimal decisions.


Why Use the Minimax Algorithm?

The Minimax algorithm is a great introduction to game AI because:

  1. It's guaranteed to find the optimal strategy: In games with perfect information like Tic-Tac-Toe, it will always find the best move.

  2. It’s simple but effective: The basic structure of the algorithm is easy to understand but has powerful applications in AI.

  3. It’s unbeatable: As we've discussed, this algorithm ensures the AI never loses when both players play optimally.


Setting up and Running the Game

After implementing the algorithm, you can run the game and play against the AI. Here’s how to get started:

  1. Run the game:

     python3 tictactoe.py
    
  2. Make your move by selecting a position (1-9), and the AI will respond instantly with its move.

You’ll find it difficult to win against this AI, and unless you play perfectly, the AI will exploit any mistakes you make!


Conclusion

Building a Tic-Tac-Toe AI with the Minimax algorithm is a fun and educational project. It showcases how you can use recursion and game theory to create an intelligent AI that plays optimally. While Tic-Tac-Toe may be a simple game, the same principles apply to more complex games and decision-making systems.

Want to try it out? Feel free to clone the repo and start playing against an unbeatable AI!

Happy coding!


Resources


I hope this gives you an idea of how powerful algorithms like Minimax can be in creating intelligent systems—even for simple games like Tic-Tac-Toe. If you have any questions or suggestions, drop a comment below!