掃雷(C語言實現)(第一步不炸死,可實現展開)
阿新 • • 發佈:2019-01-14
掃雷遊戲大家應該都有玩過,今天的我們用C語言實現一下掃雷遊戲。點開時第一步不炸死,而且沒有雷的周圍會展開。
實現思路
1.棋盤設計:
必須要設計倆個棋盤,一個設計者棋盤,一個玩家棋盤。
2.棋盤列印:
列印棋盤
3.雷的佈置
我的程式碼中採用9*9的棋盤,佈置了10個雷。用二維陣列來存棋盤的資訊,將二維陣列初始化為0,把佈置雷的地方改為1.
4.開局不炸死:
實現第一次不炸死,如果第一次輸入的位置為1,就必須將這個位置的1改為0.而尋找另一個為0的位置,將其座標改為1,來維持雷的總數不變。
5.實現展開:
在玩家輸入一個周圍有雷的座標時,顯示周圍雷的個數
6.輸贏判斷:
由於雷的總數不變,則判斷雷的個數是否為10個,為10 時,玩家掃雷成功,遊戲結束。
跟前面寫過的三子棋遊戲一樣,還是建立一個game.h的標頭檔案,用於定義遊戲程式內的函式。
建立一個一個game.c和一個test.c的原始檔,實現遊戲。
首先給出game.h檔案,後面的遊戲實現都會呼叫到標頭檔案中的函式:
然後給出test.c檔案:
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" #include<stdlib.h> void menu() { printf("*********歡迎來到掃雷***********\n"); printf("********************************\n"); printf("************ 1.play*************\n"); printf("************ 0.exit*************\n"); printf("********************************\n"); } void game() { char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 }; InitBoard(mine, ROWS, COLS, '0');//初始化設計者棋盤 InitBoard(show, ROWS, COLS, '*');//初始化玩家棋盤 SetMine(mine, ROW, COL);//佈雷 // DisplayBoard(mine, ROW, COL);//列印設計者棋盤(不能給玩家看,所以不列印) DisplayBoard(show, ROW, COL);//列印玩家棋盤 SafeMine(mine, show, ROW, COL);//第一次不炸死 FindMine(mine, show, ROW, COL);//排雷 } int main() { int input = 0; srand((unsigned int)time(NULL)); menu(); printf("請選擇:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0 : printf("退出遊戲\n"); break; default : printf("選擇錯誤\n"); break; } system("pause"); return 0; }
game.c檔案:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdlib.h> #include"game.h" void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { memset(board, set, rows*cols*sizeof(board[0][0])); } void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; for (i = 0; i <= row; i++)//列印行號和列號 { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++)//列印九乘九的棋盤 { printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("\n"); } void SetMine(char board[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = EASY_COUNT;//定義count來數雷,總共要佈置十個雷 while (count) { x = rand() % row + 1;//生成隨機下標1-9 y = rand() % col + 1; if (board[x][y] == '0')//判斷這個位置有沒有雷,沒有雷的話將非雷的座標由0改為1,每佈置好一個雷,count--(這裡不用判斷座標是否合法) { board[x][y] = '1'; count--; } } } int GetMineCount(char mine[ROWS][COLS], int x, int y) { return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0'; } void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y) { int ret = 0; ret = GetMineCount(mine, x, y); if (ret == 0) { show[x][y] = ' '; if (x - 1>0 && y>0 && show[x - 1][y] == '*') OpenMine(mine, show, row, col, x - 1, y); if (x - 1>0 && y + 1 <= col && show[x - 1][y + 1] == '*') OpenMine(mine, show, row, col, x - 1, y + 1); if (x>0 && y + 1 <= col && show[x][y + 1] == '*') OpenMine(mine, show, row, col, x, y + 1); if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*') OpenMine(mine, show, row, col, x + 1, y + 1); if (x + 1 <= row && y>0 && show[x + 1][y] == '*') OpenMine(mine, show, row, col, x + 1, y); if (x + 1 <= row && y - 1>0 && show[x + 1][y - 1] == '*') OpenMine(mine, show, row, col, x + 1, y - 1); if (x>0 && y - 1>0 && show[x][y - 1] == '*') OpenMine(mine, show, row, col, x, y - 1); if (x - 1>0 && y - 1>0 && show[x - 1][y - 1] == '*') OpenMine(mine, show, row, col, x - 1, y - 1); } else { show[x][y] = GetMineCount(mine, x, y) + '0'; } } void SafeMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int ret = 1; int ch = 0; printf("請輸入要排查的座標:>"); scanf("%d%d", &x, &y); if (mine[x][y] == '1')//如果第一次輸入座標為雷將座標改為0即非雷 { mine[x][y] = '0';//獲取周圍雷的個數 ch = GetMineCount(mine, x, y); show[x][y] = ch + '0';////數字對應的ASCII值和數字字元對應的ASCII值相差48,即'0'的ASCII while (ret)//在其餘有空的地方設定一個雷 { x = rand() % 9 + 1;//生成隨機數1-9 y = rand() % 9 + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; } ret--; } } OpenMine(mine, show, row, col, x, y); DisplayBoard(show, row, col); } int IsWin(char show[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int count = 0; for (i = 1; i <= row; i++) { for (j = 1; j <= col; j++) { if (show[i][j] == '*') { count++; } } } return count; } void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; while (1) { printf("請輸入要排查的座標:>"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row &&y >= 1 && y <= col)//判斷座標的有效性 { if (mine[x][y] == '1')//判斷是否為雷,如果是雷提示被炸死並列印設計者棋盤 { printf("很遺憾,你被炸死了\n"); DisplayBoard(mine, row, col); break; } else//如果不是雷,獲取周圍雷的個數並展開 { int c = GetMineCount(mine, x, y); show[x][y] = c + '0'; OpenMine(mine, show, row, col, x, y); DisplayBoard(show, row, col); if (IsWin(show, row, col) == EASY_COUNT) { break; } } } else//如果座標無意義,提示座標非法 { printf("座標非法\n"); } } if (IsWin(show, row, col) == EASY_COUNT) { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL); } }