五子棋核心演算法

2021-05-11 12:37:04 字數 3638 閱讀 1224

五子棋是一種受大眾廣泛喜愛的遊戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這裡設計和實現了乙個人機對下的五子棋程式,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜尋發現最好的下子位置。介紹五子棋程式的資料結構、評分規則、勝負判斷方法和搜尋演算法過程。

一、相關的資料結構

關於盤面情況的表示,以鍊錶形式表示當前盤面的情況,目的是可以允許使用者進行悔棋、回退等操作。

clist steplist;

其中step結構的表示為:

struct step

int  m; //m,n表示兩個座標值

int  n;

char side; //side表示下子方

以陣列形式儲存當前盤面的情況,

目的是為了在顯示當前盤面情況時使用:

char fivearea[five_max_line][five_max_line];

其中five_max_line表示盤面最大的行數。

同時由於需要在遞迴搜尋的過程中考慮時間和空間有效性,只找出就當前情況來說相對比較好的幾個盤面,而不是對所有的可下子的位置都進行搜尋,這裡用變數countlist來表示當前搜尋中可以選擇的所有新的盤面情況物件的集合:

clist countlist;

其中類cboardsituiton為:

class cboardsituation

clist  steplist; //每一步的列表

char fivearea[five_max_line][five_max_line];

struct step machinestep;    //機器所下的那一步

double value;  //該種盤面狀態所得到的分數

二、評分規則

對於下子的重要性評分,需要從六個位置來考慮當前棋局的情況,分別為:-,¦,/,/,//,//

實際上需要考慮在這六個位置上某一方所形成的子的布局的情況,對於在還沒有子的地方落子以後的當前局面的評分,主要是為了說明在這個地方下子的重要性程度,設定了乙個簡單的規則來表示當前棋面對機器方的分數。

基本的規則如下:

判斷是否能成5, 如果是機器方的話給予100000分,如果是人方的話給予-100000 分;

判斷是否能成活4或者是雙死4或者是死4活3,如果是機器方的話給予10000分,如果是人方的話給予-10000分;

判斷是否已成雙活3,如果是機器方的話給予5000分,如果是人方的話給予-5000 分;

判斷是否成死3活3,如果是機器方的話給予1000分,如果是人方的話給予-1000 分;

判斷是否能成死4,如果是機器方的話給予500分,如果是人方的話給予-500分;

判斷是否能成單活3,如果是機器方的話給予200分,如果是人方的話給予-200分;

判斷是否已成雙活2,如果是機器方的話給予100分,如果是人方的話給予-100分;

判斷是否能成死3,如果是機器方的話給予50分,如果是人方的話給予-50分;

判斷是否能成雙活2,如果是機器方的話給予10分,如果是人方的話給予-10分;

判斷是否能成活2,如果是機器方的話給予5分,如果是人方的話給予-5分;

判斷是否能成死2,如果是機器方的話給予3分,如果是人方的話給予-3分。

實際上對當前的局面按照上面的規則的順序進行比較,如果滿足某一條規則的話,就給該局面打分並儲存,然後退出規則的匹配。注意這裡的規則是根據一般的下棋規律的乙個總結,在實際執行的時候,使用者可以新增規則和對評分機制加以修正。

三、勝負判斷

實際上,是根據當前最後乙個落子的情況來判斷勝負的。實際上需要從四個位置判斷,以該子為出發點的水平,豎直和兩條分別為 45度角和135度角的線,目的是看在這四個方向是否最後落子的一方構成連續五個的棋子,如果是的話,就表示該盤棋局已經分出勝負。具體見下面的圖示:

四、搜尋演算法實現描述

注意下面的核心的演算法中的變數currentboardsituation,表示當前機器最新的盤面情況, countlist表示第一層子節點可以選擇的較好的盤面的集合。核心的演算法如下:

void maindealfunction()

value=-maxint; //對初始根節點的value賦值

calseveralgoodplace(currentboardsituation,countlist);

//該函式是根據當前的盤面情況來比較得到比較好的可以考慮的幾個盤面的情況,可以根據實際的得分情況選取分數比較高的幾個盤面,也就是說在第一層節點擊擇的時候採用貪婪演算法,直接找出相對分數比較高的幾個形成第一層節點,目的是為了提高搜尋速度和防止堆疊溢位。

pos=countlist.getheadposition();

cboardsituation* pboard;

for(i=0;ivalue=search(pboard,min,value,0);

value=select(value,pboard->value,max);

//取value和pboard->value中大的賦給根節點

for(i=0;ivalue)

//找出那乙個得到最高分的盤面

currentboardsituation=pboard;

playermode=min; //當前下子方改為人

break;

其中對於search函式的表示如下:實際上核心的演算法是乙個剪枝過程,其中在這個搜尋過程中相關的四個引數為:(1)當前棋局情況;(2)當前的下子方,可以是機器(max)或者是人(min);(3)父節點的值oldvalue;(4)當前的搜尋深度depth。

double search(cboardsituation&

board,int mode,double oldvalue,int depth)

clist  m_deeplist;

if(deptholdvalue))==    true)

if(mode==max)

value=select(value,search(successor

board,min,value,depth+1),max);

else

value=select(value,search(successor

board,max,value,depth+1),min);

return value;

else

if ( goal(board)<>0)

//這裡goal(board)<>0表示已經可以分出勝負

return goal(board);

else

return evlation(board);

注意這裡的goal(board)函式是用來判斷當前盤面是否可以分出勝負,而evlation(board)是對當前的盤面從機器的角度進行打分。

下面是select函式的介紹,這個函式的主要目的是根據 playermode情況,即是機器還是使用者來返回節點的應有的值。

double select(double a,double b,int mode)

if(a>b && mode==max)¦¦ (a< b && mode==min)

return a;

else

return b;

五、小結

在windows作業系統下,用vc++實現了這個人機對戰的五子棋程式。和國內許多只是採用規則或者只是採用簡單遞迴而沒有剪枝的那些程式相比,在智力上和時間有效性上都要好於這些程式。同時所討論的方法和設計過程為使用者設計其他的遊戲(如象棋和圍棋等)提供了乙個參考

五子棋的核心演算法

五子棋是一種受大眾廣泛喜愛的遊戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這裡設計和實現了乙個人機對下的五子棋程式,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜尋發現最好的下子位置。介紹五子棋程式的資料結構 評分規則 勝負判斷方法和搜尋演算法過程。一 相關的資料結構 關於盤面情況的表示...

五子棋的核心演算法

五子棋是一種受大眾廣泛喜愛的遊戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這裡設計和實現了乙個人機對下的五子棋程式,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜尋發現最好的下子位置。介紹五子棋程式的資料結構 評分規則 勝負判斷方法和搜尋演算法過程。一 相關的資料結構 關於盤面情況的表示...

五子棋的核心演算法

五子棋是一種受大眾廣泛喜愛的遊戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這裡設計和實現了乙個人機對下的五子棋程式,採用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜尋發現最好的下子位置。介紹五子棋程式的資料結構 評分規則 勝負判斷方法和搜尋演算法過程。一 相關的資料結構 關於盤面情況的表示...