象棋AI算法
一、最小-最大搜索(Minimax Search)
核心思想:最小与最大是相对的,且只针对一方(AI)。
原理:
AI走一步后,假设对手会走对AI最差的一步;AI需选择使自身收益最大的走法。
示例(搜索深度4):
1 | AI走第1步 → 对手走第2步(最差) → AI走第3步(最佳) → 对手走第4步(最差) |
→ 深度0时调用 Evaluate() 返回局面评价
代码实现:
1 | int Max(int depth) { |
调用方式:val = MinMax(5); → 返回向前看5步的当前局面评价。
二、负值最大函数(Negamax Search)
优化点:将 Min/Max 合并为单函数,通过取负号处理双方角色切换。
1 | int NegaMax(int depth) { |
优势:省去求 min 函数的步骤,减少代码量,始终求对当前节点的最佳走法。
三、Alpha-Beta搜索
问题:Minimax 需检查整个博弈树,分枝因子大导致效率低。
解决方案:通过维护上下界 alpha 和 beta,剪枝无效分支。
3.1 核心概念
| 概念 | 说明 |
|---|---|
| Alpha | 当前节点的最优上界(MAX节点的最大值) |
| Beta | 对手节点的最优下界(MIN节点的最小值) |
| Alpha剪枝 | MIN节点:当 alpha >= beta 时终止扩展 |
| Beta剪枝 | MAX节点:当 alpha >= beta 时终止扩展 |
3.2 口袋示例
场景:死敌面前有多个口袋,你挑口袋,他挑物品。
目标:挑出在诸多最糟糕物品中最好的物品所在的口袋。
排序后剪枝示意:
- 节点2最小值200,节点3中150<200
- 节点1下第一个子节点170 < 200,第二个子节点更小 → 剪裁
- 节点4类似,第一个子节点50,后面的无需再比较
3.3 代码实现
1 | int AlphaBeta(int depth, int alpha, int beta) { |
3.4 性能关键
依赖搜索顺序:若先搜最差分支,无法触发剪枝,退化为 Minimax。
优化建议:生成全部着法后,排序很重要。
参考文献
- http://www.xqbase.com/computer/search_minimax.htm
- http://www.xqbase.com/computer/search_alphabeta.htm
待补充
- 评估函数设计(子力价值、位置优势、残局特征)
- 迭代加深(Iterative Deepening)优化
- 实际象棋博弈树规模估算