You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现井字棋Minimax算法失效问题求助

问题:Minimax算法井字棋AI未遍历所有可能,仅输出首个检查位置

我参考YouTube教程实现了基于Minimax算法的简易井字棋AI,但算法无法正常工作——它没有遍历所有可能并返回最优位置,而是直接输出首个检查到的位置。复制教程代码后问题依然存在;尝试调换电脑与玩家的棋子标识、调整算法的最大化/最小化逻辑,均未解决问题。

以下是我的代码:

import math
import random

print()

board = {1: '   ', 2: '   ', 3: '   ',
         4: '   ', 5: '   ', 6: '   ',
         7: '   ', 8: '   ', 9: '   '}
computerLetter = 'X'
playerLetter = 'O'


def print_board(board=board):
    for i in range(1, 8, 3):
        print('|' + board[i] + '|' + board[i + 1] + '|' + board[i + 2] + '|')

        if i < 7:
            print('-' * 13)

    print()


def space_is_free(position):
    if board[position] == '   ':
        return True
    else:
        return False


def free_spaces(board=board):

    freeSpaces = 0
    for key in board.keys():
        if key == '   ':
            freeSpaces += 1

    return freeSpaces


def make_move(letter, position):

    if space_is_free(position):

        board[position] = ' ' + letter + ' '
        print_board(board)

        if check_for_win(board):

            if letter == 'O':
                print("You win!!")
                exit()
            else:
                print("The computer wins. Better luck next time!")
                exit()

        elif check_for_tie(board):
            print("It's a tie! Well played.")
            exit()

    else:

        print("Invalid choice.")
        position = int(input("Enter new position: "))
        make_move(letter, position)


def check_for_win(board=board):

    if board[1] == board[2] == board[3] != '   ' or board[4] == board[5] == board[6] != '   ' or board[7] == board[8] \
            == board[9] != '   ' or board[1] == board[4] == board[7] != '   ' or board[2] == board[5] == board[6] != \
            '   ' or board[3] == board[6] == board[9] != '   ' or board[1] == board[5] == board[9] != '   ' or board[3]\
            == board[5] == board[7] != '   ':
        return True
    else:
        return False


def check_for_win_letter(letter):

    if board[1] == board[2] == board[3] == ' ' + letter + ' ' or board[4] == board[5] == board[6] == ' ' + letter + ' '\
            or board[7] == board[8] == board[9] == ' ' + letter + ' ' or board[1] == board[4] or board[7] == ' ' +\
            letter + ' ' or board[2] == board[5] or board[6] == ' ' + letter + ' ' or board[3] == board[6] or board[9]\
            == ' ' + letter + ' ' or board[1] == board[5] == board[9] == ' ' + letter + ' ' or board[3] == board[5] ==\
            board[7] == ' ' + letter + ' ':
        return True
    else:
        return False


def check_for_tie(board=board):

    for key in board.keys():
        if board[key] == '   ':
            return False
    else:
        return True


def player_move(playerLetter='O'):

    if free_spaces(board) >= 9:
        print_board(board)

    position = int(input("Enter position (1-9): "))
    make_move(playerLetter, position)


def computer_move(computerLetter='X'):

    if free_spaces(board) == 9:
        make_move(computerLetter, 5)

    else:

        bestScore = -math.inf
        bestPosition = 0

        for key in board.keys():
            if space_is_free(key):
                board[key] = ' ' + computerLetter + ' '
                score = minimax(board, 0, False)
                board[key] = '   '

                if score > bestScore:
                    bestScore = score
                    bestPosition = key

        make_move(computerLetter, bestPosition)
        print(f"Computer moves to {bestPosition}.")


def minimax(board, depth, isMaximising):

    if check_for_win_letter('X'):
        return 1 * (free_spaces(board) + 1)

    elif check_for_win_letter('O'):
        return -1 * (free_spaces(board) + 1)

    elif check_for_tie(board):
        return 0

    if isMaximising:

        bestScore = -math.inf

        for key in board.keys():

            if space_is_free(key):
                board[key] = ' ' + computerLetter + ' '
                score = minimax(board, depth + 1, False)
                board[key] = '   '
                bestScore = max(score, bestScore)

        return bestScore

    else:

        bestScore = math.inf

        for key in board.keys():

            if space_is_free(key):
                board[key] = ' ' + playerLetter + ' '
                score = minimax(board, depth + 1, True)
                board[key] = '   '
                bestScore = min(score, bestScore)

        return bestScore


while not check_for_win(board):
    computer_move('X')
    player_move('O')

# gameState = input("Would you like to play again? (y/n)")
#
# if gameState.lower() == 'y':
#     main()
# elif gameState.lower() == 'n':
#     exit()
# else:
#     print("Invalid choice.")

问题根源及修复方案

1. free_spaces函数逻辑错误

原函数错误地判断board的key是否等于空字符串(key == ' '),而board的key是1-9的数字,永远不可能等于空字符串,导致该函数始终返回0。这会让Minimax算法错误评估游戏状态,无法正确计算得分。

修复后的代码:

def free_spaces(board=board):
    freeSpaces = 0
    for key in board.keys():
        if board[key] == '   ':  # 修正为判断对应位置的取值是否为空
            freeSpaces += 1
    return freeSpaces

2. check_for_win_letter函数逻辑错误

原函数存在多处逻辑错误:

  • 竖排判断中,将board[2] == board[5] == board[8]错误写成board[2] == board[5] or board[6],导致竖排检测失效。
  • 多处使用or连接条件,而非判断三个位置全部等于目标棋子,导致错误识别获胜状态。

修复后的代码:

def check_for_win_letter(letter):
    target = ' ' + letter + ' '
    # 横排检测
    if board[1] == board[2] == board[3] == target:
        return True
    if board[4] == board[5] == board[6] == target:
        return True
    if board[7] == board[8] == board[9] == target:
        return True
    # 竖排检测
    if board[1] == board[4] == board[7] == target:
        return True
    if board[2] == board[5] == board[8] == target:
        return True
    if board[3] == board[6] == board[9] == target:
        return True
    # 对角线检测
    if board[1] == board[5] == board[9] == target:
        return True
    if board[3] == board[5] == board[7] == target:
        return True
    return False

3. 主循环逻辑优化

原主循环在电脑获胜后仍会执行玩家移动,可在computer_move和player_move中通过check_for_win提前终止循环,不过修复前两个核心错误后,make_move函数已经会在获胜时调用exit()终止程序,该问题可忽略。

修复后效果验证

修复上述错误后,Minimax算法会正确遍历所有可用位置,计算每个位置的得分:

  • 当AI有直接获胜的位置时,会优先选择该位置。
  • 当玩家即将获胜时,AI会优先阻止玩家。
  • 无直接胜负时,AI会选择能引导至平局或最优局面的位置。

内容的提问来源于stack exchange,提问作者Toxic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:31:11