HarmonyOS 小游戏《对战五子棋》开发第14篇 - 困难AI实现:Minimax算法原理详解

向前看两步------Minimax让AI学会"换位思考"

设计截图如下:

为什么需要Minimax

普通AI的局限:只看当前一步,不考虑对手的反击。

场景:AI可以选择形成活三(8000分)或冲四(10000分)。普通AI选冲四,但对手下一步会堵住冲四,AI的活三机会丢失了。

Minimax的核心思想:假设对手也会做出最优选择,选择对自己最不坏的结果

Minimax算法原理

复制代码
        AI选择(最大化)
       /    |    \
     候选1  候选2  候选3
     / \    / \    / \
   对手选择(最小化)
   ↓   ↓  ↓   ↓  ↓   ↓
  评估 评估 评估 评估 评估 评估
  • Max层(AI回合):选择分数最高的走法
  • Min层(对手回合):选择分数最低的走法(对AI最不利)
  • 叶节点:用评估函数计算当前局面的分数

代码实现

typescript 复制代码
private getHardMove(board: number[][]): Move {
  const candidates = this.getSortedCandidates(board);
  const maxCandidates = Math.min(12, candidates.length);
  let bestMove: Move = candidates[0];
  let bestScore: number = -Infinity;
  let alpha: number = -Infinity;
  const beta: number = Infinity;

  for (let i = 0; i < maxCandidates; i++) {
    const move = candidates[i];
    board[move.row][move.col] = this.aiColor;

    // 如果直接获胜,立即返回
    if (this.checkWin(board, move.row, move.col, this.aiColor)) {
      board[move.row][move.col] = EMPTY;
      return move;
    }

    // Minimax递归(对手回合,最小化)
    const score = this.minimax(board, 2, alpha, beta, false);
    board[move.row][move.col] = EMPTY;

    if (score > bestScore) {
      bestScore = score;
      bestMove = move;
    }
    alpha = Math.max(alpha, score);
  }
  return bestMove;
}

minimax递归函数

typescript 复制代码
private minimax(board: number[][], depth: number, alpha: number, beta: number,
  isMaximizing: boolean): number {
  // 终止条件:深度为0时评估局面
  if (depth === 0) {
    return this.evaluateBoard(board);
  }

  const candidates = this.getSortedCandidates(board);
  const maxCandidates = Math.min(8, candidates.length);

  if (isMaximizing) {
    // AI回合:找最大值
    let maxEval: number = -Infinity;
    for (let i = 0; i < maxCandidates; i++) {
      const move = candidates[i];
      board[move.row][move.col] = this.aiColor;

      if (this.checkWin(board, move.row, move.col, this.aiColor)) {
        board[move.row][move.col] = EMPTY;
        return SCORE_FIVE;  // AI获胜
      }

      const evalScore = this.minimax(board, depth - 1, alpha, beta, false);
      board[move.row][move.col] = EMPTY;

      maxEval = Math.max(maxEval, evalScore);
      alpha = Math.max(alpha, evalScore);
      if (beta <= alpha) break;  // Alpha-Beta剪枝
    }
    return maxEval;
  } else {
    // 对手回合:找最小值
    let minEval: number = Infinity;
    for (let i = 0; i < maxCandidates; i++) {
      const move = candidates[i];
      board[move.row][move.col] = this.humanColor;

      if (this.checkWin(board, move.row, move.col, this.humanColor)) {
        board[move.row][move.col] = EMPTY;
        return -SCORE_FIVE;  // 对手获胜(对AI最不利)
      }

      const evalScore = this.minimax(board, depth - 1, alpha, beta, true);
      board[move.row][move.col] = EMPTY;

      minEval = Math.min(minEval, evalScore);
      beta = Math.min(beta, evalScore);
      if (beta <= alpha) break;  // Alpha-Beta剪枝
    }
    return minEval;
  }
}

搜索树图解

假设AI在搜索深度2,候选3个:

复制代码
深度2           AI选择(MAX)
              /     |      \
深度1       对手(MIN) 对手(MIN) 对手(MIN)
           /  \     /  \     /  \
深度0    评估  评估  评估  评估  评估  评估
          80   50   60   30   90   70

自底向上计算:
  深度1: min(80,50)=50  min(60,30)=30  min(90,70)=70
  深度2: max(50,30,70)=70 → 选择候选1

关键设计决策

1. 深度2的选择

typescript 复制代码
const score = this.minimax(board, 2, alpha, beta, false);
  • 深度1:只看对手反应------不够
  • 深度2:看AI→对手→AI------合理
  • 深度3:AI→对手→AI→对手------更好但计算量大

移动端选择深度2是性能与棋力的平衡。

2. 候选数量限制

typescript 复制代码
// 顶层:12个候选
const maxCandidates = Math.min(12, candidates.length);
// 递归层:8个候选
const maxCandidates = Math.min(8, candidates.length);

搜索树大小 = 12 × 8 × 8 = 768,在移动端可接受。

3. 立即获胜检查

typescript 复制代码
if (this.checkWin(board, move.row, move.col, this.aiColor)) {
  board[move.row][move.col] = EMPTY;
  return move;  // 不需要继续搜索
}

找到必胜走法立即返回,避免不必要的搜索。

4. 评估函数的差异

困难模式使用evaluateBoard(全盘评估),而非普通模式的evaluatePosition(单点评估):

typescript 复制代码
private evaluateBoard(board: number[][]): number {
  let aiScore: number = 0;
  let humanScore: number = 0;
  aiScore += this.evaluateLines(board, this.aiColor);
  humanScore += this.evaluateLines(board, this.humanColor);
  return aiScore - humanScore * 1.1;
}

总结

Minimax算法是博弈树搜索的经典方法:

  1. 换位思考:假设对手做出最优选择
  2. 最大最小:AI最大化,对手最小化
  3. 递归搜索:从叶节点向上回传
  4. 深度控制:平衡棋力与性能

困难模式通过深度2的Minimax搜索,能预见2步之后的局面变化,显著强于普通AI的单步评估。

相关推荐
用户818187062746几秒前
第14章 行为治理与访问控制
人工智能
Lsir10110_5 分钟前
【力扣hot100】矩阵题通关复盘
算法·leetcode·矩阵
退休倒计时6 分钟前
【每日一题】LeetCode 207. 课程表 TypeScript
算法·leetcode·typescript
忘路之远近i11 分钟前
受够阿里云自带终端后,我用 Cursor + grill-me 做了个运维面板
服务器·开发语言·人工智能·python·阿里云·云计算
朱涛的自习室14 分钟前
Munk AI 桌面端「预告」
android·前端·人工智能
www_comsci15 分钟前
【语言、教育类主题EI会议|Call For Paper】第二届人工智能与计算社会科学国际研讨会
人工智能·语言模型
祝威廉16 分钟前
四条语句跑完机器学习:让模型成为一个 SQL 函数
人工智能·sql·机器学习
luoyayun36118 分钟前
【Qt for Harmony】 Qt 5.12.12 鸿蒙版 Windows 交叉编译
qt·harmonyos·qt for harmony
superz丶21 分钟前
Claude Code / Codex 已经有 Harness,项目里还需要自己搭吗?
人工智能
TMT星球23 分钟前
荣耀将阿莱电影工作流融入机器人手机
人工智能·智能手机·机器人