C語(yǔ)言掃雷排雷小游戲?qū)崿F(xiàn)全程
test.c
在這個(gè)文件中,我們主要是完成游戲邏輯的測(cè)試,在這里我們要注意的點(diǎn),我們建立了二個(gè)數(shù)組,mine數(shù)組我們用來存放布置雷的信息,show數(shù)組存放排查出雷的信息。本次排雷區(qū)域是9*9的格子,為了防止數(shù)組出現(xiàn)越界,我們特意把數(shù)組的下標(biāo)定義大點(diǎn)變?yōu)?1*11。
#define _CRT_SECURE_NO_WARNINGS #include"game.h" void game() { char mine[ROWS][COLS] = { 0 };//存放布置雷的信息 char show[ROWS][COLS] = { 0 };//存放排查出雷的信息 //初始化棋盤 InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*'); //打印棋盤 DisplayBoard(show, ROW, COL); //設(shè)置雷 SetMine(mine, ROW, COL); //找雷 /*DisplayBoard(mine, ROW, COL);*///開局顯示雷的位置 FindMine(mine,show, ROW, COL); } void menu() { printf("*************************\n"); printf("****** 1.play *****\n"); printf("****** 0.exit *****\n"); printf("*************************\n"); } int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("請(qǐng)選擇>: "); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戲\n"); break; default: printf("選擇錯(cuò)誤,請(qǐng)重新選擇:>\n"); } } while (input); return 0; }
game.h
這個(gè)文件,我們用來實(shí)現(xiàn)游戲所用頭文件的包含,游戲常量的定義,函數(shù)的聲明。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<time.h> #include<stdlib.h> //定義棋盤數(shù) #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 //定義雷數(shù) #define EASY_COUNT 10 //函數(shù)的聲明 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); void DisplayBoard(char board[ROWS][COLS], int row, int col); void SetMine(char mine[ROWS][COLS], int row, int col); void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col); void UnfoldMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col, int* win);
game.c
在這里,我們實(shí)現(xiàn)掃雷游戲的整體過程,我們可以分為:初化掃雷區(qū),打印掃雷區(qū),設(shè)置雷和排雷。
#define _CRT_SECURE_NO_WARNINGS #include"game.h" //初化掃雷區(qū) void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; int j = 0; for (i = 0;i < rows;i++) { for (j = 0;j < cols;j++) { board[i][j] = set; } } } //打印掃雷區(qū) void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf("--------掃雷游戲--------\n"); //打印列提示數(shù) for (j = 0;j <= col;j++) { printf("%d ", j); } printf("\n"); for (i = 1;i <= row;i++) { printf("%d ", i);//打印行提示數(shù) for (j = 1;j <=col;j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("---------掃雷游戲-------\n"); } //設(shè)置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1;//生成0~9之間的數(shù) int y = rand() % col + 1;//生成0~9之間的數(shù) if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //返回周圍雷的個(gè)數(shù) int get_mine_count(char board[ROWS][COLS], int x, int y) { return ( board[x - 1][y] + board[x + 1][y] + board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] + board[x - 1][y + 1] + board[x][y + 1] + board[x + 1][y + 1] - 8 * '0'); } //展開一片沒有雷的地區(qū),用遞歸實(shí)現(xiàn) //遞歸結(jié)束的條件: //1 該坐標(biāo)不是雷 //2 該坐標(biāo)不是空格(防止死遞歸) void UnfoldMine(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y,int row,int col,int* win) { if ((show[x][y]!=' ' &&mine[x][y]!='1')|| (show[x][y]) == '#') { int count = get_mine_count(mine, x, y); if (count == 0) { show[x][y] = ' ';//無雷設(shè)置為空格 (*win)--;//無雷的位置減1 int i = 0; int j = 0; for (i = -1;i <= 1;i++) { for (j = -1;j <= 1;j++) { UnfoldMine(mine, show, x + i, y + j, row, col, &win); } } } //不符合遞歸的條件 else { show[x][y] = count + '0'; (*win)--; } } } //排雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int m = 0;//標(biāo)記的橫坐標(biāo) int n = 0;//標(biāo)記的縱坐標(biāo) int sign = 0;//標(biāo)記的選擇 int win = ROW*COL-EASY_COUNT;//找到不是雷的次數(shù) while (win) { do { printf("請(qǐng)選擇是否要標(biāo)記雷:>0/1\n"); scanf("%d", &sign); switch(sign) { case 1: printf("請(qǐng)輸入要標(biāo)記的坐標(biāo):>"); again: scanf("%d%d", &m, &n); if (show[m][n] == '*') { show[m][n] = '#';//用'#'標(biāo)記雷 DisplayBoard(show, ROW, COL);//展示標(biāo)記 } else { printf("該位置不需要標(biāo)記,請(qǐng)重新選擇:>\n"); goto again; } break; case 0: break; default: printf("選擇錯(cuò)誤,請(qǐng)重新選擇:>"); break; } } while (sign); printf("\n"); printf("請(qǐng)選擇要排查雷的坐標(biāo):>"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if ((show[x][y] != '*') && (show[x][y] != '#')) { printf("該坐標(biāo)以前被排查過了,請(qǐng)重新選擇\n"); } else { if (mine[x][y] == '1') { printf("很遺憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL);//打印雷區(qū) break; } else { UnfoldMine(mine, show, x, y, ROW,COL, &win);//注意這里要傳win的地址,讓形參和實(shí)參建立聯(lián)系 DisplayBoard(show, ROW, COL);//展示棋盤 } } } else { printf("選擇坐標(biāo)違規(guī),請(qǐng)重新選擇:>\n"); } } if (win == 0)//判斷位置是否都找完 { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL);//顯示埋雷的棋盤 } }
詳解游戲代碼的實(shí)現(xiàn)
1初化掃雷區(qū)
這里我們規(guī)定:
無雷我們用0表示;
初始界面用*表示;
為了解決二個(gè)數(shù)組的初始化問題,我們將數(shù)組mine和數(shù)組show要初始化的內(nèi)容直接傳過來,我們用set接收.
/初化掃雷區(qū) void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; int j = 0; for (i = 0;i < rows;i++) { for (j = 0;j < cols;j++) { board[i][j] = set; } } }
2打印掃雷區(qū)
這部分主要實(shí)現(xiàn)的功能是為了我們能夠打印出現(xiàn)掃雷游戲的界面
//打印掃雷區(qū) void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf("--------掃雷游戲--------\n"); //打印列提示數(shù) for (j = 0;j <= col;j++) { printf("%d ", j); } printf("\n"); for (i = 1;i <= row;i++) { printf("%d ", i);//打印行提示數(shù) for (j = 1;j <=col;j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("---------掃雷游戲-------\n"); }
3 設(shè)置雷
這里我們用字符1來表示雷,這里我們?nèi)匀挥玫搅穗S機(jī)數(shù)生成rand與設(shè)置隨機(jī)數(shù)的種子srand
//設(shè)置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1;//生成0~9之間的數(shù) int y = rand() % col + 1;//生成0~9之間的數(shù) if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }
4 排雷
為了實(shí)現(xiàn)排雷的功能,我們?cè)谂爬走^程中根據(jù)自己推斷,就知道那個(gè)位置有雷,所有我們要標(biāo)記,在這里我們規(guī)定用'#'來標(biāo)記,有時(shí)候在我們輸入坐標(biāo)附近都是沒有雷的,為了提高游戲的體驗(yàn),我們可以把這片區(qū)域都展開。
4.1展開一片的功能
這里為了實(shí)現(xiàn)展開一片的功能,我們需要用遞歸來進(jìn)行實(shí)現(xiàn)。這里我們繼續(xù)用在之前博客和大家分享的寫遞歸的思路
明確你的函數(shù)要實(shí)現(xiàn)什么功能
這里我們就是為了實(shí)現(xiàn)當(dāng)x和y坐標(biāo)附近周圍沒有雷的時(shí)候就用空格展示
尋找遞歸結(jié)束的條件:
1該坐標(biāo)不是雷
2該坐標(biāo)周圍沒有雷
3該坐標(biāo)沒有被排查過
if ((show[x][y]!=' '&&mine[x][y]!='1') || (show[x][y]) == '#')
找出函數(shù)的等價(jià)條件
這里我們?yōu)榱藢ふ襵和y周圍是否有雷,我們可以用二層循環(huán)遍歷周圍是否存在遞歸結(jié)束的條件,沒有我們就繼續(xù)尋找,函數(shù)的等價(jià)為UnfoldMine(mine, show, x + i, y + j, row, col, &win)。
/展開一片沒有雷的地區(qū),用遞歸實(shí)現(xiàn) //遞歸結(jié)束的條件: //1 該坐標(biāo)不是雷 //2 該坐標(biāo)不是空格(防止死遞歸) void UnfoldMine(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y,int row,int col,int* win) { if ((show[x][y]!=' '&&mine[x][y]!='1') || (show[x][y]) == '#') { int count = get_mine_count(mine, x, y); if (count == 0) { show[x][y] = ' ';//無雷設(shè)置為空格 (*win)--;//無雷的位置減1 int i = 0; int j = 0; for (i = -1;i <= 1;i++) { for (j = -1;j <= 1;j++) { UnfoldMine(mine, show, x + i, y + j, row, col, &win); } } } //不符合遞歸的條件 else { show[x][y] = count + '0'; (*win)--; } } }
4.2雷標(biāo)記功能的實(shí)現(xiàn)
這里我們猜出雷的位置,就可以用#標(biāo)記,但我們要注意,標(biāo)記的地方show[x][y]=='*'應(yīng)該要滿足這個(gè)條件。
//排雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int m = 0;//標(biāo)記的橫坐標(biāo) int n = 0;//標(biāo)記的縱坐標(biāo) int sign = 0;//標(biāo)記的選擇 int win = ROW*COL-EASY_COUNT;//找到不是雷的次數(shù) while (win) { do { printf("請(qǐng)選擇是否要標(biāo)記雷:>0/1\n"); scanf("%d", &sign); switch(sign) { case 1: printf("請(qǐng)輸入要標(biāo)記的坐標(biāo):>"); again: scanf("%d%d", &m, &n); if (show[m][n] == '*') { show[m][n] = '#';//用'#'標(biāo)記雷 DisplayBoard(show, ROW, COL);//展示標(biāo)記 } else { printf("該位置不需要標(biāo)記,請(qǐng)重新選擇:>\n"); goto again; } break; case 0: break; default: printf("選擇錯(cuò)誤,請(qǐng)重新選擇:>"); break; } } while (sign); printf("\n"); printf("請(qǐng)選擇要排查雷的坐標(biāo):>"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if ((show[x][y] != '*') && (show[x][y] != '#')) { printf("該坐標(biāo)以前被排查過了,請(qǐng)重新選擇\n"); } else { if (mine[x][y] == '1') { printf("很遺憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL);//打印雷區(qū) break; } else { UnfoldMine(mine, show, x, y, ROW,COL, &win);//注意這里要傳win的地址,讓形參和實(shí)參建立聯(lián)系 DisplayBoard(show, ROW, COL);//展示棋盤 } } } else { printf("選擇坐標(biāo)違規(guī),請(qǐng)重新選擇:>\n"); } } if (win == 0)//判斷位置是否都找完 { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL);//顯示埋雷的棋盤 } }
游戲過程
視頻預(yù)覽點(diǎn)擊掃雷游戲的過程
到此這篇關(guān)于C語(yǔ)言掃雷排雷小游戲?qū)崿F(xiàn)全程的文章就介紹到這了,更多相關(guān)C語(yǔ)言掃雷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語(yǔ)言實(shí)現(xiàn)經(jīng)典掃雷小游戲完整代碼(遞歸展開?+?選擇標(biāo)記)
- 基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷游戲
- C語(yǔ)言實(shí)現(xiàn)掃雷小游戲(擴(kuò)展版)
- C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷小游戲
- C語(yǔ)言實(shí)現(xiàn)掃雷游戲詳細(xì)流程
- C語(yǔ)言實(shí)現(xiàn)自定義掃雷游戲(遞歸版)
- C語(yǔ)言實(shí)現(xiàn)第一次防死版掃雷游戲
- C語(yǔ)言實(shí)現(xiàn)遞歸版掃雷游戲?qū)嵗?/a>
- C語(yǔ)言詳細(xì)講解通過遞歸實(shí)現(xiàn)掃雷的展開
相關(guān)文章
C語(yǔ)言設(shè)計(jì)實(shí)現(xiàn)掃描器的自動(dòng)機(jī)的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言設(shè)計(jì)實(shí)現(xiàn)掃描器的自動(dòng)機(jī),可識(shí)別的單詞包括:關(guān)鍵字、界符、標(biāo)識(shí)符和常整型數(shù),感興趣的小伙伴可以了解一下2022-12-12C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02詳解C語(yǔ)言內(nèi)核中的自旋鎖結(jié)構(gòu)
自旋鎖是內(nèi)核中提供的一種高IRQL鎖,用同步以及獨(dú)占的方式訪問某個(gè)資源。自旋鎖是為了解決內(nèi)核鏈表讀寫時(shí)存在線程同步問題。本文將講解一下自旋鎖的簡(jiǎn)單應(yīng)用,感興趣的可以了解一下2022-09-09Qt實(shí)現(xiàn)網(wǎng)絡(luò)聊天室的示例代碼
本文主要介紹了Qt實(shí)現(xiàn)網(wǎng)絡(luò)聊天室,實(shí)現(xiàn)一個(gè)在線聊天室, 使用tcp對(duì)客戶端和服務(wù)器端進(jìn)行通訊。具有一定的參考價(jià)值,具有一定的參考價(jià)值,2021-06-06