← Back

Program 6: Implement the Minimax search algorithm for 2-player games. You may use a game tree with 3 plies.

Simple Python Code
# --- Global Constants ---
HUMAN = -1
COMPUTER = 1
EMPTY = 0

def display_board(board):
    #Prints the current Tic-Tac-Toe board.
    print("\nCurrent Board:")
    for i in range(9):
        # Add a newline before rows 2 and 3
        if i > 0 and i % 3 == 0:
            print()
            # Print horizontal separators
            print("-" * 11)

        cell = board[i]
        symbol = " "
        if cell == HUMAN:
            symbol = "X"
        elif cell == COMPUTER:
            symbol = "O"

        # Print cell content with padding
        print(f" {symbol} ", end="")

        # Print vertical separator between columns
        if (i + 1) % 3 != 0:
            print("|", end="")
    print("\n")


def player_x_turn(board):
    #Handles the human player's move (X). Validates input.
    while True:
        try:
            position = int(input("Enter your move (1-9): "))
            index = position - 1

            if position < 1 or position > 9:
                print("Please enter a number between 1 and 9.")
                continue
            if board[index] != EMPTY:
                print("Cell already taken. Try another.")
                continue

            board[index] = HUMAN
            break
        except ValueError:
            print("Invalid input. Please enter a number between 1 and 9.")


def check_winner(board):
    """Checks for a winner.
    Returns:
        1 if Computer (O) wins
       -1 if Human (X) wins
        0 if no winner yet (or draw)
    """
    wins = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
        [0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
        [0, 4, 8], [2, 4, 6]             # Diagonals
    ]
    for combo in wins:
        a, b, c = combo
        if board[a] != EMPTY and board[a] == board[b] == board[c]:
            return board[a]
    return 0


def minimax(board, player):
    """
    The recursive Minimax algorithm.
    It searches the entire game tree from the current state to find the best
    possible terminal outcome.
    Returns the score from the perspective of the current 'player'.
    Win = 1, Loss = -1, Draw = 0.
    """
    winner = check_winner(board)
    if winner != 0:
        # If game is over, return value relative to current player.
        # If winner matches player, return 1. If opposite, return -1.
        return winner * player
    
    if EMPTY not in board:
        return 0  # Draw

    # Initialize best score lower than lowest possible score (-1)
    best_score = -2

    for i in range(9):
        if board[i] == EMPTY:
            # Make temporary move
            board[i] = player
            # Call minimax for the opponent and negate their score
            score = -minimax(board, -player)
            # Undo move (backtracking)
            board[i] = EMPTY

            if score > best_score:
                best_score = score

    return best_score


def computer_turn(board):
    #Computer (O) finds and makes the best move using minimax.
    print("Computer is thinking...")
    best_score = -2
    best_move = -1

    for i in range(9):
        if board[i] == EMPTY:
            # Try a move
            board[i] = COMPUTER
            # Calculate value of this move; we want to minimize score
            score = -minimax(board, HUMAN)
            # Undo the move
            board[i] = EMPTY

            if score > best_score:
                best_score = score
                best_move = i

    # Make the best move found
    if best_move != -1:
        board[best_move] = COMPUTER


def main():
    #Main game loop to handle setup, turns, and game end conditions.
    print("=== Tic-Tac-Toe Game ===\n")
    print("You are X. Computer is O.")
    print("The board positions are numbered 1-9 like a keypad.\n")
    
    while True:
        try:
            player_order = int(input("Do you want to play 1st or 2nd? (1/2): "))
            if player_order not in [1, 2]:
                print("Please enter 1 or 2.")
                continue
            break
        except ValueError:
            print("Invalid input. Please enter 1 or 2.")

    board = [EMPTY] * 9
    game_over = False

    # Max 9 turns in a game
    for turn in range(9):
        # Determine whose turn it is based on player order choice
        # If player chose 1st: Human plays on even turns (0, 2, 4...)
        # If player chose 2nd: Computer plays on even turns
        if (turn + player_order) % 2 == 0:
            computer_turn(board)
        else:
            display_board(board)
            player_x_turn(board)

        # Check game end conditions immediately after a move
        winner = check_winner(board)
        if winner != 0 or EMPTY not in board:
            game_over = True
            break

    # Final board display and result message
    display_board(board)
    winner = check_winner(board)
    if winner == 0:
        print("It's a Draw! A perfect game played by both sides.")
    elif winner == HUMAN:
        # This should technically never happen if minimax works correctly
        print("Congratulations! You (X) win!")
    else:
        print("Computer (O) wins!")

if __name__ == "__main__":
    # This block ensures the main function runs only when executed directly
    main()
Advanced Python Code
HUMAN = -1
COMPUTER = 1
EMPTY = 0

def display_board(board):
    #Prints the current Tic-Tac-Toe board.
    print("\nCurrent Board:")
    for i in range(9):
        if i > 0 and i % 3 == 0:
            print()
            print("-" * 11)

        cell = board[i]
        symbol = " "
        if cell == HUMAN:
            symbol = "X"
        elif cell == COMPUTER:
            symbol = "O"

        print(f" {symbol} ", end="")

        if (i + 1) % 3 != 0:
            print("|", end="")
    print("\n")


def player_x_turn(board):
    #Handles the human player's move (X). Validates input.
    while True:
        try:
            position = int(input("Enter your move (1-9): "))
            index = position - 1

            if position < 1 or position > 9:
                print("Please enter a number between 1 and 9.")
                continue
            if board[index] != EMPTY:
                print("Cell already taken. Try another.")
                continue

            board[index] = HUMAN
            break
        except ValueError:
            print("Invalid input. Please enter a number between 1 and 9.")


def check_winner(board):
    #Checks for a winner. 1 - Computer (O) wins -1 if Human (X) wins, 0 if no winner yet (or draw)
    wins = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
        [0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
        [0, 4, 8], [2, 4, 6]             # Diagonals
    ]
    for combo in wins:
        a, b, c = combo
        if board[a] != EMPTY and board[a] == board[b] == board[c]:
            return board[a]
    return 0


def minimax(board, player):
    #The recursive Minimax algorithm.
    winner = check_winner(board)
    if winner != 0:
        return winner * player
    
    if EMPTY not in board:
        return 0  # Draw

    best_score = -2

    for i in range(9):
        if board[i] == EMPTY:
            board[i] = player
            score = -minimax(board, -player)
            board[i] = EMPTY

            if score > best_score:
                best_score = score

    return best_score


def computer_turn(board):
    #Computer (O) finds and makes the best move using minimax.
    print("Computer is thinking...")
    best_score = -2
    best_move = -1

    for i in range(9):
        if board[i] == EMPTY:
            board[i] = COMPUTER
            score = -minimax(board, HUMAN)
            board[i] = EMPTY

            if score > best_score:
                best_score = score
                best_move = i

    if best_move != -1:
        board[best_move] = COMPUTER


def main():
    print("=== Tic-Tac-Toe Game ===\n")
    print("You are X. Computer is O.")
    print("The board positions are numbered 1-9 like a keypad.\n")
    
    while True:
        try:
            player_order = int(input("Do you want to play 1st or 2nd? (1/2): "))
            if player_order not in [1, 2]:
                print("Please enter 1 or 2.")
                continue
            break
        except ValueError:
            print("Invalid input. Please enter 1 or 2.")

    board = [EMPTY] * 9
    game_over = False

    # Max 9 turns in a game
    for turn in range(9):
        if (turn + player_order) % 2 == 0:
            computer_turn(board)
        else:
            display_board(board)
            player_x_turn(board)

        # Check game end conditions immediately after a move
        winner = check_winner(board)
        if winner != 0 or EMPTY not in board:
            game_over = True
            break

    # Final board display and result message
    display_board(board)
    winner = check_winner(board)
    if winner == 0:
        print("It's a Draw! A perfect game played by both sides.")
    elif winner == HUMAN:
        print("Congratulations! You (X) win!")
    else:
        print("Computer (O) wins!")

if __name__ == "__main__":
    main()
Infographics