【C语言】 扫雷游戏(保姆级的实现过程)
🚀write in front🚀 ??
🔎大家好,我是謓澤,希望你看完之后,能對你有所幫助,不足請指正!共同學習交流🔎
🏅2021年度博客之星物聯網與嵌入式開發TOP5→周榜31→總榜2513🏅
🆔本文由?謓澤?原創 CSDN首發🐒 如需轉載還請通知?
📝個人主頁:打打醬油desu-CSDN博客
🎁歡迎各位→點贊👍 + 收藏?? + 留言📝?
📣系列專欄:YY_打打醬油desu-CSDN博客
??我們并非登上我們所選擇的舞臺,演出并非我們所選擇的劇本📩
目錄
🚀write in front🚀 ??
Ⅰ 前言
Ⅱ 模塊化編程??
Ⅲ 游戲思路與邏輯
Ⅳ 實現游戲步驟/過程?
① 創建顏色函數
?🖊創建顏色函數color()?
③ 實現多行多列掃雷?
④ 實現多個雷
⑤ 棋盤初始化?
⑥ 棋盤的打印?
⑦ 布置雷的信息
⑧ 玩家輸入雷實現步驟?
⑨ 排查 x,y 周圍有多少雷
Ⅴ 結果演示?
Ⅵ 模塊化代碼實現?
(一)、test.c
(二)、game.h?
(三)、game.c?
Ⅰ 前言
掃雷游戲,想必大家都有玩過吧。沒完過的話也可以試著玩一玩,這樣對寫掃雷游戲這個小游戲的化是會有一個很好的思路的。那么本片博客就來介紹如何實現掃雷游戲的具體步驟。
掃雷游戲鏈接👉?掃雷游戲網頁版 - Minesweeper
Ⅱ 模塊化編程??
再說實現三子棋邏輯思路前,我們來說說什么是 模塊化編程?吧🤔
傳統方式編程:所有的函數均放在main.c里,若使用的模塊比較多,則一個文件內會有很多的代碼,不利于代碼的組織和管理,而且很影響編程者的思路。
模塊化編程:把各個模塊的代碼放在不同的.c文件里,在.h文件里提供外部可調用函數的聲明,其它.c文件想使用其中的代碼時,只需要#include "XXX.h"文件即可。使用模塊化編程可極大的提高代碼的可閱讀性、可維護性、可移植性等。
傳統方式編程:所有的函數均放在main.c里,若使用的模塊比較多,則一個文件內會有很多的代碼,不利于代碼的組織和管理,而且很影響編程者的思路。
模塊化編程:把各個模塊的代碼放在不同的.c文件里,在.h文件里提供外部可調用函數的聲明,其它.c文件想使用其中的代碼時,只需要#include "XXX.h"文件即可。使用模塊化編程可極大的提高代碼的可閱讀性、可維護性、可移植性等!
總的來說就是:當你代碼比較多的時候,就可以采用模塊化編程來完成這個程序😜
Ⅲ 游戲思路與邏輯
Ⅳ 實現游戲步驟/過程?
① 創建顏色函數
?🖊創建顏色函數color()?
前景色顏色的對應值↓
0=黑色 ? ? ? ? ? ? ? ?8=灰色 1=藍色 ? ? ? ? ? ? ? ?9=淡藍色 ? ? ? ?十六進制 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 2=綠色 ? ? ? ? ? ? ? ?10=淡綠色 ? ? ? ?A ? ? ? ? 3=湖藍色 ? ? ? ? ? ? ?11=淡淺綠色? ? B 4=紅色 ? ? ? ? ? ? ? ?12=淡紅色 ? ? ? ?C 5=紫色 ? ? ? ? ? ? ? ?13=淡紫色 ? ? ? ?D ? ? ? ? 6=黃色 ? ? ? ? ? ? ? ?14=淡黃色 ? ? ? ?E ? ? ? 7=白色 ? ? ? ? ? ? ? ?15=亮白色 ? ? ? ?Fcolor()創建顏色函數如下↓?
void color(short x) {if (x >= 0 && x <= 15)SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x); elseSetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); }使用顏色函數的好處實際上無非就是讓程序運行看上去更加美觀、鮮明,實際上沒什么實際作用,這點是我們要知道的。?
這里的STD_OUTPUT_HANDLE需要引頭文件#include<Windows.h>,才可以進行使用。
② 菜單界面(menu)?
菜單界面函數實際上就像是我們的一個界面,就好比是游戲的界面目錄,餐館當中的菜單。一樣的道理。這個是庫函數就有的我們只需要直接引用下即可。示例代碼如下↓
void menu() {color(0); //Black 黑色system("cls"); //清屏.color(10);printf("|-----------|掃雷游戲|-----------|\n");printf("|********************************|\n");printf("|★★★★★★★★★★★★★★★★|\n");printf("|★★ 1.開始 0.退出 ★★|\n");printf("|★★★★★★★★★★★★★★★★|\n");printf("|0 = 不是雷 ---------- 1 = 它是雷|\n");printf("|--------------------------------|\n"); }注→在這里用到了一個system("cls");?達到了一個清屏的效果,只有加了這個,你才可以讓cmd中的界面全部為黑色。因為我們還在這個清屏指令上+color(0); 這個代表的是,黑色。
③ 實現多行多列掃雷?
#define ROW 9 #define COL 9使用 #define?宏定義在這里的好處:
在程序當中,是9行9列的,如果想修改成10行10列的只需要把#define改成10即可!
10行10列的掃雷棋盤如下?👇
但是十行十列就是會出現這個的情況,當然這個問題也是非常的好解決的。大家可以看下怎么去解決這個問題。☆⌒(*^-゜)v THX!!
④ 實現多個雷
#define Thunder 10這里 #define 在上面提到過,就不提了。
修改雷的個數也只需要把這上面的數字(10)修改變的數字修改,當然修改請理性修改,你不可能 9*9 的棋盤,給很多雷吧,那還怎么玩哈哈哈😤。?
比如修改成 40?個雷,看看效果如下所示 👇
⑤ 棋盤初始化?
打印棋盤,本質上是打印數組的內容。如下所示👇
void Initialization(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;}} }char set 是實參傳遞到形參的字符。
?實參數組名 行 可以進行省略,但是 列 不能進行省略。?
⑥ 棋盤的打印?
打印棋盤,本質上是打印數組的內容,這里數組的內容是字符'0'。如下所示👇??
void Print_board(char board[ROWS][COLS], int row, int col) {int i = 0; int j = 0;color(7);printf("════════════════════\n");for (i = 0; i <= row; i++){if (i == 0){printf("%d|", i);}else{printf("%d|", i);}}printf("\n/|══════════════════");printf("\n");for (i = 1; i <= row; i++){printf("%d|", i);for (j = 1; j <= col; j++){printf("%c|", board[i][j]);}printf("\n");}color(6);printf("\n-----掃雷游戲------\n"); }打印棋盤的效果圖,如下所示👇? ?
⑦ 布置雷的信息
打印完棋盤之后,就開始布置雷。
void Lay_thunder(char Findout[ROWS][COLS], int row, int col) {//布置雷int count = Thunder;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (Findout[x][y] = '0'){Findout[x][y] = '1';count--;}} }這里還用到了一個知識點【隨機數】
在實際開發中,我們往往需要一定范圍內的隨機數,過大或者過小都不符合要求,那么,如何產生一定范圍的隨機數呢?我們可以利用取模的方法:
int a = rand() % 10; //產生0~9的隨機數,注意10會被整除 如果要規定上下限: int a = rand() % 51 + 13; //產生13~63的隨機數分析:取模即取余,rand()%51+13?我們可以看成兩部分:rand()%51?是產生 0~50 的隨機數,后面+13保證 a 最小只能是 13,最大就是 50+13=63
使用 <time.h> 頭文件中的 time() 函數即可得到當前的時間(精確到秒),就像下面這樣:
srand((unsigned)time(NULL));🍁注意:這個在程序當中是只執行一次即可!
⑧ 玩家輸入雷實現步驟?
這里的玩家輸入坐標,在玩家輸入下棋的時候,定義了個靜態局部變量,在執行代碼的時候。玩游戲的時候會提醒一次,?輸入第一個坐標記得空一格!每次進入游戲只有一次,這里主要就是用到了 靜態局部變量 就可以保證上一次的值不會被銷毀。
檢查坐標處是不是雷,布置存放的是字符'1',沒有放置雷存放的是字符'0'。
判斷坐標輸入合法性幾種情況:
⑨ 排查 x,y 周圍有多少雷
static int Statistics(char Layouts[ROWS][COLS], int x, int y) {return Layouts[x-1][y-1]+Layouts[x][y-1] +Layouts[x+1][y-1]+Layouts[x-1][y]+Layouts[x+1][y]+Layouts[x-1][y+1]+Layouts[x][y+1]+Layouts[x+1][y+1] - 8*'0'; }🍁注意:靜態局部變量去修飾函數的時候,讓這個函數只能在自己所在的源文件內看到,其它的內部當中是看不到的。
Ⅴ 結果演示?
被雷"砸死"的結果演示。
Ⅵ 模塊化代碼實現?
(一)、test.c
測試游戲的邏輯。
//掃雷游戲的測試 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include "game.h"void menu() {color(0); //Black 黑色system("cls"); //清屏.color(10);printf("|-----------|掃雷游戲|-----------|\n");printf("|********************************|\n");printf("|★★★★★★★★★★★★★★★★|\n");printf("|★★ 1.開始 0.退出 ★★|\n");printf("|★★★★★★★★★★★★★★★★|\n");printf("|0 = 不是雷 ---------- 1 = 它是雷|\n");printf("|--------------------------------|\n"); }void game() {printf(" ---------\n");printf("|PLAY GAME|\n");printf(" ---------\n");char Layouts[ROWS][COLS] = { 0 };//存放布置好雷的信息char Findout[ROWS][COLS] = { 0 };//存放排查出雷的信息//初始化棋盤Initialization(Layouts, ROWS, COLS, '0');//mineInitialization(Findout, ROWS, COLS, 'x');//show//打印棋盤/*Print_board(Layouts, ROW, COL);*/Print_board(Findout, ROW, COL);//布置雷Lay_thunder(Layouts, ROW, COL);/*Print_board(Findout, ROW, COL);*///排查雷Check(Layouts,Findout,ROW,COL); }void test() {int input = 0;srand((unsigned)time(NULL));do{menu(); color(5);printf("\n");printf("|═════════════════════════════════|\n");printf("|Please enter the interface number|:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("|════════|\n");printf("|退出游戲|\n");printf("|════════|\n");break;default:printf("\n");printf("|═════════════════════════════════|\n");printf("|由于你輸入錯誤罰你5s不能玩(→_→)|\n");printf("|═════════════════════════════════|\n");Sleep(5000);}} while (input); }int main(void) {test();return 0; }(二)、game.h?
關于游戲包含的函數聲明,符號聲明頭文件的包含以及宏定義。
//游戲的函數的聲明 //一開始保持神秘感:■ 第①個棋盤初始化 //不是雷:〇 第②個棋盤初始化 //是雷話:★ //排查出來雷的信息:數字表達,例如:Ⅰ - 1(這是周圍有1個雷),兩個雷的時候 - Ⅱ,依次類推! //1:①個數字存放布置好雷的信息 2:①個數組存放排查出的雷的信息。—— 都用 char 類型 字符數組 來進行實現!#include<stdio.h> #include<Windows.h> #include<stdlib.h> #include<time.h>#define Thunder 10#define ROW 9 #define COL 9#define ROWS ROW+2 #define COLS COL+2 //顏色函數 void color(short x);//初始化函數,初始化11*11,因為 行 & 列 都需要加1 void Initialization(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盤,最終打印 9*9 棋盤即可 void Print_board(char board[ROWS][COLS], int row, int col);//布置雷 void Lay_thunder(char Findout[ROWS][COLS], int row, int col);//排查雷 void Check(char Layouts[ROWS][COLS], char Findout[ROWS][COLS], int row, int col);(三)、game.c?
游戲和相關函數實現。
#define _CRT_SECURE_NO_WARNINGS 1 //游戲的函數的實現 #include "game.h" #include<stdio.h>void color(short x) {if (x >= 0 && x <= 15)SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);elseSetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); }void Initialization(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 Print_board(char board[ROWS][COLS], int row, int col) {int i = 0; int j = 0;color(7);printf("════════════════════\n");for (i = 0; i <= row; i++){if (i == 0){printf("%d|", i);}else{printf("%d|", i);}}printf("\n/|══════════════════");printf("\n");for (i = 1; i <= row; i++){printf("%d|", i);for (j = 1; j <= col; j++){printf("%c|", board[i][j]);}printf("\n");}color(6);printf("\n-----掃雷游戲------\n"); }void Lay_thunder(char Findout[ROWS][COLS], int row, int col) {//布置雷int count = Thunder;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (Findout[x][y] = '0'){Findout[x][y] = '1';count--;}} } //靜態局部變量去修飾函數的時候,讓這個函數只能在自己所在的源文件內看到,其它的內部當中是看不到的。 static int Statistics(char Layouts[ROWS][COLS], int x, int y) {return Layouts[x-1][y-1]+Layouts[x][y-1] +Layouts[x+1][y-1]+Layouts[x-1][y]+Layouts[x+1][y]+Layouts[x-1][y+1]+Layouts[x][y+1]+Layouts[x+1][y+1] - 8*'0'; } void Check(char Layouts[ROWS][COLS], char Findout[ROWS][COLS], int row, int col) {//1.輸入排查雷的坐標//2.檢查坐標處是不是雷,布置雷存放的是字符'1',沒有放置雷存放的是字符'0'。int x, y;int win = 0;while (win<row*col - Thunder){static int j = 1;//延長生明周期,while (j){color(8);printf("--------------------------\n");printf("[輸入第一個坐標記得空一格!]\n");printf("--------------------------\n");j--;break;}color(11);printf("---------------\n");printf("請輸入坐標>:");//x與y坐標范圍 1~9scanf("%d %d", &x, &y);printf("---------------\n");//判斷坐標的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (Layouts[x][y] == '1'){printf("|══════════════════|\n");printf("|很遺憾,你被炸死了!|\n");printf("|══════════════════|\n");Print_board(Layouts, ROW, COL);Sleep(5000);break;}if (Findout[x][y] == '0'){color(6);printf("|═══════════════════════════════════|\n");printf("|寧已經在這里輸入過坐標了,請重新輸入!|\n");printf("|═══════════════════════════════════|\n");}if (Findout[x][y] == '1'){color(6);printf("|════════════════════════════════════|\n");printf("|寧已經在這里輸入過坐標了,請重新輸入!|\n");printf("|════════════════════════════════════|\n");}else{//不是雷情況下,統計x,y周圍坐標有幾個雷int Count = Statistics(Layouts, x, y);Findout[x][y] = Count + '0';Print_board(Findout, row, col);win++;}}else{printf("|═════════════════════════════|\n");printf("|寧輸入的坐標范圍錯誤!重新輸入|\n");printf("|═════════════════════════════|\n");}}if (win == row*col - Thunder){printf("|═══════════════════════|\n");printf("|恭喜你,排雷成功!太優秀了!|\n");printf("|═══════════════════════|\n");Print_board(Findout, ROW, COL);} }好了,那么這個掃雷游戲就到這里了,不知道你學會了沒有。對于初學者這是可以嘗試下,對編程的思維和邏輯,以及代碼的理解能力幫助都是非常大的( ?? .? ?? )?
別忘記👍(??? )總結
以上是生活随笔為你收集整理的【C语言】 扫雷游戏(保姆级的实现过程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 端口tnpl,Linux和W
- 下一篇: 自己搭建的CISCO实验环境