人機博弈-吃子棋遊戲(四)搜尋演算法,人機

來源:互聯網
上載者:User

人機博弈-吃子棋遊戲(四)搜尋演算法,人機

博弈樹搜尋技術簡介:

博弈樹的搜尋演算法,負值極大搜尋,alpha-beta搜尋,渴望搜尋,PVS極窄視窗搜尋等。通常來說,搜尋演算法常常和以下技術聯合在一起。

如下:

1.置換表,記錄已經搜尋過的棋局,避免再次搜尋。

2.吃子啟發,優先試下能夠吃對方棋子的走法。

3.殺手啟發,曆史啟發簡化版。

4.曆史啟發,優先試下曆史統計資料得出的比較好的走法。

5.靜止期搜尋,繼續對某些葉子結點搜尋,避免水平線效應。

6.迭代加深搜尋,根據搜尋時間,狀態。決定是否繼續搜尋。

 有興趣的朋友可以深入研究一下上述技術和演算法。

 

吃子棋搜尋演算法:

我的程式最初的實現使用的負值極大搜尋演算法,之後改用alpha-beta搜尋演算法,後來又使用PVS極窄視窗搜尋演算法。

在我自己的實現裡沒有使用置換表,曆史啟發等技術。是因為吃子棋每層的走法數相對較少,所以並沒有使用。

但我們知道,這些技術可以很大的提高搜尋效率。

 

吃子棋搜尋演算法源碼:

接下來,看看吃子棋搜尋演算法的原始碼:

負值極大演算法

int CNegaMaxEngine::negaMax(int depth){    int currentMaxScore = -20000;//init value mini    int score;    int nextMoveCount;    int overNum = IsGameOver(CurPosition, depth);    if (overNum != 0)return overNum;    if (depth <= 0)        return m_pEval->Eveluate(CurPosition, (m_nMaxDepth - depth ) % 2 );    nextMoveCount = m_pMG->CreatePossibleMove(CurPosition, depth, (m_nMaxDepth - depth) % 2);    for (int i = 0; i < nextMoveCount; i++)    {        MakeMove(&m_pMG->m_MoveList[depth][i], (m_nMaxDepth - depth) % 2);        score = -negaMax(depth-1);        UnMakeMove(&m_pMG->m_MoveList[depth][i]);        if (score>currentMaxScore)        {            currentMaxScore = score;            if (depth == m_nMaxDepth){                            m_cmBestMove = m_pMG->m_MoveList[depth][i];            }        }    }    return currentMaxScore;}
alpha-beta演算法
int CAlphtBetaEngine::alphabeta(int depth,int alpha ,int beta){        int score;    int nextMoveCount;    int overNum = IsGameOver(CurPosition, depth);        if (overNum != 0)return overNum;    int whoTurn = (m_nMaxDepth - depth) % 2;    if (depth <= 0)        return m_pEval->Eveluate(CurPosition, whoTurn);    nextMoveCount = m_pMG->CreatePossibleMove(CurPosition, depth, whoTurn);    for (int i = 0; i < nextMoveCount; i++)    {        MakeMove(&m_pMG->m_MoveList[depth][i], whoTurn);        score = -alphabeta(depth - 1, -beta, -alpha);        UnMakeMove(&m_pMG->m_MoveList[depth][i]);        if (score>alpha)        {            alpha = score;            if (depth == m_nMaxDepth){                m_cmBestMove = m_pMG->m_MoveList[depth][i];            }        }        if (alpha >= beta)break;    }    return alpha;}

PVS演算法:

int CPVS_Engine::PrincipalVariation(int depth, int alpha, int beta){    int score;    int Count, i;    BYTE type;    int best;    i = IsGameOver(CurPosition, depth);    if (i != 0)        return i;    if (depth <= 0)    //葉子節點取估值        return m_pEval->Eveluate(CurPosition, false);    Count = m_pMG->CreatePossibleMove(CurPosition, depth, (m_nMaxDepth - depth ) % 2);     MakeMove(&m_pMG->m_MoveList[depth][0], (m_nMaxDepth - depth ) % 2);    best = -PrincipalVariation(depth - 1, -beta, -alpha);    UnMakeMove(&m_pMG->m_MoveList[depth][0]);    if (depth == m_nMaxDepth)        m_cmBestMove = m_pMG->m_MoveList[depth][0];    for (i = 1; i<Count; i++)    {        if (best < beta)        {            if (best > alpha)                alpha = best;            MakeMove(&m_pMG->m_MoveList[depth][i], (m_nMaxDepth - depth ) % 2);            score = -PrincipalVariation(depth - 1, -alpha - 1, -alpha);            if (score > alpha && score < beta)            {                best = -PrincipalVariation(depth - 1, -beta, -score);                if (depth == m_nMaxDepth)                    m_cmBestMove = m_pMG->m_MoveList[depth][i];            }            else if (score > best)            {                best = score;                if (depth == m_nMaxDepth)                    m_cmBestMove = m_pMG->m_MoveList[depth][i];            }            UnMakeMove(&m_pMG->m_MoveList[depth][i]);        }    }    return best;}



αβ剪枝演算法應用於五子棋中,急!!!

int ab(int n,int a,int b)
{
int temp;
if(n<=0)
return (評價函數); /*評價函數*/
for(每一個走法)
{
(產生節點函數);
temp=-ab(n-1,-b,-a);
(撤消產生的節點函數);
if(temp>a)
a=temp;(此處可保留搜尋的最佳位置)
if(a>b)
break;
}
return a;
}
 
五子棋人機對戰演算法

總的來說,要讓電腦知道該在哪一點下子,就要根據盤面的形勢,為每
一可能落子的點計算其重要程度,也就是當這子落下後會形成什麼棋型(如:“沖四”、“活三”等),然後通覽
全盤選出最重要的一點,這便是最基本的演算法。當然,僅靠當前盤面進行判定是遠遠不夠的,這樣下棋很輕易掉進
玩家設下的陷阱,因為它沒有考慮以後的變化。所以在此基礎上我們加入遞迴調用,即:在電腦中猜測出今後幾步
的各種走法,以便作出最佳選擇,這也是我們下棋時常說的“想了幾步”。如此一來您的程式便具有一定的水平了。
什嗎?不信!過來試試吧!
總體思路弄清之後,下面進行具體討論:
一:資料結構
先來看看資料結構,我們需要哪些變數?
首先得為整個棋盤建立一張表格用以記錄棋子資訊,我們使用一個15*15的二維數組 Table[15][15] (15*15是
五子棋棋盤的大小),數組的每一個元素對應棋盤上的一個交叉點,用‘0’表示空位、‘1’代表己方的子、‘2’
代表對方的子;這張表也是今後分析的基礎。
在此之後還要為電腦和玩家雙方各建立一張棋型表Computer[15][15][4]和Player[15][15][4],用來存放棋型
資料,就是剛才所說的重要程度,比如用‘20’代表“沖四”的點,用‘15’代表“活三”的點,那麼在計算重要
性時,就可以根據20>15得出前者比後者重要,下子時電腦便會自動選擇“沖四”的點。那為什麼棋型表要使用三
維數組呢?因為棋盤上的每一個點都可以與橫、豎、左斜、右斜四個方向的棋子構成不同的棋型,所以一個點總共
有4個記錄;這樣做的另一個好處是可以輕易判定出複合棋型,例如:假如同一點上有2個‘15’就是雙三、有一個‘15’和一個‘20’就是四三。
怎麼樣!3個數組構成了程式的基本資料骨架,今後只要再加入一些輔助變數便可以應付自如了。應該不會太
難吧?OK!有了這麼多有用的資料,我們就可以深入到程式的流程中去了。
二:程式流程
我們主要討論五子棋的核心演算法,即:人工智慧部分,而其他像圖形顯示、鍵盤滑鼠控制等,因較為簡單,所
以就不作過多介紹了。
我們看到本程式由六個準系統模組構成,各模組的具體分析如下:
(1)初始化:首先,建立盤面數組Table[15][15]、對戰雙方的棋型表Computer[15][15][4]和Player[15]
[15][4]並將它們清零以備使用;然後初始化顯示器、鍵盤、鼠等輸入輸出裝置並在螢幕上畫出棋盤。
(2)主迴圈控制模組:控制下棋順序,當輪到某方下子時,負責將程式轉到相應的模組中去,主要擔當一個
調度者的角色。
(3)玩家下子:當輪到玩家下時,您通過鍵盤或滑鼠在棋盤上落子,程式會根據該點的位置,在Table[15]
[15]數組的相應地方記錄‘2’,以表明該子是玩家下的。
(4)盤面分析填寫棋型表:本程式核心模組之一,人工智慧演算法的根本依據!其具體實現方法如下:您在下
五子棋時,一定會先根據棋盤上的情況,找出當前最重要的一些點位,如“活三”、“沖四”等;然後再在其中
選擇落子點。但是,電腦不會像人一樣分析問題,要讓它知道哪是“活三”、哪是“沖四”,就得在棋盤上逐點
計算,一步一步的教它。
先來分析己方的棋型,我們從棋盤左上方出發,向右逐行搜尋,當碰到一個空白點時,以它為中心向左挨個
尋找,假如碰到己方的子則記錄然後繼續,假如碰到對方的子、空白點或邊界就停止尋找。左邊完成後再向右進
行同樣的操作;最後把左右兩邊的記錄合并起來,得到的資料就是該點橫向上的棋型,然後把棋型的編號填入到Co......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.