You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python3实现Minimax算法遇阻:井字棋Bot开发求助

嘿,我懂这种感觉!Minimax听起来玄乎,第一次看确实像看天书,但其实拆解开就是个很直白的思路——说白了就是模拟所有可能的走法,然后选对自己最有利的那一步。咱们拿井字棋来拆解,绝对能给你讲明白。

先搞懂Minimax的核心逻辑

Minimax是个零和博弈算法——你赢我就输,反之亦然。井字棋里,假设你是X,Bot是O:你要最大化自己的胜率,Bot要最小化你的胜率,这就是Minimax(Max和Min的结合)名字的由来。

第一步:给局面打“分”

首先得给每个最终局面定个得分,算法才知道哪步好哪步坏:

  • 如果Bot(O)赢了,得**+10分**
  • 如果玩家(X)赢了,得**-10分**
  • 平局的话,得0分

第二步:递归模拟所有走法

算法会递归遍历棋盘上所有空位置,分别假设自己(Max方,Bot)和玩家(Min方)走这一步,然后计算每个分支的得分:

  1. Max层(Bot走):遍历所有空位,选能得到最高得分的那步
  2. Min层(玩家走):遍历所有空位,选能得到最低得分的那步(因为玩家会尽量让Bot得分低)
  3. 递归到终点(有人赢或者平局),就返回对应的得分

第三步:可选优化——Alpha-Beta剪枝

如果你的棋盘不大(井字棋只有9格),剪枝不是必须,但知道了能让算法更快。它的核心是提前砍掉那些不可能影响最终结果的分支:比如Max已经找到一个10分的走法,后面的分支哪怕再高也超不过10,就不用浪费时间算了。

结合井字棋的Python代码示例

咱们写个极简版的核心函数,你一看就懂:

首先写个判断胜负的辅助函数:

def check_winner(board):
    # 定义所有赢棋的模式:行、列、对角线
    win_patterns = [
        [0,1,2], [3,4,5], [6,7,8],  # 横向
        [0,3,6], [1,4,7], [2,5,8],  # 纵向
        [0,4,8], [2,4,6]             # 对角线
    ]
    # 检查是否有人赢
    for pattern in win_patterns:
        if board[pattern[0]] == board[pattern[1]] == board[pattern[2]] != '':
            return board[pattern[0]]
    # 检查是否平局
    if '' not in board:
        return 'tie'
    return None

然后是Minimax核心函数:

def minimax(board, is_maximizing):
    winner = check_winner(board)
    # 终止条件:走到终点就返回对应得分
    if winner == 'O':  # Bot赢了
        return 10
    elif winner == 'X':  # 玩家赢了
        return -10
    elif winner == 'tie':  # 平局
        return 0

    if is_maximizing:
        best_score = -float('inf')
        # 遍历所有空位,模拟Bot走棋
        for i in range(9):
            if board[i] == '':
                board[i] = 'O'  # Bot走一步
                # 切换到玩家回合(Min层),递归计算得分
                score = minimax(board, False)
                board[i] = ''  # 回溯,恢复棋盘原样
                best_score = max(best_score, score)  # Max选最高分
        return best_score
    else:
        best_score = float('inf')
        # 遍历所有空位,模拟玩家走棋
        for i in range(9):
            if board[i] == '':
                board[i] = 'X'  # 玩家走一步
                # 切换到Bot回合(Max层),递归计算得分
                score = minimax(board, True)
                board[i] = ''  # 回溯
                best_score = min(best_score, score)  # Min选最低分
        return best_score

最后是Bot找最优走法的函数:

def find_best_move(board):
    best_score = -float('inf')
    best_move = -1
    # 遍历所有空位,找到得分最高的走法
    for i in range(9):
        if board[i] == '':
            board[i] = 'O'
            score = minimax(board, False)
            board[i] = ''
            if score > best_score:
                best_score = score
                best_move = i
    return best_move
为啥你看StackOverflow的答案看不懂?

很多StackOverflow的最优答案会把代码写得很简洁,甚至加上很多进阶优化(比如缓存局面得分、更复杂的剪枝逻辑),但核心就是上面这些基础逻辑。你可以先从这个极简版开始跑,测试没问题后再慢慢加优化。

比如你可以初始化一个空棋盘:board = ['', '', '', '', '', '', '', '', ''],调用find_best_move(board)就能得到Bot应该走的位置索引(0-8对应九宫格的每个位置)。跑起来你会发现,Bot再也不会轻易输了——甚至根本不会输,最多和你平局!

内容的提问来源于stack exchange,提问作者defunct-user

火山引擎 最新活动