老調重提,利用SDK實現智慧型五子棋

2021-03-31 08:56:29 字數 3090 閱讀 1799

網上有很多的實現五子棋的演算法,如利用規則法,遞迴法,博弈樹法來實現五子棋的,上次我寫了一篇利用sdk實現迷宮演算法的文章,這次還是同樣的題目,老調重提,我利用的是規則法來實現五子棋的智慧型。不過我個人認為還是博弈樹法還是簡潔。如果讀者對博弈樹有興趣的,可以重讀資料結構中的樹結構的實現這一部分!

這是利用sdk實現的五子棋程式執行介面:

這裡我講出我實現的思路:

第一步,計算出乙個棋盤的五子棋的所有勝利組合。

第二步,計算出玩家的下棋狀態,電腦將會根據玩家的狀態而採取進攻或防守。

第三步,根據第二步的運**況,而出現三種結果,玩家獲勝,電腦獲勝,和局。

第一步,計算勝利的組合

從圖中可以看出,只要五個棋子連續成一直線就可以勝利,這樣我們就可以根據這樣的規則計算出所有的勝利組合,利用組合運算可以算出乙個10 * 10的棋盤的勝利組合可以有192種。即這樣計算,每一行有十個格,計算出連續的五個格的組合,10個格中無論怎樣已經有四個格連續的了,剩下的六個格中每乙個都會是連續的組合,所以c6.1 = 6,共有6種勝利組合,10行共有 60 種勝利組合,10列中也會有 60 種勝利組合, 對角線則這樣計算, 從正對角線開始, 其組合成直線的格可以有 10, 9, 8, 7, 6, 5, 剩下的不足五格,不可能構成勝利組合 c(10 - 4).1 = 6, c(9 - 4).1 = 5, c(8 - 4).1 = 4, c(7 - 4).1 = 3, c(6 - 4).1 = 2, c(5 - 5).1 = 1,由於對稱,即對角線有 6 + ( 5 + 4 + 3 + 2 + 1 ) * 2 = 36, 反對角線同樣為 36。則所有的勝利組合為 36 * 2 + 60 * 2 = 192 種勝利組合,玩家和電腦的所有獲勝都會在這些組合中。

//知道所有的勝利組合狀態,我們可以定義乙個陣列記錄這些組合.

bool barrplayerwin[ 10 ][ 10 ][ 192 ] = ;

bool barr***win[ 10 ][ 10 ][ 192 ] = ;

這是乙個三維陣列, 記錄了在棋盤中所有的勝利組合.如玩家在棋盤 列1 行1的位置,則有三種勝利組合,如圖:

可能為barrplayer[1][1][3] = true,barrplayer[1][1][6] = true,barrplayer[1][1][9] = true如果電腦在標記為綠色的位置的地方放了棋子,則破壞了這種獲勝組合,玩家不可能在這種組合中獲勝,所以把其值設成 false,則電腦可以不用在這兒再放置棋子了,同樣,玩家可以破壞電腦的獲勝組合。

計算所有的勝利的組合在 initwinstatus()函式中,這些**很簡單,所以不講解了,請讀者自已理解這些**!

void initwinstatus()

ncount++;

} // vertical has 60 winning status.

assert( ncount == 60 );

// set the horizontal ***binations winning status.

for ( i = 0; i < 10; i++ )

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

ncount++;

} // horizontal has 60 winning status

assert( ncount == 120 );

// set the positive diagonal winning status.

for ( i = 0; i < 6; i++ )

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

ncount++;

} // positive diagonal has 36 winning status.

assert( ncount == 156 );

// set the negative diagonal winning status.

for ( i = 0; i < 6; i++ )

for ( int j = 9; j > 3; j-- )

ncount++;

} // negative diagonal has 36 winning status.

assert( ncount == 192 );

// who is the first ?

if ( rand() % 2 == 0 )

bplayerdo = true;

else

b***puterdo = true;

}

第二步,電腦計算玩家下棋狀態採取進攻或防守的策略,這是五子棋的關鍵所在,這兒給出實現的偽**.

// 計算玩家的狀態.

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

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

if ( narrboard[ i ][ j ] == noball )

// 計算電腦的狀態, **同上.

.........

// 判斷情況

if ( narr***grades[ i ][ j ] < narrplayergrades[ i ][ j ] )

// 該勝利組合中有可能輸

進攻;

else

防守;

第三步,在第二步中不停地進攻防守,則可以出現三種結果,電腦勝,玩家勝,或和局。

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

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

else

if ( bover )

break;

}

遍歷所有的勝利組合, 如果所屬的組合已經有五顆棋子,有則遊戲結束!這只是簡單地說明我實現的過程,附件中附有五子棋的所有源**,你自已修改這些**,增加功能。

結語

從這裡可以初步了解, ai的其本實現就是要將所有的情況計算出來, 再根據情況而採取相應

的措施。但是這裡的實現只是限於簡單的五子棋規則, 從而把其所有的勝利計算出來, 對於象棋,圍棋等複雜的情況,我們還是需要用博弈樹進行剪枝來找出所有的勝利組合。希望你會喜歡這個遊戲!

老調重彈之整除與實數除

學計算機的同學一定被人問到這樣的問題 1.5除以2等於多少?很多人第一反應就是暴怒,這麼簡單的問題居然還拿來考我,真是豈有此理。小學生都會的啊,等於2.5嘛 等等,好像事情沒有那麼簡單吧?如果這麼簡單的話,為什麼還要拿來問呢?我們來看一下到底等於多少?看到了嗎?它的結果是等於2.太不可思議了吧。但其...

老調重彈之整除與實數除

學計算機的同學一定被人問到這樣的問題 1.5除以2等於多少?很多人第一反應就是暴怒,這麼簡單的問題居然還拿來考我,真是豈有此理。小學生都會的啊,等於2.5嘛 等等,好像事情沒有那麼簡單吧?如果這麼簡單的話,為什麼還要拿來問呢?我們來看一下到底等於多少?看到了嗎?它的結果是等於2.太不可思議了吧。但其...

老調重彈 access注入過主機衛

首先開啟伺服器上安裝了主機衛士的 嘗試在變數id的值後面插入萬惡的單引號,根據報錯,我們可以分析出來,使用的是access資料庫。通過order by檢視當前表有多少個列,發現6的時候報錯,5的時候正常,表明當前表中有5個列 接著試試聯合查詢 duang的一下,就被攔截了 嗚嗚嗚 那只能操出萬能的黑...