五子棋AI設計 從門外到門內不得不說的事兒2

2021-06-07 00:36:29 字數 3000 閱讀 2738

第二天:防守,堵堵堵

為了提高對五子棋遊戲的感性認識,我又在網上找了幾個寫的很好的五子棋遊戲,與電腦進行了若干次對弈。作為乙個門外漢,防守總是最好的選擇。那麼在什麼條件下防守,在什麼位置防守,這些位置如何確定……在這一系列的問題的驅動下,我開始學習模擬物件的ai部分。

首先我選擇了總是防守,所以在這一天,我的第乙個問題解決了。那麼在什麼位置放手呢?

之前定義了棋盤用points[i][j]表示,那麼最直觀的想法是看看棋盤上的棋子,可是棋盤既有白子又有黑子,還有空位。怎麼判斷呢?好吧,從ai的角度出發,他現在要做的事情是:在當前棋盤狀態選擇乙個合法位置——空位,然後在該位置出招。那麼既然是在空位置出招,那麼是不是評估棋盤上的空位置來指導出招就可以了?

作為門外漢我現在能夠想到的就這麼多了,好吧先不管3721,走起。

如何評估棋盤上的空位?

為了大家看起來方便,我先展示乙個7*7的棋盤,示意一下。人先執黑,電腦後手執白,現在輪到電腦出招。棋盤如下

1234567

10000000

20000000

30021000

40001000

50000000

60000000

70000000

那麼有子周圍的空位置中,(2,4)向下看有乙個2連,在(5,4)向上看有乙個2連,在其他位置看到的都是1連。好了,從防守的角度出發,現在最危險的位置是(2,4)和(5,4)。通過這次觀察,我們可以得到一種評估方法,那就是列舉棋盤上的每個空位,然後統計其8個方向上,相同顏色的棋子連成一線的棋子的個數。

為什麼是8個方向?

因為空位填上子後,可能將以前的陰線(可能連成一線的線)變成陽線(已經連成一線的線)。因此,我們要在空位置上向八個方向都看看,看看這個位置能夠連成多少條陽線,如果連成的陽線越多,陽線中棋子的數目越多,那麼這個空位的威脅就越大。

定義int qiju[16][16][8][2]表示棋盤某個位置某個方向某種顏色的棋子連成一線的棋子的個數

定義int a1[16][16], a2[16][16]表示棋盤上某空位的評分。

如何評分呢?我們先考慮一線式的吧,就是橫、豎、左斜、右斜這四種。定義int t1 = qiju[i][j][k][0]+qiju[i][j][k+4][0]表示,涵蓋了空位在某一方向上一側或兩側連成一線的棋子數目。

if t1 >= 4 a1[i][j] += 10000000;

if t1 == 3 a1[i][j] += 100000;

if t1 == 2 a1[i][j] += 1000;

if t1 == 1 a1[i][j] += 10;

同理可以計算a2。

好了在a1和a2中找到最大值的位置,如果人執黑,那麼ai就用a1的最大值的位置作為落子的位置,如果ai執黑,那麼ai就用a2的最大值的位置作為落子的位置。ai就可以成功的封堵住對自己威脅最大的位置,完成防守。

可是ai只會防守怎麼行,好吧,那麼我們只能重新考慮第乙個問題將ai定義為攻守兼備,在什麼條件下進攻呢,欲知後事如何,且聽下回分解。

--------------------分割線--------------------

ai的**如下,

void cwuziqi::ai_1( const int points[16][16], bool first, int oldp[16][16], int newp[16][16], int *nx, int *ny )

fillmatrix( qiju, 0 );

fillmatrix( a1, 0 );

fillmatrix( a2, 0 );

howmanyinline( oldp, qiju );

valuethechessboard*****( oldp, qiju, a1, a2 );

//rintmatrix( qiju );

//printmatrix( oldp );

/****************算出分數最高的空位,填寫座標*********************/

for( i = 1; i <= 15; i++ )

for( j = 1; j <= 15; j++ )

// black

} for( i = 1; i <= 15; i++ )

for( j = 1; j <= 15; j++ )

// white

} if ( first )

else

*nx = x; *ny = y;

}

統計函式如下,

void cwuziqi::howmanyinline( const int oldp[16][16], int qiju[16][16][8][2] )

; int dy[8] = ;

/****************為雙方填寫棋型表************/

for ( i = 1; i <= 15; i++ ) // col

for ( j = 1; j <= 15; j++ ) // row

if ( oldp[i][j] == 0 )

qiju[i][j][k][0] = cnt;

// white

cnt = 0;

tx = i;

ty = j;

for ( t = 0; t < 5; t++ )

qiju[i][j][k][1] = cnt;}}

}

最最原始的、*****陰線評估函式如下

void cwuziqi::valuethechessboard*****( const int points[16][16], int qiju[16][16][8][2], int a1[16][16], int a2[16][16] )

a1[i][j] = win; // black

win = 0;

for ( k = 0; k < 4; k++ ) // direction

a2[i][j] = win; // white

}}}

五子棋AI設計 從門外到門內不得不說的事兒7

第7天 結 7作為乙個神奇的數字,許許多多具有特殊意義的事情往往會發生在第7日。作為乙個小 課程內的五子棋系列就在這裡作結吧。從門外到門裡,雖然只有一步之遙,但是我們還是走了好幾天。簡單回顧一下我們的歷程 第一天 ai 乙個稱不上ai的ai 第二天 防守,堵堵堵 陰線評估器 第三天 進攻防守,視情況...

五子棋 AI篇

效果圖 贏法陣列 var wins 第count種贏法 var count 0 贏法的統計陣列 var mywin var computerwin 結束標識 var gameover false var chess document.getelementbyid chess var me true ...

遊戲 五子棋 與AI

然後ai下棋時,把每個能下的地方都下一次,求個己方與對方的期望值,用個微妙的比較方法 既要考慮到己方的期望,也要考慮到對方的情況 找出期望值最好的那個點,就下那裡了。然後不一會兒我就寫出了乙個 一代 ai,不過我發現有問題,這一代中函式 val 中還沒有那個 y 導致雙方的優先度基本相當,後來我就想...