砍掉无用的搜索分支------Alpha-Beta剪枝让Minimax快一倍
设计截图如下:

为什么需要剪枝
Minimax搜索深度2、宽度12时,需要评估 12 × 8 = 96 个叶节点。如果深度增加到3,就是 12 × 8 × 8 = 768 个。指数增长很快就会让AI"思考"时间过长。
Alpha-Beta剪枝的核心思想:如果已经知道一个分支的结果不可能比另一个分支更好,就没必要继续搜索了。
Alpha和Beta的含义
- Alpha:MAX层当前能保证的最大值(AI至少能拿到这么高的分)
- Beta:MIN层当前能保证的最小值(对手最多让AI拿到这么低的分)
剪枝条件 :beta <= alpha 时剪枝------当前分支不可能影响最终决策。
剪枝过程图解
MAX
/ | \
A B C
/ \ / \ / \
3 5 2 ? ? ?
1. 评估A的子节点:min(3,5)=3 → A=3, alpha=3
2. 评估B的第一个子节点:2
此时 beta=2, alpha=3
beta(2) <= alpha(3) → 剪枝!B的第二个子节点不需要评估
B=2
3. 评估C...
直觉理解:AI已经知道A分支能拿3分。搜索B分支时,发现对手能限制到2分。2 < 3,所以AI不会选B,B的剩余子节点不需要搜索。
代码中的剪枝
MAX层(AI回合)
typescript
if (isMaximizing) {
let maxEval: number = -Infinity;
for (let i = 0; i < maxCandidates; i++) {
// ... 落子、递归 ...
maxEval = Math.max(maxEval, evalScore);
alpha = Math.max(alpha, evalScore); // 更新alpha
if (beta <= alpha) break; // 剪枝!
}
return maxEval;
}
MIN层(对手回合)
typescript
else {
let minEval: number = Infinity;
for (let i = 0; i < maxCandidates; i++) {
// ... 落子、递归 ...
minEval = Math.min(minEval, evalScore);
beta = Math.min(beta, evalScore); // 更新beta
if (beta <= alpha) break; // 剪枝!
}
return minEval;
}
顶层调用的Alpha-Beta
typescript
private getHardMove(board: number[][]): Move {
let alpha: number = -Infinity;
const beta: number = Infinity;
for (let i = 0; i < maxCandidates; i++) {
// ...
const score = this.minimax(board, 2, alpha, beta, false);
// ...
alpha = Math.max(alpha, score); // 更新alpha
}
}
顶层beta保持Infinity(因为还没搜索完所有候选,无法确定上限),alpha随着搜索逐渐增大。
剪枝效果分析
| 场景 | 无剪枝 | 有剪枝 | 加速比 |
|---|---|---|---|
| 深度2,宽度12×8 | 96次评估 | ~48次评估 | 2x |
| 深度3,宽度12×8×8 | 768次评估 | ~256次评估 | 3x |
| 深度4,宽度12×8×8×8 | 6144次评估 | ~1024次评估 | 6x |
最佳情况 :剪枝后搜索量减少到原来的平方根。
最差情况:候选排序最差时,没有剪枝效果(但也不会更慢)。
候选排序对剪枝的影响
typescript
private getSortedCandidates(board: number[][]): Move[] {
// 按攻防评分从高到低排序
scored.sort((a: ScoredMove, b: ScoredMove) => b.score - a.score);
return scored.map((s: ScoredMove) => s.move);
}
排序越好,剪枝越多。因为高价值候选先搜索,alpha快速增大,后续低价值候选更容易被剪掉。
这就是为什么困难模式要用getSortedCandidates而非getCandidates------排序是为了让Alpha-Beta剪枝更有效。
实际调试中的思考时间
在本项目中,困难模式的AI在移动端模拟器上的响应时间约200-500ms:
- 搜索 12 × 8 = 96 个局面(理论值)
- 剪枝后约 40-60 个实际评估
- 每个评估约5ms(全盘扫描4个方向)
这个延迟在用户体验上是可以接受的(配合400ms的setTimeout延迟,看起来像AI在"思考")。
总结
Alpha-Beta剪枝是Minimax的标准优化:
- 原理简单:alpha和beta两个变量维护搜索边界
- 效果显著:最佳情况下搜索量减少到平方根
- 依赖排序:候选排序越好,剪枝效果越好
- 零风险:剪枝不影响最终结果,只减少搜索量
没有Alpha-Beta的Minimax在移动端几乎不可用,而加上剪枝后,深度2-3的搜索可以流畅运行。