【编程开发】简单五子棋 AI 设计

【研究报告】简单五子棋 AI 设计

社会研讨课做的研究课题,有空了来完善一下算法吧,基础 \(\text{UI}\) 直接搬的 \(ckj\),已获得本人允许。

【Github】

一:【探究目标】

学习、设计、部分实现一只基础五子棋 \(\text{AI}\),调整参数并简单测试对弈能力(考虑最简单的无禁手五子棋)。

二:【设计算法】

算法核心问题:落子决策(择优)。

1.【暴力出奇迹】

“精确记忆”能力是计算机相较于人类的优势之一,自然引入“棋谱记录”。

(1).【全棋谱记忆】

在大小为 \(19\times 19\) 的棋盘上,每个格子有 “黑”、“白”、“无” 三种状态,共 \(3^{361}\) 种棋局状态,对于每种状态记录走法。

储存空间有限、算力不足,不具备可实践性。

(2).【部分棋谱记忆】

利用有限的储存空间和算力记录部分棋谱。

  • 查找开局谱,使用优势走法到有限步数停止
  • 中间局使用单步决策算法进行临场决策
  • 根据残局谱,检测是否出现必胜局

2.【单步决策-落子估价】

开局和残局有棋谱参考,中间局则需“临场应变”。

  • 每次落子前,扫描当前棋局,选择最优落点

何为最优?

  • 设计“估价函数”,以当前棋局状态为参数,为可落子位置估计“落点价值”,择其大者

影响落点价值的因素构成?

【特殊情况】下回合必胜/败

【攻/防】攻防分数占比

【当前局面】根据连子点数给予不同分数

\(^{*}\)全局估价】赢法数组(\(f_{(横、竖)}=2*19*(19-5+1)=570\)\(g_{(斜)}=2*\sum_{k=5}^{19}(k-5+1)=240\),总情况数:\(570+240=810\)

【对手的价值盘】用相同的估价方法计算对手的价值盘,提前断绝对方的优势落点

3.【预言决策-对抗搜索】

(1).【深度搜索】

【Min-Max 搜索算法】

分数从终点往起点方向累加(叶节点为 \(0\)),我方落子加正分,对方落子加负分,我方希望最后总分最大,对方希望总分最小。

\(\text{findmax}\) 层:\(s(x)=\max\{s(y)+v(x,y)|y\in son(x)\}\)

\(\text{findmin}\) 层:\(s(x)=\min\{s(y)-v(x,y)|y\in son(x)\}\)

两者相互递归调用。

(2).【算法优化】

【Alpha-beta 剪枝】

对于 \(\text{findmax}(x)\)
\(son(x)=\{y_1,y_2...\}\),当前检索到 \(y_k\) 的位置,设 \(alpha=\max\{s(y_i)+v(x,y_i)|1\leqslant i < k\}\)
\(son(y_k)=\{z_1,z_2...\}\),当前检索到 \(z_l\) 的位置,若 \(s(z_l)-v(y_k,z_l)\leqslant alpha-v(x,y_k)\),则 \(s(y_k)=\min\{s(z)+v(y_k,z)|z\in son(y_k)\}\) \(\leqslant s(z_l)-v(y_k,z_l)\) \(\leqslant alpha-v(x,y_k)\),而 \(alpha\) 在不断寻找更大的分数更新自己,所以 \(s(y_k)\) 必对 \(alpha\) 无影响,\(y_k\) 剩下的子节点 \(\{z_{l+1},...z_{m}\}\) 不必再检索。

对于 \(\text{findmin}\) 层类似。

//(完整代码1000+行,不作展示)
inline LL findmin(Re deep,LL alpha,Re op);//对手想让我尽量小
inline LL findmax(Re deep,LL beta,Re op) {//我想尽量大
	if(...)return -inf;//对手赢了
	if(...)return 0;//平局
	if(deep>MAX_deep)return 0;//搜索深度限制
	LL ans=-dfs_inf;//准备一个对于我来说的最坏情况(低分)
	for(i;;){//枚举状态
		luozi();//试探落子
		ans=max(ans,v+findmin(deep+1,ans-v,op^1));//搜下一层
		luozi_back();//撤销落子
		if(ans>=beta)return ans;//alpha-beta剪枝
	}
	return ans;
}

【棋盘局部搜索】不需要搜索棋盘上所有位置

(3).【\(^{*}\)更好的落子估价-更多影响因素构成】

\(^{*}\)未来局面】

\(^{*}\)空步预测】

4.【参数调整】

调整各种参数,不同参数下的机器相互对战。

【*估价函数】各种不同的连子局面,分别设置什么参数

【攻防比】我攻:我防:敌攻:敌防

【搜索参数】深度、广度


三:【对弈测试】

对弈参与者:

  • \(\text{AI}_{ckj}\):由 \(ckj\) 同学提供,使用单步决策算法
  • \(\text{AI}_0\):采用估价函数进行单步决策
  • \(\text{AI}_1\):采用搜索算法进行预言决策
  • \(\text{Human}_1\):为避免实力差距过大,粗略限制了思考时间

1.【调整参数】

(1).【攻防比】

【对弈对象】我方:\(\text{AI}_0\),敌方:\(\text{AI}_{ckj}\)

【先手开局最佳成绩】我攻:我防:敌攻:敌防=2:4:3:1 胜:败:平=316:129:55

【后手开局最佳成绩】我攻:我防:敌攻:敌防=3:4:2:1 胜:败:平=271:165:64

(2).【搜索范围】

【对弈对象】

我方:\(\text{AI}_1\)(估价函数攻防比取 3:4:2:1),敌方:\(\text{AI}_{ckj}\)

【先手开局最佳成绩】deep=1,wide=9 胜:败:平=322:125:53

【后手开局最佳成绩】deep=2,wide=4 胜:败:平=342:83:75

2.【AI 对弈】

【对弈对象】我方:\(\text{AI}_1\),敌方:\(\text{AI}_{0}\)

【先手开局】胜:败:平=125:49:326

【后手开局】胜:败:平=6:84:410

3.【人机对弈】

(1).单步决策

【对弈对象】我方:\(\text{AI}_0\),敌方:\(\text{Human}_1\)

【先手开局】胜:败:平=11:9:0

【后手开局】胜:败:平=8:12:0

(2).预言决策

【对弈对象】我方:\(\text{AI}_1\),敌方:\(\text{Human}_1\)

【先手开局】胜:败:平=16:4:0

【后手开局】胜:败:平=11:9:0


四:【数据分析】

  • 调整参数时,更多地是在趋于”如何击败 \(\text{AI}_{ckj}\)“,所以先手最佳成绩为"deep=1",后手最佳成绩为"deep=2"(\(\text{AI}_{ckj}\) 为单步决策算法)
  • \(\text{AI}_0\)\(\text{AI}_1\) 对弈时两者差异不大、平局居多,推测原因为:估价函数参数设置对强度影响较大,而两者估价函数同源
  • 人机对弈时,搜索预测明显比单步预测更强

五:【总结】

1.【对弈算法一般性】

  • 简单棋类博弈均可采用“估价函数+对抗搜索”的方法设计 \(\text{AI}\)。对于局面状态数量较少的类型,可以一次搜索找到必胜策略;较多者则辅以“部分棋谱记忆”。

  • 设计估价函数方案需要大量时间调整参数,“部分棋谱记忆”需要大量棋谱数据。

2.【算法改进空间】

  • 录入开局谱、残局谱

  • 与较强 \(\text{AI}\) 对弈,寻找最佳估价函数参数方案

  • 优化复杂度


六:【致谢】

感谢 \(ckj\) 同学提供基础 \(\text{UI}\) 代码。


七:【参考资料】

posted @ 2022-05-29 16:32  辰星凌  阅读(928)  评论(0编辑  收藏  举报