摘要:今天博主將為大家帶來語言入門級小游戲三子棋井字棋的詳細介紹,希望這篇文章對大家能有幫助。在這里,我們使用函數來實現這一功能。
?? ? ??今天博主將為大家帶來C語言入門級小游戲——三子棋(井字棋)的詳細介紹,希望這篇文章對大家能有幫助?。??
? ? 在編程的學習過程中,編寫一些中這樣的小游戲,是非常有樂趣的事情,完成之后會非常非常有成就感,我們需要這樣的小項目來提高對編程學習的信心,培養對編程的興趣,由于博主是一個編程學習的小白,所以這只是三子棋的初級版,此版本只能實現人機對戰,并且電腦隨機下棋,電腦的算法比較低級,在后續的學習中,我會持續更新,不斷對這個小游戲進行優化,期待大家的關注,還有,這篇文章中若有錯誤或不當的地方,歡迎大家指正!?
關于這個項目的代碼,歡迎訪問我的gitee代碼倉庫:
?Living_Amethyst/code2021 - Gitee.com
? 那么正文開始咯!
目錄
為了讓代碼的可讀性更高,思維性更強,我們需要創建三個文件來完成這個項目
作為游戲,菜單是肯定少不了的,這里我們也為三子棋小游戲準備了游戲的菜單
由于一進入游戲,我們首先就要看到菜單,所以這里我們采用do...while循環
我們的菜單需要實現的功能有:
void menu(){ printf("************************/n"); printf("***** 1.play *******/n"); printf("***** 0.exit *******/n"); printf("************************/n");}void test(){ int input = 0; do { menu(); printf("請選擇"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戲/n"); break; default: printf("選擇錯誤/n"); break; } } while (input);}int main(){ test(); return 0;}
? 這里我們創建了test函數和menu函數,為的是讓邏輯更清晰,現在我們的菜單部分就完成了
對于這個游戲菜單,我們能實現的游戲功能有:?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?這是菜單的運行效果
? ? 這張圖大概就是棋盤的樣子,為了實現棋盤,我們需要用到二維數組,在下棋時,我們要將數據存儲到一個字符的二維數組中,我們設定玩家下棋是 " * ",電腦下棋是?‘ # ’
? 通過這個函數,我們實現了棋盤的初始化,我們給數組中每個元素初始化為一個空格
代碼如下?
char board[ROW][COL] = { 0 };//函數聲明void InitBoard(char board[ROW][COL], int row, int col);//函數定義void InitBoard(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++) { board[i][j] = " "; } }}//函數調用InitBoard(board, ROW, COL);
? ?這里有一個小細節,在數組的初始化過程中,我并沒有在[ ]中輸入具體的數字,而是用ROW,COL取代,這是因為通過這樣操作,我們可以用define定義它們為常量,這樣如果我們想修改成五子棋或n子棋,就不用一個一個改了,直接在define定義常量時修改即可?
?
?對棋盤的打印,我我們使用DisplayBoard這一函數來實現,代碼如下:
//函數聲明void DisplayBoard(char board[ROW][COL], int row, int col);//函數定義void DisplayBoard(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++) { 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
?值得一提的是,在函數調用部分我們一開始寫的代碼并不是這個,而是
void DisplayBoard(char board[ROW][COL], int row, int col){ int i = 0; int j = 0; for (i = 0;i < row;i++) { //數據 printf(" %c | %c | %c /n", board[i][0],board[i][1],board[i][2]); //分割行 if (i < row - 1) //第三行數據不用打印分割行 { printf("---|---|---/n"); }
但很快,我們就發現了這個代碼的局限性:
? ? ? ? ?版本1,不方便代碼的改動,如要打印10*10的棋盤,無法完成,只能10*3,也就是我們把這個代碼寫死了
所以我們做了如下的改動,希望大家好好體會兩者的區別
下面展示一下棋盤打印出來的效果!?
?
?是不是有點那個意思了?
接下來我們來實現玩家下棋這一功能。
為了完成這一功能,我們需要注意以下幾點:?
代碼如下:
//函數的聲明void player_move(char board[ROW][COL],int row,int col);//函數的定義void player_move(char board[ROW][COL], int row, int col){ printf("玩家下棋:/n"); 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("該坐標被占用,請重新輸入!/n"); } } else { printf("坐標非法!請重新輸入/n"); } }}//函數的調用 //玩家下棋 player_move(board,ROW,COL); //棋下完要打印 DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL);
與前面的玩家下棋類似,只是這里我們需要電腦隨機下棋,所以我們要用到rand函數獲取隨機值
我們需要創建隨機數,這就需要調用以下頭文件:
同時,我們還需要使用:?
srand((unsigned int)time(NULL)); 來進行初始化
x = rand() % row;
y = rand() % ?col; ? ? 來進行創建坐標的隨機數?
?代碼實現如下
//函數的聲明void player_move(char board[ROW][COL],int row,int col);//函數的定義void computer_move(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("電腦下棋/n"); while (1) { x = rand() % ROW;//取余數3后范圍是0~2 y = rand() % COL;//0~2 if (board[x][y] == " ") { board[x][y] = "#"; break; } } }//函數的調用 //電腦下棋 computer_move(board, ROW, COL); DisplayBoard(board, ROW, COL); //用時間戳生成隨機數srand((unsigned int)time(NULL));
在我們下棋的過程中,由于規則的特殊性,我們需要在玩家和電腦下的每一步后都對比賽的結果進行判斷,確保程序的邏輯正確性。
在這里,我們使用?Is_win()函數?來實現這一功能。
在這一函數中,我們需要實現以下四個邏輯:
- 返回四種不同的狀態
- 玩家贏? ? ?:? 返回"*"
- 電腦贏? ? ?:? 返回"#"
- 平局? ? ? ? ?:? 返回"Q"
- 游戲繼續? :? 返回"C"
首先我們要確立判斷函數再整個游戲主體中的位置和作用,邏輯如下:
void game(){ //數據存儲到一個字符的二維數組中,玩家下棋是" * ",電腦下棋是" # " , char board[ROW][COL] = { 0 };//數組的內容應該是全部空格(二維數組初始化一般是{}) //初始化棋盤 InitBoard(board, ROW, COL); //打印棋盤 DisplayBoard(board,ROW,COL); //下棋 char ret = is_win(board, ROW, COL); 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"); } }
我們在實現Iswin()這一函數時,需要注意以下幾點:
以下是Is-win()函數的實現:
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 ( is_full(board, row, col)==1) { return "Q"; } //繼續 return "C"; }
?這個代碼的缺陷是也只適用于三子棋,后續會進行改進
下面時is_full函數的實現
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; }
最后再看一下游戲整體的邏輯實現
void game(){ //數據存儲到一個字符的二維數組中,玩家下棋是" * ",電腦下棋是" # " , char board[ROW][COL] = { 0 };//數組的內容應該是全部空格(二維數組初始化一般是{}) //初始化棋盤 InitBoard(board, ROW, COL); //打印棋盤 DisplayBoard(board,ROW,COL); //下棋 char ret = is_win(board, ROW, COL); 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.h—— 游戲函數的聲明
#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://繼續---"C"char is_win(char board[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS#include"game.h"void InitBoard(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++) { board[i][j] = " "; } }}// (把每一格看成一組數據,一組一組地打印)//這樣代碼的可擴展性就高了void DisplayBoard(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++) { 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= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == " ") { board[x - 1][y - 1] = "*"; break; } else { printf("該坐標被占用,請重新輸入!/n"); } } else { printf("坐標非法!請重新輸入/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;//取余數3后范圍是0~2 y = rand() % COL;//0~2 if (board[x][y] == " ") { board[x][y] = "#"; break; } } } 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; } 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 ( is_full(board, row, col)==1) { return "Q"; } //繼續 return "C"; }
?test.c? ?—— 測試游戲
#define _CRT_SECURE_NO_WARNINGS#include"game.h"void menu(){ printf("************************/n"); printf("***** 1.play *******/n"); printf("***** 0.exit *******/n"); printf("************************/n");}void game(){ //數據存儲到一個字符的二維數組中,玩家下棋是" * ",電腦下棋是" # " , char board[ROW][COL] = { 0 };//數組的內容應該是全部空格(二維數組初始化一般是{}) //初始化棋盤 InitBoard(board, ROW, COL); //打印棋盤 DisplayBoard(board,ROW,COL); //下棋 char ret = is_win(board, ROW, COL); 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"); } }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);}int main(){ test(); return 0;}
你看,這個電腦玩家是不是有點不太聰明的樣子~
? ? 其實,電腦的”聰明程度“取決于我們程序員的技術水平程度,如果我們給電腦設計更優秀的算法,那它也會更聰明哦?
?
?以上就是三子棋游戲的全部內容,相信大家看到這里應該也能夠獨立的完成屬于自己專有的三子棋游戲了,也相信你在這過程中對編程有了更進一步的認知。
好了,這篇文章就到這里了,歡迎大家點贊評論哦!?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/123078.html
摘要:上一期咱們用語言實現了三子棋的小游戲語言實現三子棋今天我們再來寫個掃雷的游戲,說起掃雷,相信大家都不陌生,可能許多朋友還是玩掃雷的高手。 ? ? ?上一期咱們用C語言實現了三子棋的小游戲? C語言實現三子棋? ? ? ?今天我們再來寫個掃雷的游戲,說起掃雷,相信大家都不陌生,可能許多朋友還是...
摘要:簡單介紹了三子棋原理后接下來為大家講解分步目標及代碼如何實現。電腦下棋我們實現了玩家和電腦的下棋后,我們需要編寫一個函數來判斷雙方的輸贏。我們使用函數來實現這一目標。 目錄 1.三子棋原理 2.分塊代碼實現 3.總結 1.首先向大家介紹一下三子棋的原理 首先我們需要有一個棋盤,初始時棋...
摘要:條消息語言入門三子棋語言實現詳細版的博客博客條消息語言入門三子棋語言實現詳細版的博客博客我們將雷盤初始化為統一的符號。 目錄 1.原理簡介 2.分布目標及代碼實現 3.總結 1.原理簡介 ?首先我們需要一個空的雷盤,在其中隨機埋入十枚雷,當我們排這顆雷時,若此位置為雷,則游戲失敗,若不...
摘要:三子棋目錄一問題介紹三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋 目錄 一、問題介紹 ? ? ? ? 三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋的游戲規則十分的簡單: ...
閱讀 2682·2023-04-25 15:15
閱讀 1322·2021-11-25 09:43
閱讀 1611·2021-11-23 09:51
閱讀 1086·2021-11-12 10:36
閱讀 2888·2021-11-11 16:55
閱讀 962·2021-11-08 13:18
閱讀 734·2021-10-28 09:31
閱讀 2057·2019-08-30 15:47