如何寫一個象棋 AI (一)

本文代碼:github.com/ParadeTo/ch…node

Demo 地址:www.paradeto.com/chinese-che…git

咱們都知道,把大象關進冰箱須要三步。同理,寫一個象棋 AI 程序也只須要三步:github

  1. 遍歷出全部可能的走法
  2. 選擇出最好的走法

第三步其實只是湊數而已,能夠去掉,這樣寫一個 AI 程序就更簡單了,只須要兩步。算法

其中,第一步對於稍微有點象棋和編程知識的人來講並非很難,除了馬和炮的走法須要寫一些額外的規則來判斷之外,其餘的棋子都比較相似,這一部分不在本文的討論範圍以內。編程

第二步纔是本文須要討論的重點,首先咱們要解決的第一個問題是,給定一個棋局,如何判斷該棋局的好壞呢?bash

局勢評估

關於象棋局勢的評估已有很多學者作過研究,有靜態單子型、將來局勢型、象棋知識型、局面附加信息等。本文采起的是靜態單子型。優化

所謂靜態單子型評估,是指對棋盤上的每個棋子考慮其種類和位置,依種類的重要性與位置的優劣決定它的評估值,而後將棋盤上全部己方棋子的評估值直接累加獲得己方戰力值,將對手全部棋子的評估值累加獲得對手戰力值,已方戰力值減去對手戰力值獲得最終的局勢評估值。ui

最大最小值算法

有了局勢評估方法後,每次遍歷出全部的可能走法,而後從中選取局勢分數最高的走法就是一個最簡單的象棋 AI 了。不過這個 AI 會有點蠢,有點短視。想一想小時候跟院子裏的老大爺下棋時是怎麼被玩弄的吧,老大爺老是故意讓一個車給你吃,而正當你開心得得意忘形的時候,一聲 「將軍」 瞬間讓你跌回了深淵,死棋,遊戲結束。每當這個時候,心中總會暗忖,這個老頭子可真陰險。後來才知道,對付這種陰險的戰術須要咱們下棋時能抵抗住誘惑,看得更加長遠一些,不能只顧當前這一步,要考慮到後面兩步、三步……的狀況。spa

既然這樣,那程序實現起來也簡單,無非就是遞歸的遍歷幾層,達到葉子節點後計算當前局勢得分,而後選擇分數最高的不就能夠了。就像下圖這樣:code

我先遍歷出全部可能的走法(圖中黑色方塊),而後基於該層的走法繼續遍歷(圖中最後一排的白色方塊),計算局勢分數,選擇最高分數的走法,即選擇左邊黑色方塊的走法。可是,你忘記了一點,你走完後,接下來是輪到你對手走了,你若是想獲得 100 的分數,就須要你的對手配合你選擇分數 100 的走法。很明顯你的對手不會那麼傻,此時,只要他跟你同樣聰明,他應該會選擇走分數爲 1 的那一步。而若是你選擇右邊黑色方塊的走法,你的對手會選擇分數爲 33 的走法,你反而會獲得一個高一點的分數。

讓咱們用一個別的例子再來模擬一下上面的情景,以便更好的理解。假設你朋友給你兩個袋子,第一個袋子裏面裝了一顆螺絲和一臺 Mac Pro,第二個袋子裏面裝了一臺小米9和一臺華爲p30。而後跟你說,選擇一個袋子,而後我從裏面拿一個禮物送給你。你會怎麼選?你確定選第二個袋子是吧。固然,這裏重要的一點是你的朋友智商必定要正常,若是是個傻子的話,保不許你選了第一個袋子,他會送臺 Mac 給你。

人能夠作出這樣的決策這很正常,可是如何教會計算機也這樣思考呢?這就須要用到最大最小值算法了。最大最小算法把搜索樹分紅最大值層和最小值層,AI 處於最大值層,對手處於最小值層,最大值層老是從下一層選取最大的值做爲結果,最小值層老是從下一層選擇最小值做爲結果。以下圖所示:

思路清楚了,代碼實現起來就很簡單了,如下是來自 wiki 的一段僞代碼:

function minimax(node, depth, maximizingPlayer) is
    if depth = 0 or node is a terminal node then
        return the heuristic value of node
    if maximizingPlayer then
        value := −∞
        for each child of node do
            value := max(value, minimax(child, depth − 1, FALSE))
        return value
    else (* minimizing player *)
        value := +∞
        for each child of node do
            value := min(value, minimax(child, depth − 1, TRUE))
        return value
複製代碼

總結

本文闡述了實現一個象棋 AI 的基本步驟,引出了最大最小值算法並經過例子加以分析。不過該算法比較耗時,假設每次遍歷平均產生 30 種走法,則深度爲 5 的 AI 的一共須要進行 24300000 次的局勢分數計算。事實上該算法經過必定的規則能夠進行優化,這個就留在下一篇文中再進行論述吧。

參考

  1. 中國象棋計算機博弈局面評估技術研究
  2. Minimax
  3. IntelligentChineseChessSystem
  4. gobang
相關文章
相關標籤/搜索