别再死记硬背了!用‘石头剪刀布’和‘抢30’游戏,5分钟搞懂Minimax算法核心
2026/6/6 18:20:10 网站建设 项目流程

用童年游戏破解Minimax算法:从石头剪刀布到决策树逆向思维

小时候玩石头剪刀布时,我们总希望猜透对手的心思;和朋友轮流报数"抢30"时,又总在盘算如何逼对方走入绝路。这些看似简单的游戏背后,隐藏着人工智能领域最经典的决策算法——Minimax的核心逻辑。今天,我们就用这两种人人都懂的游戏,拆解这个让无数初学者头疼的算法精髓。

1. 石头剪刀布:零和博弈的微观世界

想象一下午休时和同事玩石头剪刀布,每次出手前大脑中闪过的那些念头:"上局他出布,这次可能会出剪刀"、"我连续两次石头,该换策略了"...这种心理博弈正是完全信息零和博弈的雏形。虽然游戏本身具有随机性,但当我们赋予AI学习能力时,它需要建立一套应对策略。

零和博弈的本质很简单:

  • 双方利益完全对立(你赢即我输)
  • 所有可能结果的总和为零(没有双赢或双输)
  • 参与者需要预测对方行为并做出最优反应

用支付矩阵表示石头剪刀布的收益(假设赢=+1,输=-1,平=0):

选择组合玩家A收益玩家B收益
石头 vs 剪刀+1-1
剪刀 vs 布+1-1
布 vs 石头+1-1
相同选择00

这个矩阵揭示了Minimax算法的第一个关键概念:在对手采取最优策略的情况下,如何保证自己的最坏结果最好。对应到石头剪刀布,当双方都采用纳什均衡策略(即随机等概率出拳)时,谁都无法通过单方面改变策略获得优势。

2. 抢30游戏:决策树的具象化演绎

比石头剪刀布更适合解释Minimax的是"抢30"游戏:两人轮流报数,每次可以加1-3,谁先报到30谁赢。这个游戏的状态空间极小,却能完美展示决策树的构建过程。

假设现在轮到你说数字,当前数是25,你有三种选择:

  • 说26(+1)
  • 说27(+2)
  • 说28(+3)

决策树分析

  1. 如果你选28(当前层是MAX层,你希望最大化胜率):

    • 对手会面对29(MIN层,对手会最小化你的胜率):
      • 对手可以报30直接获胜 → 这个分支你必输
  2. 如果你选27:

    • 对手面对28:
      • 对手选29(你被迫报30输) → 同样必输
  3. 如果你选26:

    • 对手面对27:
      • 对手选28(你报29,对手被迫报30)
      • 或对手选29(你被迫报30) → 存在让对手被迫报30的路径

通过这种逆向推导,你会发现报26是唯一可能获胜的选择。这就是Minimax的核心——从终局倒推,假设对手总是做出对你最不利的选择,你则在这些"最坏情况"中选择"相对最好"的路径。

3. Minimax算法四步拆解

现在我们将抢30游戏的思考过程抽象成算法步骤:

3.1 构建游戏决策树

从当前状态出发,列出所有可能的移动(通常受游戏规则限制)。对于抢30游戏:

def generate_moves(current_number): return [current_number + 1, current_number + 2, current_number + 3]

3.2 定义叶节点估值

对于终止状态(如报30)给出胜负判定:

def evaluate(state): if state == 30: return float('-inf') # 报30的人输 elif state > 30: return float('inf') # 让对手报30的人赢 return 0 # 非终局状态

3.3 递归计算节点值

交替应用MIN和MAX规则:

def minimax(state, is_max_player): if state >= 30: # 终局判断 return evaluate(state) if is_max_player: best_value = float('-inf') for move in generate_moves(state): value = minimax(move, False) best_value = max(best_value, value) return best_value else: best_value = float('inf') for move in generate_moves(state): value = minimax(move, True) best_value = min(best_value, value) return best_value

3.4 选择最优路径

从根节点选择估值最高的分支执行:

def find_best_move(current_state): best_move = None best_value = float('-inf') for move in generate_moves(current_state): value = minimax(move, False) # 下一层是对手回合 if value > best_value: best_value = value best_move = move return best_move

4. 从游戏到实战:Minimax的应用进化

理解了基础原理后,我们可以探讨Minimax在实际AI系统中的演进路径:

4.1 深度限制与估值函数

真实棋类游戏无法构建完整决策树(如围棋可能状态数超过宇宙原子数),需要:

  • 设置搜索深度限制
  • 设计中间状态估值函数(如象棋中:皇后=9,车=5,象/马=3,兵=1)

估值函数设计示例

def chess_evaluation(board): piece_values = {'Q':9, 'R':5, 'B':3, 'N':3, 'P':1} score = 0 for piece in board: if piece.isupper(): # 己方棋子 score += piece_values.get(piece.upper(), 0) else: # 对方棋子 score -= piece_values.get(piece.upper(), 0) return score

4.2 Alpha-Beta剪枝优化

通过记录α(当前MAX最佳)和β(当前MIN最佳)来跳过无效分支:

def alphabeta(state, depth, α, β, is_max_player): if depth == 0 or is_terminal(state): return evaluate(state) if is_max_player: value = float('-inf') for move in generate_moves(state): value = max(value, alphabeta(move, depth-1, α, β, False)) α = max(α, value) if α >= β: break # β剪枝 return value else: value = float('inf') for move in generate_moves(state): value = min(value, alphabeta(move, depth-1, α, β, True)) β = min(β, value) if β <= α: break # α剪枝 return value

4.3 现代AI的融合应用

当代游戏AI往往结合多种技术:

  • 蒙特卡洛树搜索(MCTS):AlphaGo的核心算法
  • 神经网络估值:用深度学习替代人工设计估值函数
  • 并行计算:利用GPU加速树搜索过程

在开发自己的第一个棋类AI时,建议从这些优化路线入手:

  1. 先实现基础Minimax
  2. 加入深度限制和简单估值函数
  3. 实现Alpha-Beta剪枝
  4. 逐步引入更复杂的优化技术

5. 为什么Minimax如此重要?

这个诞生于1928年的算法至今仍是博弈AI的基石,主要因为:

  1. 理论完备性:在完全信息零和博弈中能证明找到纳什均衡
  2. 框架通用性:只需修改移动生成和估值函数即可适配不同游戏
  3. 教学价值:完美展示了如何将人类直觉思维形式化为算法

我曾用Python实现过一个五子棋AI,最初版本只搜索3层深度就能击败大多数新手。当加入简单的开局库和4层搜索后,已经能给我这个开发者带来挑战。最有趣的是观察AI如何"思考"——打印出它的评估过程,会发现它确实在像人类一样计算各种走法的后果,只是更加全面和快速。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询