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