五子棋人機博弈
五子棋,人與人之間博弈,我們不用考慮太多,都是玩家自動思考。
但是如果我們要玩一個單機的五子棋,實現人機的對戰,那么我就得“幫”電腦考慮下走哪步了。
實現的方法大概有三種:
最大權值法
決策樹法
機器學習訓練
這里我們主要針對第一種方法討論下,大致思路如下:
我們繪制好一個棋盤后,假定大小為 15*15;
下棋之前,對於棋盤中的每個空位,我們每都替電腦人“掂一掂”下在哪里合算;(估權過程)
對每個空位按照規則都計算完權重,我們找出權重最大的位置,此位置就是npc落子位置
那么現在的問題就是,這個權重的計算規則是怎樣的呢?
首先,我們思考一下人是怎么下子的。
當該位置四周為空時,這個位置落子可能就不是那么有意義;
我們最大可能地去實現將棋子相連,若該位置四周已出現一條連線,則連子數越多,該子越重要
就算一條線有很多子已經相連,如果該線的一端被堵住,那么該線的重要程度降低,我們稱之為眠連,otherwise,兩端都沒堵住我們稱之為活連。
現在我們來將棋子相連的情況進行下歸類賦權
空子位置我們用 “0” 表示,白子用“2”表示,黑子用“1”表示;
我們主要分為以下幾種情況:
定義
棋子相連情況
權值
活一連
010、020
40
活二連
0110、0220
400
活三連
01110、02220
3000
活四連
011110、022220
10000
眠一連
012、021
20
眠二連
0112、0221
200
眠三連
01112、02221
500
眠四連
011112、022221
3000
主要被分為了以上幾類,當然可以考慮更多以使你的npc更加“智能”;
現在考慮算法
對於每個空位,我們從四個方向進行考察:
水平
豎直
左斜
右斜
我們以水平方向為例進行代碼考察:
int go[row][column]; //記錄每個點的落子情況
int weightarr[row][column]; //記錄每個空位的權值
for piece in chessboard{
if(piece為空){
key1="0"; //記錄空位左邊連子情況
key2="0"; //記錄空位右邊連子情況
(i,j)為空位坐標
ux=i;uy=j; //(ux,uy)記錄左邊連子邊界
dx=i;dy=j; //(dx,dy)記錄右邊邊界
first1=0;
first2=0;
//first1 記錄空位左邊第一個子顏色,first2記錄右邊第一個顏色
//while的目的在於找到最多的顏色相同的連線
while(左邊不越界){
int first=go[i-1][j].color;
first1=first;
if(first==0) break; //如果空位相鄰也為空,退出
else { //如果不為空位
--ux;
if(顏色和first相同) {
key1+=go[ux][uy].color;
}
else {
key1+=go[ux][uy].color;
break;
}
}
}
while(右邊不越界){
... //和上面同理
}
value1=左邊連線權值;
value2=右邊連線權值;
if(左右連線顏色相同) 權值翻倍;
weightarr[i][j]+=該方向權值;
//同理,依此計算 左斜,右斜,豎直情況;
}
}
要注意的是,因為對於每個大方向,比如說水平方向,我們以該空位做間斷點分了水平左和水平右,當水平左和水平右的顏色相同時,權值注意要加強,因為比如說隔開的2個黑子和1個黑子填上空位可以變成4個黑子;
大家可以具體自己重新設置權值,添加更多情況。
我們將具體實現代碼放在github中,供大家參考:
https://github.com/Gray-way/Gobang