摘要:前言本篇文章記錄了用語言實現(xiàn)三子棋小游戲,主要目的是對之前語言知識學(xué)習(xí)的鞏固,聯(lián)系各個知識,以及怎么樣實際使用各個知識。效果顯示函數(shù)當(dāng)玩家輸入時,跳入到游戲的實現(xiàn)代碼之中。這里調(diào)用了函數(shù),實現(xiàn)代碼如下由于在這里強(qiáng)制轉(zhuǎn)化為正整數(shù)。
本篇文章記錄了用C語言實現(xiàn)三子棋小游戲,主要目的是對之前C語言知識學(xué)習(xí)的鞏固,聯(lián)系各個知識,以及怎么樣實際使用各個知識。
一、三子棋的游戲規(guī)則
玩家將會看到一個3X3的網(wǎng)格棋盤,默認(rèn)玩家先下棋,電腦后下棋。
規(guī)定:先連成一條直線(3個棋子)的玩家獲勝,行,列,對角線均可。若在棋盤下滿時仍未分出勝負(fù),則為平局
二、使用到的頭文件
#include #include #include
#define ROW 3 #define COL 3
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
//玩家贏 - "*"http://電腦贏 - "#"http://平局 - "Q"http://繼續(xù) - "C"char is_win(char board[ROW][COL],int row,int col);
三、游戲的測試
int main() { test();//調(diào)用test測試函數(shù) return 0;}
void test() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("請選擇:>"); scanf("%d",&input); switch (input) { case 1: game(); break; case 0: printf("退出游戲/n"); break; default: printf("選擇錯誤/n"); break; } } while (input);}
解析test函數(shù)主要構(gòu)成:
i>菜單menu()函數(shù):
void menu() { printf("******************************/n"); printf("***** 1. play ********/n"); printf("***** 0. exit ********/n"); printf("******************************/n");}
實現(xiàn)效果:
?ii>switch case 語句:實現(xiàn)了玩家通過不同輸入選擇實現(xiàn)不同的功能。
效果顯示:
iii>game()函數(shù):當(dāng)玩家輸入1時,跳入到游戲的實現(xiàn)代碼之中。
void game() { // 數(shù)據(jù)存儲,玩家下棋"*",電腦下棋是"#" char board[ROW][COL] = {0};//數(shù)組的內(nèi)容 應(yīng)該是全部空格 InitBoard(board,ROW,COL);// 初始化棋盤 // 打印棋盤 DisplayBoard(board,ROW,COL); //下棋 char ret = 0; while (1) { player_move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != "C") { break; } computer_move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != "C") { break; } } if (ret == "*") { printf("玩家贏/n"); } else if (ret == "#") { printf("電腦贏/n"); } else{ printf("平局/n"); } }
game()函數(shù)里面包括了:打印棋盤函數(shù),初始化棋盤函數(shù),玩家下棋函數(shù),電腦下棋函數(shù),判斷輸贏函數(shù)的調(diào)用,已經(jīng)規(guī)定輸贏的條件,具體每個函數(shù)的實現(xiàn)代碼和問題如下。
注:最后有g(shù)ame()函數(shù)的邏輯順序。
四、游戲的實現(xiàn)
我們首先實現(xiàn)對棋盤的打?。?/p>
我們在頭文件中規(guī)定了 3行3列
#define ROW 3 #define COL 3
自定義函數(shù)DisplayBoard實現(xiàn)對棋盤的打?。?/p>
預(yù)期實現(xiàn)的棋盤模樣:
?我們發(fā)現(xiàn)里面包含了數(shù)據(jù)和分割行,實現(xiàn)代碼:
void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { // 數(shù)據(jù) for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j < col - 1) printf("|"); } printf("/n"); //分割行 if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } } printf("/n"); }}
定義InitBoard()函數(shù),主要實現(xiàn)代碼如下:
void InitBoard(char board[ROW][COL], int row, int col){ int i = 0; int j = 0; for (i = 0; i < row; i++) { //3行 for (j = 0; j < col; j++) { // 3列 board[i][j] = " "; } }}
初始化棋盤全為空格
自定義函數(shù) player_move 實現(xiàn),代碼如下:
void player_move(char board[ROW][COL], int row, int col) { printf("玩家下棋:>"); int x = 0; int y = 0; while (1) { scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == " ") { board[x - 1][y - 1] = "*"; break; } else { printf("該坐標(biāo)被占用,請重新輸入!/n"); } } else { printf("坐標(biāo)非法,請重新輸入!/n"); } }}
這里面包含了很多小問題和解決方案:
1:輸入的坐標(biāo)不在棋盤的范圍內(nèi)怎么辦?
答:使用if else 選擇語句,如果輸入的坐標(biāo)合法,則輸入成功,如果輸入的坐標(biāo)不合法則會提醒“坐標(biāo)非法,請重新輸入!”字樣。
if (x >= 1 && x <= row && y >= 1 && y <= col)
2:輸入的坐標(biāo)在棋盤上已被占用怎么辦?
這個問題我們需要轉(zhuǎn)化成這個問題解決:
i>怎么判斷輸入坐標(biāo)被占用?
答:我們通過對選擇語句if else 對改坐標(biāo)進(jìn)行判斷,由于我們在初始化棋盤時,初始化棋盤全部為空格,如果輸入坐標(biāo)所對應(yīng)的格子是空格,則說明未被占用,如果輸入坐標(biāo)所對應(yīng)的格子不是空格,則說明該格子已經(jīng)被占用。
if (board[x - 1][y - 1] == " ")
ii>如何正確輸入棋子?
如果輸入坐標(biāo)所對應(yīng)的格子是空格,則可以成功輸入,如果不是空格,則會else提醒玩家“該坐標(biāo)被占用,請重新輸入!”字樣。利用while循環(huán)語句可再次輸入正確的未被占用的坐標(biāo)。
自定義函數(shù) computer_move 實現(xiàn),代碼如下:
void computer_move(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("電腦下棋:>/n"); while (1) { x = rand() % ROW; // 0 ~ 2 y = rand() % COL; // 0 ~ 2 if (board[x][y] == " ") { board[x][y] = "#"; break; } }}
這里也包含了幾個小問題和解決方案:
1:這里電腦的輸入是隨機(jī)輸入,如何實現(xiàn)?
答:這里我們并非是真的隨機(jī)值,只是利用了時間戳,由于時間在每時每刻的改變,所以在不同的時間,經(jīng)過處理后的時間我們也無法知道,可當(dāng)做隨機(jī)值使用。這里調(diào)用了time函數(shù),實現(xiàn)代碼如下:
#include srand((unsigned int)time(NULL));
由于在這里強(qiáng)制轉(zhuǎn)化為正整數(shù)。
2:如何控制電腦隨機(jī)輸入的值合法?
答:這個問題的意思是,如果不對這個隨機(jī)值進(jìn)行處理,那么這個值很可能超出棋盤,所以要對這個值進(jìn)行控制,由于棋盤規(guī)定3行3列,數(shù)組下標(biāo)由0開始,所以隨機(jī)值只要在0~2之內(nèi)即可。所以我們對這個隨機(jī)值進(jìn)行取模(取余數(shù))處理即可解決此問題:
x = rand() % ROW; // 0 ~ 2y = rand() % COL; // 0 ~ 2
為了區(qū)分玩家和電腦的棋子不同,在此規(guī)定
玩家使用 " * " , 電腦使用 " #?"
因為這里電腦輸入坐標(biāo)均為隨機(jī)值,所以不具有判斷的能力,讀者可以思考一種優(yōu)化算法,寫出一種最快贏下比賽的算法。而不至于出現(xiàn)可能都已經(jīng)一行出現(xiàn)2個棋子了,隨機(jī)值可能再下到別處的情況(哈哈 人工“智障”)。
實現(xiàn)代碼:
char is_win(char board[ROW][COL], int row, int col) { int i = 0; // 三行的判斷 for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != " ") return board[i][1]; } // 三列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != " ") return board[1][i]; } //對角線 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != " ") { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != " ") { return board[1][1]; } //判斷平局 if (1 == is_full(board, row, col)) { return "Q"; } //繼續(xù) return "C";}
游戲規(guī)定,首先完成一行或者一列或者對角線的玩家獲勝,在此我們只需要進(jìn)行三行,三列,對角線的判斷以及平局的判斷,游戲繼續(xù)判斷。具體是玩家贏還是電腦贏,我們在測試函數(shù)test中有規(guī)定,不同的玩家對應(yīng)不同的字符,在此規(guī)定:
三行的判斷:
for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != " ") return board[i][1]; }
三列的判斷:
for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != " ") return board[1][i]; }
兩條對角線的判斷:
//第一條對角線if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != " ") { return board[1][1]; }//第二條對角線if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != " ") { return board[1][1]; }
平局的判斷:
游戲規(guī)定,當(dāng)棋盤下滿時,還未分出勝負(fù)時,則為平局。
因此首先我們思考如何判斷棋盤是否下滿?
答:在這里我們通過返回值的數(shù)字來判斷是否下滿
自定義函數(shù) is_full函數(shù),具體代碼:
int is_full(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == " ") { return 0; } } } return 1;}
代碼邏輯:我們通過返回值來判斷棋盤是否下滿,
如果未被下滿,則返回值是0(return 0 )
如果下滿我們將返回1(return 1)
小問題:我們?nèi)绾闻袛嗍欠裣聺M?
我們遍歷數(shù)組的過程中,如果發(fā)現(xiàn)還有空格存在,說明棋盤還沒有被下滿,我們立刻返回0,否則說明棋盤沒有空格存在,說明已經(jīng)下滿,返回1.
所以我們就可以通過返回值判斷平局,代碼如下:
if (1 == is_full(board, row, col)) { return "Q"; }
如果返回值 == 1 說明 棋盤被下滿 我們返回字符? " Q " (我們剛剛已經(jīng)規(guī)定Q為平局)
五、game()函數(shù)
我們再次將game()函數(shù)調(diào)出進(jìn)行詳解:
void game() { // 數(shù)據(jù)存儲,玩家下棋"*",電腦下棋是"#" char board[ROW][COL] = {0};//數(shù)組的內(nèi)容 應(yīng)該是全部空格 InitBoard(board,ROW,COL);// 初始化棋盤 // 打印棋盤 DisplayBoard(board,ROW,COL); //下棋 char ret = 0; while (1) { player_move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != "C") { break; } computer_move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != "C") { break; } } if (ret == "*") { printf("玩家贏/n"); } else if (ret == "#") { printf("電腦贏/n"); } else{ printf("平局/n"); } }
根據(jù)代碼發(fā)現(xiàn)主要邏輯順序:
?這是game()函數(shù)內(nèi)部的主要邏輯順序,每一步所對應(yīng)的函數(shù)調(diào)用和判斷也均在圖中顯示。
六、演示
完整代碼: 完整代碼我放在我的Gitee倉庫內(nèi),鏈接如下:
https://gitee.com/Yaulixingyu/c-language/tree/master/三子棋/三子棋
游戲演示:
?
以上就是我對三棋子小游戲的實現(xiàn),有興趣的小伙伴可以對代碼進(jìn)行優(yōu)化,可實現(xiàn)五子棋等,也可以對電腦下棋記性優(yōu)化,使電腦不再人工“智障”。
哈哈哈~由于文章較長,感謝各位小伙伴的觀看,由于本人的技術(shù)水平有待提高,如果遇到錯誤也請及時指正。如果各位小伙伴覺得不錯的話,可以點贊關(guān)注一波~多謝多謝
下期預(yù)告:掃雷? 小游戲
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/123187.html
摘要:簡單介紹了三子棋原理后接下來為大家講解分步目標(biāo)及代碼如何實現(xiàn)。電腦下棋我們實現(xiàn)了玩家和電腦的下棋后,我們需要編寫一個函數(shù)來判斷雙方的輸贏。我們使用函數(shù)來實現(xiàn)這一目標(biāo)。 目錄 1.三子棋原理 2.分塊代碼實現(xiàn) 3.總結(jié) 1.首先向大家介紹一下三子棋的原理 首先我們需要有一個棋盤,初始時棋...
摘要:三子棋目錄一問題介紹三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋 目錄 一、問題介紹 ? ? ? ? 三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋的游戲規(guī)則十分的簡單: ...
摘要:今天博主將為大家?guī)碚Z言入門級小游戲三子棋井字棋的詳細(xì)介紹,希望這篇文章對大家能有幫助。在這里,我們使用函數(shù)來實現(xiàn)這一功能。 ?? ? ??今天博主將為大家?guī)鞢語言入門級小游戲——三子棋(井字棋)的詳細(xì)介紹,希望這篇文章對大家能有幫助?。?? ? ? 在編程的學(xué)習(xí)過程中,編寫一些中這樣...
摘要:文章目錄三子棋的設(shè)置的內(nèi)容設(shè)置的設(shè)置棋盤的內(nèi)容棋盤以及棋盤的初始化打印棋盤下棋步驟玩家下棋電腦下棋判斷是否勝利三子棋三子棋的規(guī)則是在的棋盤里,雙方輪流下子以和表示,先將個子連成一條線橫豎斜都可以的一方獲勝下面是三子棋語 ...
閱讀 3559·2023-04-25 19:56
閱讀 1672·2021-11-12 10:36
閱讀 1787·2021-11-08 13:19
閱讀 1548·2019-08-30 14:06
閱讀 3037·2019-08-30 11:01
閱讀 1726·2019-08-29 13:23
閱讀 2741·2019-08-29 11:18
閱讀 3428·2019-08-26 13:35