1. 程式人生 > 其它 >【程式設計開發】簡單五子棋 AI 設計

【程式設計開發】簡單五子棋 AI 設計

【研究報告】簡單五子棋 AI 設計

社會研討課做的研究課題,有空了來完善一下演算法吧,基礎 \(\text{UI}\) 直接搬的 \(ckj\),已獲得本人允許。

【Download】.rar

一:【探究目標】

學習、設計、部分實現一隻基礎五子棋 \(\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}\) 程式碼。


七:【參考資料】