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的单步评估。

相关推荐
火山引擎开发者社区3 小时前
火山 PostgreSQL Serverless × 飞书妙搭:把 AI 装进数据库,一句话唤醒数据智能
人工智能
致Great5 小时前
Pi 的上下文压缩,到底是怎么工作的?
算法
必须会一定会5 小时前
Agent Plugins 1.0实战:plugin.json、skills、mcp.json目录结构与迁移
开发语言·人工智能·ai编程
CTA量化套保6 小时前
近期零基础量化学习:先分阶段,再用 AI 检查缺口
人工智能·python
Justin3go6 小时前
AI 引荐流量报告:哪些独立产品正在从 ChatGPT 获客?
人工智能·seo
watersink6 小时前
机器学习聚类算法
算法·机器学习·聚类
风流 少年6 小时前
Spring AI 2.0:SSE
java·人工智能·spring
深小乐6 小时前
AI 项目上线:折腾 Cloudflare,真香也藏不少坑
人工智能
luj_17687 小时前
桥牌思维启示:系统设计的模块化架构
c语言·开发语言·c++·经验分享·算法
ACP广源盛139246256737 小时前
Qwen3.8‑2.4T 开源落地@ACP#国产 MoE 私有化部署下 GSV2221 视频转换芯片机遇分析
大数据·数据库·人工智能