五子棋之極大極小

2021-08-09 17:59:23 字數 3511 閱讀 9167

總述:五子棋問題可以化為乙個博弈問題。從開始落子到最後贏,輸或和的每一步落子構成了乙個解,而解空間就是乙個樹。解就是這個樹中的一條路徑,只不過這個解空間的是由電腦和人的共同選擇構成的。我們可以使用極大極小值搜尋來解決這個博弈問題,假設每一步人和電腦都落子在最優上。但是搜尋整個樹是不現實的,16*16!的指數級,所以我們只回溯3步。

將棋盤的棋子儲存在pos[16][16]的陣列上

對於電腦來說每下一步棋,就是找到對自己最有利,即評價函式最大的一步,下一層根據博弈的基礎,對電腦越不利即是對人越有利,即找到評價函式最小的一步。

16*16的棋盤上有一些位置是不會去落子的,我們可以通過乙個getpoint()得到需要下的點,即以該點為中心,7*7的範圍內有子的位置,通過這種方法可以減少運算量。

評價函式即為下完一步之後,電腦與人形成的連成三個,四個,五個等等的評分和之差。評分時,需要對棋盤進行掃瞄,我採用的是將二維的棋盤轉化至一維的陣列上,通過簡單的函式就可以對橫邊,豎邊,斜邊進行計分操作。每一層之間的積分我為它們增加了乙個權重,加強了下面幾層的對於這一層的影響,通過這種方法可以使一些我們熟悉的定式及對於空格的判斷更加準確。

主要資料結構:

pos[16][16]乙個16*16的棋盤,用於記錄當前情況下,棋盤的情況

~~~用於儲存每乙個需要用到的點,包括可進行落子的位置,當前評分最高的位置。最後進行落子時,可通過隨機進行取結果。

~~儲存具體的某乙個點。

主要函式:

1.bool judge(int i1,int i2);判斷下完當前步驟之後,是否贏得了勝利。

bool judge(int i1,int i2)

//豎排

for(int j=(i2-4>0?i2-4:0);j<=(i2+4>16?11:i2);j++)

//正斜線

int i=i1-4;

int j=i2-4;

while(i<0||j<0)

for(;i<=(i1+4>16?11:i1)&&j<=(i2+4>16?11:i2);i++,j++)

//反斜線

i=i1+4;

j=i2-4;

while(j<0||i>15)

for(;i>=0&&j<=(i2+4>16?11:i2);i--,j++)

return false;

}

2. int scoretable(int number,int empty);計分板詳細情況如下

連成五個 100000

連成四個,沒有端點被堵 10000

連成四個,乙個端點被堵 2000

連成三個,沒有端點被堵 1500(可以使連成兩個沒有被堵的三個比連成被堵的四個更有優勢)

連成三個,乙個端點被堵 100

連成兩個,沒有端點被堵 100

連成兩個,乙個端點被堵 10

int scoretable(int number,int empty)  

else if(number==3)

else if(number==2)

else if(number==1&&empty==2)

return 10;

return 0;

}

3. int get_val(vector n,int p);返回某乙個行或列或斜線的評分

int get_val(vectorn,int p)  

//豎排

for(int j=0;j<16;j++)

//上半正斜線

for(int i=0;i<16;i++)

//下半正斜線

for(int j=1;j<16;j++)

//上半反斜線

for(int i=0;i<16;i++)

//下半反斜線

for(int j=1;j<16;j++)

return c_score-p_score;

}

5. int min_max(int depth,int i1,int i2);玩家層進行落子時的函式

int min_max(int depth,int i1,int i2)

vector< pair> v;

getpoint(v);

int len=v.size();

int best=int_max;

for(int i=0;i6. int max_min(int depth,int i1,int i2);電腦落子時的函式

int max_min(int depth,int i1,int i2)

vector< pair> v;

getpoint(v);

int len=v.size();

int best=int_min;

for(int i=0;ibest)

best=tmp;

pos[v[i].first][v[i].second]=0;

}return best;

}

7. bool haszi(int x,int y);乙個位置的7*7範圍內是否有子

bool haszi(int x,int y)
8. void getpoint(~~~);得到棋盤中可以進行落子的位置

void getpoint(vector>& v)

}

9. void result(int& cx,int& cy);得到電腦落子的乙個結果

void result(int& cx,int& cy)

//找出可下棋的點

vector< pair> v;

getpoint(v);

int best=int_min;

int len=v.size();

vector< pair> v2;//預期結果

for(int i=0;ibest)

pos[v[i].first][v[i].second]=0; //假設完之後,該子需要重新置空,恢復原來的樣子

}//從結果中隨機選擇

len=v2.size();

srand((unsigned)time(0));

int i=(int)(rand()%len);

cx=v2[i].first;

cy=v2[i].second;

}

10.main()函式,遊戲進行的主要程序

int main()

return 0;

}

普通的極大極小搜尋,對每個max,min層取的是對該局面的評價,這很大程度上使得第一步對於下面的影響是巨大的,與只看一層的差別不大,這就增大了對於評價函式的構造。我採用的是對於

注:~~~代表的是兩個int型pair的vector

~~代表的是兩個int型的pair

下五子棋的bot 五子棋演算法

include include include include include include jsoncpp json.h c 編譯時預設包含此庫 define n 7 每個節點的分支數 以下為各棋型的識別碼 權重 define win 1 4000 define lose 2 4000 defi...

窮舉五子棋

本想窮舉五子棋必勝點,可惜呀,這貨窮舉太不現實了,寫出來了,根本沒辦法執行出來結果 include include include define rl 17 char s 14 int five rl rl void init void void print void int cs int i,in...

普通 五子棋

五子棋 五子棋是世界智力運動會競技專案之一,是一種兩人對弈的純策略型棋類遊戲,是世界智力運動會競技專案之一,通常雙方分別使用黑白兩色的棋子,下在棋盤直線與橫線的交叉點上,先形成5子連線者獲勝。棋具與圍棋通用,起源於中國上古時代的傳統黑白棋種之一。主要流行於華人和漢字文化圈的國家以及歐美一些地區,是世...