C語言實現(xiàn)爆炸展開的掃雷詳解
游戲介紹
首先,我們來說基礎(chǔ)版的掃雷游戲有什么功能:
1.打印菜單,由玩家選擇玩游戲或者是退出游戲。
2.打印雷盤,讓玩家知道我們的雷盤是什么樣子的,從而讓玩家知道排雷的時候哪個位置對應(yīng)著哪個坐標(biāo)。
3.玩家開始排雷,并在排雷的函數(shù)中加入判斷輸贏的模塊。
以上就是我們基礎(chǔ)版掃雷的功能啦?。?!當(dāng)然,這樣玩掃雷這個游戲會很累的,因為我們在游戲中設(shè)置的展現(xiàn)給玩家的雷盤是9X9的雷盤,也就是說,我們?nèi)绻脍A,我們就需要在這個雷盤中排查71個非雷部分(當(dāng)然,如果排查到雷那游戲就會直接結(jié)束了?。。┻@樣的游戲是毫無游戲體驗感的。
所以,我們今天來學(xué)習(xí)一下,如何讓我們的掃雷游戲變得厲害起來!??!
那么,我們進(jìn)階版的掃雷游戲有什么新加的功能吶???
1.在玩家排雷的模塊,我們增添了爆炸展開的情況。如果玩家排雷的位置沒有雷,并且,周圍的位置也沒有雷,我們就讓這些位置爆炸式的展開。
2.在玩家開始排雷之前,我們增加了一個小菜單,用來讓玩家選擇排雷,添加標(biāo)記或者是取消標(biāo)記。
3.為了增加游戲的快樂,我們增加了添加標(biāo)記和取消標(biāo)記這兩個功能。如果玩家認(rèn)為某個位置有雷的存在,就可以在那個位置增加一個" ! "的標(biāo)記。
游戲功能實現(xiàn)
1.主菜單:
在游戲開始之前,我們先給玩家來上這么一個菜單來供玩家選擇玩游戲還是退出游戲
void Menu() { printf("\t***************************************\n\n"); printf("\t************** 1.play ***************\n\n"); printf("\t************** 0.exit ***************\n\n"); printf("\t***************************************\n"); }
2.初始化雷盤
//mine數(shù)組在沒有布置雷的時候,全是'0' //show數(shù)組在沒有排查雷的時候,全是'*' 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; } } }
3.打印雷盤
//打印雷盤 void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf("\t*** 掃雷游戲 ***\n\n"); printf("\t"); for (j = 0; j <= col; j++) { printf("%d ",j ); } printf("\n"); for (i = 1; i <= row; i++) { printf("\t"); printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("\n\t*** 掃雷選擇 ***\n\n"); }
此時,我們的調(diào)試結(jié)果應(yīng)該如下圖所示:
4.布置雷
void SetMine(char board[ROWS][COLS], int row, int col) { int count = EASY_COUNT;//雷的個數(shù) while (count) { int x = rand() % row + 1;//1~9 int y = rand() % col + 1;//1~9 if (board[x][y] == '0')//查看該坐標(biāo)處是否已經(jīng)布置雷 { board[x][y] = '1'; count--; } } }
這個時候,我們來看看是否能夠完美的布置好我們的雷:
5.玩家開始排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int input1 = 0; int win = 0;//找到非雷的數(shù)量 int flag_count = 0;//標(biāo)記雷的個數(shù) while (1) { Menu1(); printf("請輸入你的選擇:>"); scanf("%d", &input1); printf("\n"); if (input1 == 1) { int x = 0; int y = 0; printf("請輸入要排查的坐標(biāo):>"); scanf("%d %d", &x, &y); //坐標(biāo)是否合法 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (show[x][y] != '*') { printf("該坐標(biāo)被排查過了,不能重復(fù)排查\n"); } else { //是雷 if (mine[x][y] == '1') { printf("非常遺憾,你被炸死了!??!\n"); DisplayBoard(mine, ROW, COL); break; } //不是雷 else { win++; broad(mine, show, x, y); //要注意字符1和數(shù)字1的區(qū)別 if (get_mine_count(mine, x, y) == 0) { show[x][y] = ' '; system("cls"); DisplayBoard(show, ROW, COL);//如果該位置周圍沒有雷就顯示為空格 } else { int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標(biāo)周圍有幾個0 show[x][y] = count + '0'; DisplayBoard(show, ROW, COL); } //int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標(biāo)周圍有幾個0 //show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符 } } } else { printf("輸入坐標(biāo)非法!??!請重新輸入。\n"); } } else if (input1 == 2) { printf("請開始標(biāo)記雷:"); flag_count = Flagmine(show, ROW, COL, flag_count); DisplayBoard(show, ROW, COL); } else if (input1 == 3) { printf("請取消已經(jīng)標(biāo)記雷:"); flag_count = Cancelflag(show, ROW, COL, flag_count); DisplayBoard(show, ROW, COL); } if (win == COL * ROW) { printf("恭喜你排雷成功!??!\n"); DisplayBoard(mine, ROW, COL); break; } } }
6.小菜單
void Menu1() { printf("\t*** 1.開始排雷 ***\n\n"); printf("\t*** 2.添加標(biāo)記 ***\n\n"); printf("\t*** 3.取消標(biāo)記 ***\n\n"); }
7.排查位置周圍的八個坐標(biāo)有幾個雷
int get_mine_count(char board[ROWS][COLS], int x, int y) { return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] + board[x][y + 1] + board[x - 1][y + 1] - 8 * '0'); }
8.使用遞歸爆炸式展開
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { //判斷是否在范圍內(nèi),坐標(biāo)是否越界 if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1) { return; } //判斷該坐標(biāo)是否已經(jīng)被排查過了 if (show[x][y] != '*') { return; } //開始準(zhǔn)備遞歸 int count = get_mine_count(mine, x, y); if (count == 0) { show[x][y] = ' '; broad(mine, show, x - 1, y); broad(mine, show, x - 1, y - 1); broad(mine, show, x, y - 1); broad(mine, show, x + 1, y - 1); broad(mine, show, x + 1, y); broad(mine, show, x + 1, y + 1); broad(mine, show, x, y + 1); broad(mine, show, x - 1, y + 1); } else if (count > 0) { show[x][y] = count + '0'; } }
9.標(biāo)記功能
//標(biāo)記功能——>玩家可以自行標(biāo)記自己覺得是雷的位置 int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count) { int x = 0; int y = 0; //如果目前雷盤上已經(jīng)標(biāo)記過的點的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標(biāo)記 if (flag_count == EASY_COUNT) { printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標(biāo)記,無法進(jìn)行標(biāo)記?。。n"); return; } printf("請輸入你要標(biāo)記的位置坐標(biāo):> "); scanf("%d %d", &x, &y); //判斷坐標(biāo)是否在指定的區(qū)域 if (x > 0 && x <= row && y > 0 && y <= col) { //判斷該坐標(biāo)是否仍未被排除 if (show[x][y] == '*') { show[x][y] = '!'; flag_count++; } else { printf("該位置不可能是雷,請重新輸入\n"); } } else { printf("該坐標(biāo)不合法,請重新輸入:>\n"); } return flag_count; }
10.取消標(biāo)記功能
//取消標(biāo)記的功能 int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count) { int x = 0; int y = 0; printf("請輸入你要取消標(biāo)記的位置坐標(biāo):> "); scanf("%d %d", &x, &y); //判斷坐標(biāo)是否在指定的區(qū)域 if (x > 0 && x <= row && y > 0 && y <= col) { if (show[x][y] == '!') { show[x][y] = '*'; flag_count--; } else { printf("該坐標(biāo)沒有被標(biāo)記,無需取消標(biāo)記\n"); } } else { printf("該坐標(biāo)不合法,請重新輸入:>"); } return flag_count; }
完整代碼
1.game.c
掃雷游戲代碼
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //mine數(shù)組在沒有布置雷的時候,全是'0' //show數(shù)組在沒有排查雷的時候,全是'*' 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; } } } //打印棋盤 void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf("\t*** 掃雷游戲 ***\n\n"); printf("\t"); for (j = 0; j <= col; j++) { printf("%d ",j ); } printf("\n"); for (i = 1; i <= row; i++) { printf("\t"); printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("\n\t*** 掃雷選擇 ***\n\n"); } //設(shè)置雷 void SetMine(char board[ROWS][COLS], int row, int col) { int count = EASY_COUNT;//雷的個數(shù) while (count) { int x = rand() % row + 1;//1~9 int y = rand() % col + 1;//1~9 if (board[x][y] == '0')//查看該坐標(biāo)處是否已經(jīng)布置雷 { board[x][y] = '1'; count--; } } } //排查雷 int get_mine_count(char board[ROWS][COLS], int x, int y) { return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] + board[x][y + 1] + board[x - 1][y + 1] - 8 * '0'); } //遞歸爆炸式展開 void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { //判斷是否在范圍內(nèi),坐標(biāo)是否越界 if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1) { return; } //判斷該坐標(biāo)是否已經(jīng)被排查過了 if (show[x][y] != '*') { return; } //開始準(zhǔn)備遞歸 int count = get_mine_count(mine, x, y); if (count == 0) { show[x][y] = ' '; broad(mine, show, x - 1, y); broad(mine, show, x - 1, y - 1); broad(mine, show, x, y - 1); broad(mine, show, x + 1, y - 1); broad(mine, show, x + 1, y); broad(mine, show, x + 1, y + 1); broad(mine, show, x, y + 1); broad(mine, show, x - 1, y + 1); } else if (count > 0) { show[x][y] = count + '0'; } } //標(biāo)記功能——>玩家可以自行標(biāo)記自己覺得是雷的位置 int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count) { int x = 0; int y = 0; //如果目前雷盤上已經(jīng)標(biāo)記過的點的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標(biāo)記 if (flag_count == EASY_COUNT) { printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標(biāo)記,無法進(jìn)行標(biāo)記?。?!\n"); return; } printf("請輸入你要標(biāo)記的位置坐標(biāo):> "); scanf("%d %d", &x, &y); //判斷坐標(biāo)是否在指定的區(qū)域 if (x > 0 && x <= row && y > 0 && y <= col) { //判斷該坐標(biāo)是否仍未被排除 if (show[x][y] == '*') { show[x][y] = '!'; flag_count++; } else { printf("該位置不可能是雷,請重新輸入\n"); } } else { printf("該坐標(biāo)不合法,請重新輸入:>\n"); } return flag_count; } //取消標(biāo)記的功能 int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count) { int x = 0; int y = 0; printf("請輸入你要取消標(biāo)記的位置坐標(biāo):> "); scanf("%d %d", &x, &y); //判斷坐標(biāo)是否在指定的區(qū)域 if (x > 0 && x <= row && y > 0 && y <= col) { if (show[x][y] == '!') { show[x][y] = '*'; flag_count--; } else { printf("該坐標(biāo)沒有被標(biāo)記,無需取消標(biāo)記\n"); } } else { printf("該坐標(biāo)不合法,請重新輸入:>"); } return flag_count; } void Menu1() { printf("\t*** 1.開始排雷 ***\n\n"); printf("\t*** 2.添加標(biāo)記 ***\n\n"); printf("\t*** 3.取消標(biāo)記 ***\n\n"); } void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int input1 = 0; int win = 0;//找到非雷的數(shù)量 int flag_count = 0;//標(biāo)記雷的個數(shù) while (1) { Menu1(); printf("請輸入你的選擇:>"); scanf("%d", &input1); printf("\n"); if (input1 == 1) { int x = 0; int y = 0; printf("請輸入要排查的坐標(biāo):>"); scanf("%d %d", &x, &y); //坐標(biāo)是否合法 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (show[x][y] != '*') { printf("該坐標(biāo)被排查過了,不能重復(fù)排查\n"); } else { //是雷 if (mine[x][y] == '1') { printf("非常遺憾,你被炸死了?。?!\n"); DisplayBoard(mine, ROW, COL); break; } //不是雷 else { win++; broad(mine, show, x, y); //要注意字符1和數(shù)字1的區(qū)別 if (get_mine_count(mine, x, y) == 0) { show[x][y] = ' '; system("cls"); DisplayBoard(show, ROW, COL);//如果該位置周圍沒有雷就顯示為空格 } else { int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標(biāo)周圍有幾個0 show[x][y] = count + '0'; DisplayBoard(show, ROW, COL); } //int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標(biāo)周圍有幾個0 //show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符 } } } else { printf("輸入坐標(biāo)非法!??!請重新輸入。\n"); } } else if (input1 == 2) { printf("請開始標(biāo)記雷:"); flag_count = Flagmine(show, ROW, COL, flag_count); DisplayBoard(show, ROW, COL); } else if (input1 == 3) { printf("請取消已經(jīng)標(biāo)記雷:"); flag_count = Cancelflag(show, ROW, COL, flag_count); DisplayBoard(show, ROW, COL); } if (win == COL * ROW) { printf("恭喜你排雷成功?。?!\n"); DisplayBoard(mine, ROW, COL); break; } } }
2.test.c
游戲主邏輯
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void Menu() { printf("\t***************************************\n\n"); printf("\t************** 1.play ***************\n\n"); printf("\t************** 0.exit ***************\n\n"); printf("\t***************************************\n"); } void game() { char mine[ROWS][COLS] = { 0 };//用來存放布置好的雷 char show[ROWS][COLS] = { 0 };//用來存放排查出的雷的信息 //初始化數(shù)組的內(nèi)容為我們指定的內(nèi)容 Initboard(mine, ROWS, COLS, '0'); Initboard(show, ROWS, COLS, '*'); //設(shè)置雷 SetMine(mine, ROW, COL); //打印棋盤 DisplayBoard(show, ROW, COL); //DisplayBoard(mine, ROW, COL); //排查雷 FindMine(mine, show, ROW, COL);//在mine中找雷。把雷放在show中 } int main() { //設(shè)置隨機(jī)數(shù)的生成起點 srand((unsigned int)time(NULL)); int input = 0; do { Menu(); printf("請輸入你的選擇:>"); scanf("%d", &input); printf("\n"); switch (input) { case 1: game(); break; case 0: printf("退出游戲\n已退出游戲,歡迎您再次游玩\n"); break; default: printf("輸入錯誤,請重新選擇。\n"); break; } Sleep(3000); system("cls"); } while (input); return 0; }
3.game.h
頭文件部分
#pragma once #include<stdio.h> #include<time.h> #include<stdlib.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 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 board[ROWS][COLS], int row, int col); void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); int get_mine_count(char mine[ROWS][COLS], int x, int y); void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y); int Flagmine(char show[ROWS][COLS], int row, int col, int flag_count);
詳細(xì)代碼:掃雷進(jìn)階版
到此這篇關(guān)于C語言實現(xiàn)爆炸展開的掃雷詳解的文章就介紹到這了,更多相關(guān)C語言掃雷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言用函數(shù)實現(xiàn)電話簿管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言用函數(shù)實現(xiàn)電話簿管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12