信息发布→ 登录 注册 退出

Gomoku AI 的 Minimax 实现中胜负判断逻辑错误导致忽略防守

发布时间:2026-01-11

点击量:

本文揭示 gomoku(五子棋)ai 中一个关键缺陷:minimax 算法在检测对手获胜时错误地使用了当前玩家(player)而非实际获胜方(opponent)来决定评分符号,导致 ai 无法识别并阻止人类玩家的必胜局面。

在您提供的 Minimax 实现中,核心问题出在递归终止条件的胜负判定逻辑上:

if (isWinningMove(board, opponent, latestRow, latestCol)) {
  const multiplier = player === COMP ? 1 : -1; // ❌ 错误:应基于 opponent 判断
  return [ WINNING_MOVE * multiplier, latestRow * COLS + latestCol ];
}

这段代码本意是:当对手(opponent)刚落子形成五连时,立即返回一个极值分数以反映该局面对当前 player 的致命性。但 multiplier 的计算逻辑有根本性错误 —— 它依据的是 当前轮到谁走(player),而非 谁真正赢了(opponent)。

✅ 正确逻辑应为:

  • 若 opponent === COMP(即电脑被人类一步绝杀),说明这是对 COMP(最大化方)的失败局面 → 应返回极大负分(-WINNING_MOVE);
  • 若 opponent === HUMAN(即人类被电脑一步绝杀),说明这是对 HUMAN(最小化方)的失败局面 → 应返回极大正分(+WINNING_MOVE)。

因此,multiplier 必须由 opponent 决定,而非 player:

if (isWinningMove(board, opponent, latestRow, latestCol)) {
  const multiplier = opponent === COMP ? 1 : -1; // ✅ 正确:胜者决定符号
  return [ WINNING_MOVE * multiplier, -1 ]; // 同时,move 索引设为 -1(无效),避免误导
}
? 为什么低深度有时“碰巧”能防住? 在浅层搜索(如 depth=1)中,AI 直接评估所有合法子节点,并可能因 evaluateBoard() 的启发式打分(如邻接计数)偶然给“堵三”位置较高分;但随着深度增加,剪枝和更远的博弈树展开放大了胜负判断错误的影响——当某条分支中人类在第 2 步获胜,而 AI 错误地将其评分为 +WINNING_MOVE(本应是 -WINNING_MOVE),该分支反而被优先选择,导致 AI 主动“送输”。

此外,还有两个重要改进建议:

  1. evaluateBoard 启发函数过于简陋
    当前仅统计邻接同色子数,无法区分“活三”、“冲四”、“双三”等关键威胁。建议引入模式匹配(如检测 01110、011110、11110 等局部序列),并为不同威胁等级赋予差异化权重(例如:活四 = +5000,冲四 = +1000,活三 = +200,眠三 = +50)。

  2. latestRow/Col 在根节点调用时传入 (-1,-1) 存在隐患
    isWinningMove(..., -1, -1) 可能越界或产生未定义行为。应在进入 minimax 前确保 latestRow/Col 有效,或在 isWinningMove 开头添加边界防护:

    function isWinningMove(grid, who, row, col) {
      if (row < 0 || col < 0 || row >= ROWS || col >= COLS) return false;
      // ...其余逻辑
    }

总结:修复胜负判断中的 multiplier 逻辑是让 AI 具备基础防守能力的前提。在此基础上,升级评估函数、完善边界检查、并辅以合理的搜索深度(建议 3–5 层配合迭代加深),才能构建出既积极进攻又稳健防守的 Gomoku AI。

标签:# 而非  # 应在  # 大了  # 这段  # 将其  # 设为  # 被人  # 的是  # 这是  # go  # 算法  # 递归  # 为什么  # win  # ai  # oppo  # 电脑  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!