扫雷C语言写法详解
????????相信大家對掃雷一定都不陌生吧!但是你敢信僅僅使用一些C語言的初階基礎知識就能夠制作一個掃雷簡單小游戲?hhhhh,今天,我將帶領大家一起走進掃雷,探究其基礎算法奧秘。
一、基本思路
首先,既然是玩游戲,我們應該設計相應的菜單。
輸入1后繼續讓玩家選擇游戲難度:
我們在這里設計簡單模式為6x6大小的面板,雷埋10個;中等模式為10x10大小的面板,雷埋30個;困難模式為14x14大小的面板,雷埋50個。
為了方便雷的布置與顯示,我們設計了兩張面板:show_board[ROW][COL]和mine_board[ROW][COL],其中show面板負責顯示“空格”,mine面板負責記錄周圍雷的個數。
玩家通過輸入每個格子所對應的坐標進行掃雷操作。
char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));//二維數組動態內存分配for (int i = 0; i < ROW + grade * 4; i++) {show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));memset(show_board[i], ' ', (COL + grade * 4));//數組全部賦值為空格 }char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));for (int i = 0; i < ROW + grade * 4; i++) {mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));memset(mine_board[i], '0', (COL + grade * 4));//數組全部賦值為‘0’ }?二、代碼實現
Step1.畫圖
想要進行掃雷游戲,首先應該有掃雷界面的設計,如下:
我們建立Showboard函數進行面板的基本繪制:
static void Showboard(char **board,int grade)//面板制作 {printf(" ");for (int i = 1; i <= ROW-2+4*grade; i++) {printf(" %3d", i);}printf("\n");for (int i = 1; i <= ROW-2+4*grade; i++){printf(" ");for (int k = 1; k <= COL-2+4*grade; k++) {printf("----");}printf("\n");printf("%2d|",i);for (int j = 1; j <= COL-2+4*grade; j++){printf(" %c |",board[i][j]);}printf("\n");}printf(" ");for (int k = 1; k <= COL-2+4*grade; k++) {printf("----");}printf("\n"); }?成果圖如下:
Step2. 埋雷
埋雷應做到一下幾點:
1.展示面板show_board(這里傳參后以形參board替代)賦值為1(BOOM宏定義為1)?;
2.為了提高用戶體驗,在被炸后能夠展示出雷的位置,我們又建立了一個lei_board數組用來顯示,并在埋雷時將對應位置賦值為'*';
3.埋雷要具有隨機性,所以這里引用rand函數(主函數要種隨機數種子);
static void SetMines(char **board,char **lei_board,int grade) {int i = 1;int x, y;while (i <= NUM+grade*20) {x = rand() % (ROW-2+4*grade) + 1;y = rand() % (COL-2+4*grade) + 1;if (board[x][y] != BOOM) {board[x][y] = BOOM;lei_board[x][y] = '*';i++;}} }Step3.計算周圍雷的個數
當我們計算周圍雷的個數時,自然而然地就會想到統計周圍九宮格的雷的個數。如果要搜索的位置在面板中間,這很簡單,但如果是以下這類情況,比如頂點格或者邊格怎么辦?如何知道該算哪個格?
?為了避免這種特殊情況所帶來的問題,我們不如直接在外面再套一圈,對于各類面板(即二維數組)的建立也直接按照增大的來,這樣就無需討論邊角的特殊性了。
統計函數直接通過簡單的函數返回來實現:
static int CountMine(char **board,int x,int y) {return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \board[x + 1][y] + board[x + 1][y + 1] - 8 * '0'; }?三、完整代碼
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include<windows.h>#define BOOM '1' #define ROW 8 #define COL 8 #define NUM 10static void SetMines(char **board,char **lei_board,int grade)//埋雷 {int i = 1;int x, y;while (i <= NUM+grade*20) {x = rand() % (ROW-2+4*grade) + 1;y = rand() % (COL-2+4*grade) + 1;if (board[x][y] != BOOM) {board[x][y] = BOOM;lei_board[x][y] = '*';i++;}} } static void Showboard(char **board,int grade)//面板制作 {printf(" ");for (int i = 1; i <= ROW-2+4*grade; i++) {printf(" %3d", i);}printf("\n");for (int i = 1; i <= ROW-2+4*grade; i++){printf(" ");for (int k = 1; k <= COL-2+4*grade; k++) {printf("----");}printf("\n");printf("%2d|",i);for (int j = 1; j <= COL-2+4*grade; j++){printf(" %c |",board[i][j]);}printf("\n");}printf(" ");for (int k = 1; k <= COL-2+4*grade; k++) {printf("----");}printf("\n"); } static int CountMine(char **board,int x,int y)//統計周圍雷的數目 {return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \board[x + 1][y] + board[x + 1][y + 1] - 8 * '0'; }void Game(int grade)//游戲函數,grade為游戲難度等級 {char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));for (int i = 0; i < ROW + grade * 4; i++) {show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));memset(show_board[i], ' ', (COL + grade * 4));}char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));for (int i = 0; i < ROW + grade * 4; i++) {mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));memset(mine_board[i], '0', (COL + grade * 4));}char** lei_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));for (int i = 0; i < ROW + grade * 4; i++) {lei_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));memset(lei_board[i], ' ', (COL + grade * 4));}SetMines(mine_board,lei_board,grade);int x = 0, y = 0;int total = 0;while (1){Showboard(show_board, grade);printf("請輸入坐標:");//printf("%d", '*');scanf("%d %d", &x, &y);if (!(x > 0 && x <= ROW + 4 * grade - 2 && y > 0 && y <= COL + 4 * grade - 2)) {printf("掃雷的位置有問題!\n");continue;}if (show_board[x][y] != ' ') {printf("該位置已經掃過了!\n");continue;}if (mine_board[x][y] == '1') {printf("對不起,你被炸死了!\n");Showboard(lei_board, grade);break;}else {int count = CountMine(mine_board, x, y);show_board[x][y] = count + '0';total++;system("cls");}if ((ROW - 2) * (COL - 2) - total <= NUM) {printf("恭喜你,游戲通過!\n");break;}}for (int i = 0; i < ROW + grade * 4; i++) {free(show_board[i]);}free(show_board);for (int i = 0; i < ROW + grade * 4; i++) {free(mine_board[i]);}free(mine_board);for (int i = 0; i < ROW + grade * 4; i++) {free(lei_board[i]);}free(lei_board); }void Menu() {printf("#########################################\n");printf("## 1.play ##\n");printf("## 0.exit ##\n");printf("#########################################\n"); }int main() {srand((unsigned long)time(NULL));int quit = 0;while (!quit){int select;Menu();printf("請輸入游戲選項:");scanf("%d", &select);switch (select){case 1:printf("#########################################\n");printf("## 1.easy ##\n");printf("## 2.middle ##\n");printf("## 3.difficult ##\n");printf("#########################################\n");printf("請輸入游戲難度:");scanf("%d", &select);switch (select){case 1:Game(0);break;case 2:Game(1);break;case 3:Game(2);break;}break;case 0:quit = 1;printf("感謝使用!");break;default:printf("輸入有誤,請重新輸入!\n");break;}}}????????期待大家在這個代碼的基礎上加入更多創新與改進,寫出用戶體驗感更好,更加智能高端的掃雷程序!!!
總結
- 上一篇: Java 重载、重写、构造函数详解
- 下一篇: 汽车芯片保护壳体压铸缺陷模流实例