Day4 讓電腦下棋 === 看完了古人的操作,換我們來打造一個自動下棋AI了。 那除了把人塞進電腦裡之外,要怎麼讓電腦下棋呢? 以現今的科技要讓電腦下棋已經是稀鬆平常的事了,但是要怎麼讓電腦把棋下得好,甚至於遠超人類就是值得研究的問題了,不過這邊我們還是先從讓電腦可以下棋開始吧。 ## 如何讓電腦下棋 ### 工人智慧 直覺能想到的應該就是先學習人類的思維,我們怎麼下棋就讓電腦怎麼下棋。 以五子棋為例,我們要阻止對方連成五個,就得在對方連成三個時去阻擋對方。 那可能就會有像是以下的策略: ```python if 對方有活三 or 死四: 擋住對方 else: 幫自己造活三 or 死四 ``` 接下來根據遊戲的特性跟你的經驗可以寫出更多的規則,然後你的「AI」可能就會長得像下圖這樣。  會有滿滿的`if` `else` 但不管怎樣第一個會下棋的「AI」也算是完成了,又沒人說AI一定得用到什麼高深的演算法呢。 只是這麼做有個問題,那就是這樣的「AI」可能會有很多的「bug」,例如,自己可以連成活五,但對手有活三或死四,這個程式不會獲勝,而是去擋對方。不同的遊戲變化千變萬化,如果只判斷當前盤面,可能會產生無數種的例外情況。 而且AI的棋力會受到開發者棋力很大的影響,你寫的**程式棋力最強就是跟你棋力相當而已**,規則都是你寫的,你想不到的AI也下不出來,當然你也可以尋求棋力更強的玩家來幫助你寫規則,只是這樣終究有個上限。 ### 暴力窮舉 既然寫規則有其極限,那我們乾脆暴力窮舉吧,不考慮效能的前提下,把所有可能的下法都試一遍總能找到最佳解的。 但現實是殘酷的,我們不可能不考慮效能,如果要窮舉完所有可能的下法需要100年的話,那我們按下執行後就可以開始寫遺囑了,只能**拜託自己的孫子將運算結果還有獵人的完結篇一起燒給你**,所以在我們使用暴力窮舉之前也得先做一些評估才行。 ## 對局樹 (Game Tree) 對局樹是一種用來表示遊戲中所有可能行動和結果的樹狀結構。 這邊以井字遊戲(Tic-Tac-Toe)為例: * 根節點 (root node):代表初始的棋盤狀態,可以是空白棋盤或是下到一半的棋盤。 * 節點 (node):每個節點代表一個特定的棋盤狀態。 * 邊 (edge):從一個節點到下一個節點的邊代表玩家的一次行動(在棋盤上下一個子)。 * 層級 (level/depth):樹的層級表示遊戲的進展,奇數層通常是玩家 X 的回合,偶數層是玩家 O 的回合。 * 葉節點 (leaf node):代表遊戲結束的狀態,可能是 X 勝、O 勝或平局。 我們只要生成一顆對局樹,就可以透過遍歷整個對局樹,找到最佳的下法。 下面的示意圖為從盤面已經有6手棋開始展開。  ## 對局複雜度 (Game Complexity) 跟我們在學習演算法時分析的時間複雜度與空間複雜度類似,當我們分析遊戲的複雜度時,就叫做對局複雜度。 對局複雜度通常包含兩個主要部分:**狀態空間複雜度**和**對局樹複雜度**,用這兩個指標來衡量遊戲的策略空間和決策過程的複雜性。 ### 狀態空間複雜度 (State-space Complexity) 狀態空間複雜度是指遊戲中所有可能的棋盤狀態的總數,下面三張圖都是其中一種棋盤狀態,或是我更習慣稱為盤面。  一樣以井字遊戲為例: * **理論最大狀態數**: 棋盤有 9 個格子,每個格子可能是空白、X 或 O,因此總共有 $3^9 = 19683$ 種可能的棋盤狀態,通常都會以此方式快速評估一個遊戲的狀態複雜度。 * **實際合法狀態數**: 考慮到以下因素,實際的狀態數會更少。 * **玩家次序**:X 和 O 的數量差不能超過 1。 * **勝負條件**:一旦有玩家獲勝,遊戲即結束,後續的行動不再合法。 * **對稱性**:旋轉和鏡像對稱的棋盤狀態被重複計算,下圖三種情況可以視為同個狀態。<br>  最終真正有意義的井字遊戲合法狀態數約為 765 種。 ### 對局樹複雜度 (Game-tree Complexity) 對局樹複雜度是指遊戲中所有可能的對局(從開始到結束的完整行動序列)的總數。 以井字遊戲為例: 井字遊戲的棋盤一開始是空的,玩家 X 可以選擇任何一個地方,產生 9 種可能的局面。 第二步棋玩家 O 接著在剩下的 8 個空格中選擇一個位置下,所以共有 $9×8=72$ 種可能的局面。 第三步棋玩家 X 接著在剩下的 7 個空格中選擇一個位置下子,有 7 種選擇。 所以共有 $72×7=504$ 種可能的局面。 依此類推整個**井字遊戲能產生的局面就是** $9! = 362880$ **對局樹通常都比狀態空間大得多,因為要產生同一個狀態可以有很多種方式,比如手順不同但結果卻相同。** 比如下圖的盤面,X先下在A1再下B2跟先下B2再下A1會得到相同的盤面。  雖然狀態是相同的,但在遊戲樹展開的過程是完全不同的兩條路徑,如下圖。  如果將不合法、旋轉與鏡像等情況都刪除掉的話,那**最終只有26830種對局順序**。 當落子更多時就有更多機會造成相同的盤面,所以其實對局樹會有很多重複的盤面出現,造成效能的浪費,未來會介紹到Transposition Table就能夠來處理這個問題。 ### 常見遊戲的複雜度 | 遊戲 | 狀態空間複雜度 | 對局樹複雜度 | |-----------------|------------------------------|-----------------------------------| | 井字遊戲 | 約 $10^{3}$ | 約 $10^{5}$ | | Connect 4 | 約 $10^{13}$ | 約 $10^{21}$ | | Othello (黑白棋)| 約 $10^{28}$ | 約 $10^{58}$ | | 象棋 | 約 $10^{40}$ | 約 $10^{150}$ | | 西洋棋 | 約 $10^{47}$ | 約 $10^{123}$ | | 將棋 | 約 $10^{71}$ | 約 $10^{226}$ | | 五子棋 | 約 $10^{105}$ | 約 $10^{70}$ | | 圍棋 | 約 $10^{171}$ | 約 $10^{360}$ | | 六子棋 | 約 $10^{172}$ | 約 $10^{140}$ | 狀態空間複雜度影響了需要存儲和處理的資料量,較低的狀態空間複雜度意味著遊戲可以被完全求解。 對局樹複雜度反映了完全遍歷所有可能對局所需的計算量,較高的對局樹複雜度意味著需要更深入的策略思考。 根據電腦對局導論中寫到,以2014年的電腦硬體,可以用窮舉法破解狀態空間在 $10^{13}$~$10^{14}$ 之間的雙人對局,所以可以看到基本上是大多數的遊戲都沒有辦法直接暴力破解,就算是2024年的今天估計也是進步的有限,所以看到一個新的遊戲時,先別急著暴力窮舉,先評估看看這個遊戲的複雜度再來決定要使用什麼方法。 ## 結論 寫一堆規則的AI棋力受限於寫規則的人棋力,暴力窮舉雖然可以找到最佳解,但複雜度太高的遊戲可能有生之年都窮舉不完。 ## Reference * 電腦對局導論 * [賽局複雜度wiki](https://zh.wikipedia.org/zh-tw/%E5%8D%9A%E5%BC%88%E5%A4%8D%E6%9D%82%E5%BA%A6)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.