個人對五子棋的程式設計的幾個難點的思考和理解

2021-10-06 12:40:31 字數 3721 閱讀 6226

本人在對簡單五子棋程式設計的過程中的幾個難點的個人思考和理解, 當然沒到使用極大值極小值演算法和alpha-beta剪枝的那種高階演算法的程度, 只是能夠使用最基本的c語言知識來盡可能的進行合理的模擬。在這過程中會有幾個難點,寫在這裡便於理解思考:

首先面臨的難點就是棋盤的設定,暫且不談使用呼叫window.h 來實現乙個完美的五子棋封面,僅僅通過終端視窗來實現棋盤的展現難免需要我們有一定的想象力,我們可以通過乙個16 * 16的「 * 」 陣來展現屬於自己設計的棋盤,當然棋盤的設計是由你自己決定,你完全可以使用「 + 」來代替 「 * 」 (實際上使用「 + 」 似乎效果更好一點…)實際的效果類似是這樣的:

在這裡我利用的是「 * 」來構造的棋盤,當然你也可以使用「 + 」 來完成棋盤的構造。

這裡給出我構造這種「簡陋」棋盤的**塊:

void initboard(void)/*定義 初始化棋盤 函式*/

如你所見,簡單的利用while 迴圈而已,當然我是用函式封裝了**塊,這麼做的目的是為了**的簡潔性以及可讀性。(實際上之後講到的一些功能都是通過函式封裝過的)這裡用了乙個小技巧:

while (getchar()!='\n')/*清除快取(清除回車符號)*/

continue;

你或許問這段是想幹嘛用的,是否有點多此一舉了,然而不僅不多此一舉,反而大有用處,它為了當你在從鍵盤輸入a之後輸入回車, 防止計算機接收到的是你輸入的回車而不是你想讓計算機接收的a。

接著比較重要的的就是這個清屏函式:

#include...

...system("cls");

當然,前面你必須有加標準庫標頭檔案。

void playchess(void)/*定義 開始走棋 函式*/

while(board[i][j]!=0)

board[i][j]=turn%2==1?1:2;

system("cls");/*重新整理棋盤*/

displayboard();

if(winner(i,j))/*判斷輸贏*/

}

在這裡我想到了幾點需要解決的:

棋子不能超出棋盤邊界:

這一點應該不用過多解釋吧,不解決人家還以為你寫了個bug

這一點再解決時的**具體是這樣的:

#define board_lim (i>=1 && i<=n && j>=1 && j<=n)

....

....

while(!board_lim)

如你所見,我用了乙個簡單的巨集定義不至於到後面寫起來太麻煩,當然也是為了**的可讀性。原理也很簡單,while 語句保證讓玩家輸入棋子座標超出邊界時讓他重複輸入知道他輸入正確(不超出邊界)

如果某個位置有棋子,當然就不能再次在那個位置下棋:

這一點也是應該想到的,但是並不難。具體**是這樣的:

while(board[i][j]!=0)

什麼時候輪到誰下棋:

這個難點剛開始想似乎真的不懂怎麼整,不過我自己使用的是用乙個turn變數來計算回合,賦初值turn = 0;之後每回合結束累加一次,也就是說,玩家一下棋是turn是個偶數(能被2整除),玩家二下棋時turn是個奇數(不能被2整除):

board[i][j] = turn % 2 == 1 ? 1 : 2;
當你真正想通玩家對戰並完成**開始考慮人機對戰的時候,你發現並不是想象中的那麼相似,或者說,容易。因為就目前的個人能力來說還無法做到使用理論上的各種演算法(諸如比較經典的專門針對五子棋等棋類博弈問題的極大值極小值演算法,加上alpha-beta剪枝演算法優化),我們盡可能地想讓計算機在跟我們下棋對戰時不至於看起來那麼的笨,這就需要我們解決另外一些難點,這裡先給出**塊:

void playchess_c(void)/*定義 人機下棋 函式*/

while (board[i][j] != 0)

board[i][j] = 1;

computerjudge(i, j);

//computerdefense(i, j);

system("cls");/*重新整理棋盤*/

displayboard();

} else if (t == 2) //電腦走棋

if (winner( i, j) == 1)/*判斷輸贏*/

}

(看起來明顯比玩家對戰的**多了不少)

計算機在哪下棋:

在哪下棋的問題, 我們優先考慮的是利用隨機數來生成:

else if (t == 2)												//電腦走棋

當然我不敢保證計算機能夠聰明的按部就班的盡力連成五子,但至少能保證的時他能下棋。

2. 如何讓電腦變得「聰明」:

在不會使用高階的演算法的情況下想讓計算機下棋能夠變得聰明似乎不切實際,但我們還是盡力的想讓它看起來不是那麼的笨,我們根據輸贏的危機感,從最簡單的情況開始考慮的話,當玩家快要連成五子時(橫豎斜對角線四子),我們至少要讓計算機想到要努力堵住玩家的下一步勝利:

int computerjudge(int x, int y)/*定義 電腦判斷 函式*/

void computerdefense(int i,int j)

else if (board[i + 1][j] == 1)

else if (board[i][j - 1] == 1)

else if (board[i][j + 1] == 1)

else if (board[i - 1][j + 1] == 1)

else if (board[i + 1][j - 1] == 1)

else if (board[i + 1][j + 1] == 1)

else if (board[i - 1][j - 1] == 1)

}

這是我個人能夠想到的最笨的方式讓計算機變得「聰明」的方式了,說實話,**看起來真的很冗長(甚至有點笨重),但至少還算是變」聰明「讓它看起來真的不是那麼呆。

4. 一點額外的想法:我甚至想過通過修改計算機的下棋方式(隨機數生成)來讓計算機更加智慧型,比如我讓第一步棋隨機數生成,接下來的幾步棋在第一步棋周圍布置(上下左右),接著第三步棋在第二步棋周圍布置,但實際的能力並沒有做到那裡。

相對於前面兩個難點,判斷輸贏函式似乎並不是那麼的難,只需要判斷橫豎斜對角線是否連成五子來定輸贏,這裡直接給出**塊:

int winner(int x, int y)/*定義 判斷輸贏 函式*/

if (winner( i, j) == 1)/*判斷輸贏*/

csdn社群:

維基中文映象:

《一種 改進 的威脅空 間搜尋演算法》(湖南文理學院報(自然科學報)2023年9月 第22卷 第3期)

alpha-beta剪枝優化的極大值極小值演算法講解**:

春季網(spring):

stack overflow問答社群:

cs 161複習筆記:帶有alpha-beta剪枝的minmax:

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

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

五子棋Pro 最好玩的五子棋遊戲

五子棋是一種兩人對弈的純策略型漢族棋類益智遊戲,棋具與圍棋通用,由中國古代漢族人發明,起源於中國上古時代的傳統黑白棋種之一。主要流行於華人和漢字文化圈的國家以及歐美一些地區。容易上手,老少皆宜,而且趣味橫生,引人入勝 不僅能增強思維能力,提高智力,而且富含哲理,有助於修身養性。1 多種遊戲模式 1 ...

程式設計娛樂之五子棋

奉上五子棋 include using namespace std const int x 21 棋盤行數 const int y 21 棋盤列數 char p x y 定義棋盤 int m 0 定義臨時點,儲存輸入座標 int n 0 void display 輸出棋盤 else if p m n...