上一期咱們用C語言實作了三子棋的小游戲 C語言實作三子棋
今天我們再來寫個掃雷的游戲,說起掃雷,相信大家都不陌生,可能許多朋友還是玩掃雷的高手,

其實掃雷和三子棋有許多相似之處,都需要用到陣列的知識,
今天的掃雷也是相當有趣的
由于博主是一個編程學習的小白,所以這只是掃雷的初級版,此版本有一些功能還無法實作,在后續的學習中,我會持續更新,不斷對這個小游戲進行優化,期待大家的關注,還有,這篇文章中若有錯誤或不當的地方,歡迎大家指正!
關于這個掃雷專案的代碼,歡迎訪問我的gitee代碼倉庫:
https://gitee.com/living-amethyst/code2021/tree/master/test_11_09_mine%20clearance
讓我們開始吧!
目錄
一.游戲的整體思路
二.創建游戲選單
三.游戲主體的實作
1.創建棋盤(陣列)
2.初始化棋盤
3.列印棋盤
4.布置雷
4.排查雷
四.全部的代碼
五.關于游戲的改進的思考
一.游戲的整體思路
為了讓代碼的可讀性更高,思維性更強,我們需要創建三個檔案來完成這個專案
- test.c —— 測驗游戲
- game.h—— 游戲函式的宣告
- game.c—— 游戲函式的實作
然后我們需要建立兩個棋盤,為什么呢?

我們先想一下掃雷的游戲規則,如圖,如果我選中的方塊不是雷,那么它上面就會顯示一個數字,這個數字代表它以它為中心的這個3*3區域內(紅色方框)地雷的個數,它的范圍是0~8,我們初步的設想是:無雷的放數字0,有雷的放數字1
但是如果我這個方塊不是雷,顯示它周圍的雷的格式時,如果它的周圍有一個雷,需要顯示
數字1時 ,我們就會分不清這個1 是雷?還是排查出的周圍雷的個數?所以我們需要建立兩個棋盤
一個棋盤用來存放布置好的雷的資訊(這是游戲結束前不讓玩家看到的)
另一個棋盤存放排查好的雷的資訊(這是游戲程序中玩家看到的)
還有一個問題

如果我們布置的棋盤是9*9的
當我們選擇了排查這個位置的周圍的雷的個數時,它的旁邊就沒有了,所以我們要將棋盤擴展為11*11
(但是列印時只列印9*9的棋盤 )

如圖,這樣我們就能排查這格周圍的地雷的個數了
我們具體這樣操作

二.創建游戲選單
與之前的三子棋游戲一樣,我們首先需要設定一個游戲選單
由于一進入游戲,我們首先就要看到選單,所以這里我們采用do...while回圈
我們的選單需要實作的功能有:
- 游戲的進入
- 游戲的退出
- 非法輸入的回傳提示和說明
void menu()
{
printf("************************\n");
printf("***** 1.play *******\n");
printf("***** 0.exit *******\n");
printf("************************\n");
}
void test()
{
int input = 0;
do
{
menu();
printf("請選擇");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
這里我們創建了test函式和menu函式,為的是讓邏輯更清晰,現在我們的選單部分就完成了
對于這個游戲選單,我們能實作的游戲功能有:
- 輸入1進入游戲
- 輸入0退出游戲
- 輸入其他數字提示選擇錯錯誤,將重新輸入

這是選單的運行效果
三.游戲主體的實作
1.創建棋盤(陣列)
//創建陣列
char mine[ROWS][COLS] = { 0 };//存放布置好的雷的資訊
char show[ROWS][COLS] = { 0 };//存放排查好的雷的資訊
2.初始化棋盤
我們把mine陣列作為存放布置好的雷的資訊的棋盤
把show陣列作為存放排查好的雷的資訊棋盤
我們用一個InitBoard函式來初始化這兩個棋盤
看代碼:
//函式的宣告
void InitBoard(char board[ROWS][COLS], int rows,int cols,char set);
//函式的定義
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;
}
}
}
//函式的呼叫
//初始化mine陣列為全字符'0'
InitBoard(mine,ROWS,COLS,'0');
//初始化show陣列為全'*'
InitBoard(show,ROWS,COLS,'*');
我們把mine陣列全部初始化為字符 ' 0 '
把show陣列全部初識化為字符 ' * '
3.列印棋盤
我們與兩個棋盤
其中 mine陣列代表的棋盤時游戲結束后或者游戲測驗人員才能看到的
另一個show陣列代表的棋盤是玩家玩游戲時能看到的
我們上代碼
//函式的定義
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//函式的定義
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
//1-9
int i = 0;
int j = 0;
printf("\n");
printf("---掃雷游戲---\n");
//列印列號
for (i = 0;i <= col;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");
}
}
//函式的呼叫
DisplayBoard(show, ROW, COL);//只列印9*9的內容
4.布置雷
下面我們就可以來布置雷啦,由于雷是隨機布置的,于是我們就要用到rand函式
srand((unsigned int)time(NULL)); //進行初始化
x = rand() % row+1; //x的范圍是1~9
y = rand() % col+1; //y的范圍是1~9
下面看代碼:
//函式的宣告
void SetMine(char mine[ROWS][COLS],int row,int col);
//函式的定義
void SetMine(char mine[ROWS][COLS], int row, int col)
{
//布置10個雷
int count = EASY_COUNT;
while (count)
{
//生產隨機的下標
int x = rand() % row + 1;//范圍1到9
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
//函式的呼叫
SetMine(mine, ROW, COL);
我們加上mine棋盤的列印,并將它注釋掉,這是為了方便我們測驗游戲或這檢查游戲出現的問題的
這里的EASY_COUNT是雷的個數,我們用define定義它
4.排查雷
關于排查雷,我們是這樣實作的:
- 輸入排查雷的坐標
- 檢查該坐標是不是雷
- (1)是雷 --> 很遺憾炸死了
- (0)不是雷 --> 統計坐標周圍有幾個雷-->存盤排查雷的資訊到show陣列,游戲繼續
這里我們用了 get_mine_count 和 FindMine 兩個函式
get_mine_count函式用來統計坐標周圍有幾個雷
看代碼
//宣告
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);//從mine中排查放到show中
//排查雷
int get_mine_count(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+1] +
mine[x + 1][y] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0';
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//1.輸入排查雷的坐標
//2.檢查該坐標是不是雷
//(1)是雷 --> 很遺憾炸死了
//(0)不是雷 --> 統計坐標周圍有幾個雷-->存盤排查雷的資訊到show陣列,游戲繼續
int x = 0;
int y = 0;
int win = 0;
while (win<row*col- EASY_COUNT)
{
printf("請輸入要排查的坐標: ");
scanf("%d %d", &x, &y);//x的范圍是1~9,y的范圍是1~9
//判斷坐標的合法性
if (x >= 1 && x <= col && y >= 1 && y <= row)
{
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
DisplayBoard(mine, row, col);//把怎么被炸死的顯現出來
break;
}
else
{
//不是雷的話統計(x,y)坐標周圍有幾個雷
int count = get_mine_count(mine, x, y);
show[x][y] = count+'0';
//顯示排查出的資訊
DisplayBoard(show, row, col);
win++;
}
}
else
{
printf("坐標不合法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!");
DisplayBoard(mine, row, col);
}
}
//呼叫
FindMine(mine,show,ROW,COL);
這里有幾個需要說明的點:
1.
這里函式有兩個形參,是為了從mine中排查然后放到show中
2.
這些代表查找的坐標的周圍其他格子的坐標
3.由于我們在棋盤中存放的是字符 '0 '和字符 '1'
我們先看一下 ASCII碼 表

我們可以發現'0' '1' '2'這些字符的ASCII碼值都是連續的,我們想顯示出排查格子周圍雷的個數,需要先將字符'0','1','2'...轉化為數字 0,1 ,2,3...
我們只需要把每個字符減去一個'0',它的ASCII碼值是48就可以了,看看我們是如何操作的吧:

之后再轉化成字符的形式存到陣列中

4.我們還要判斷玩家輸入坐標的合法性:
四.全部的代碼
game.h—— 游戲函式的宣告
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define EASY_COUNT 10
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盤
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);
game.c—— 游戲函式的實作
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//初始化
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)
{
//1-9
int i = 0;
int j = 0;
printf("\n");
printf("---掃雷游戲---\n");
//列印列號
for (i = 0;i <= col;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");
}
}
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
//布置10個雷
int count = EASY_COUNT;
while (count)
{
//生產隨機的下標
int x = rand() % row + 1;//范圍1到9
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int get_mine_count(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+1] +
mine[x + 1][y] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0';
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//1.輸入排查雷的坐標
//2.檢查該坐標是不是雷
//(1)是雷 --> 很遺憾炸死了
//(0)不是雷 --> 統計坐標周圍有幾個雷-->存盤排查雷的資訊到show陣列,游戲繼續
int x = 0;
int y = 0;
int win = 0;
while (win<row*col- EASY_COUNT)
{
printf("請輸入要排查的坐標: ");
scanf("%d %d", &x, &y);//x的范圍是1~9,y的范圍是1~9
//判斷坐標的合法性
if (x >= 1 && x <= col && y >= 1 && y <= row)
{
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
DisplayBoard(mine, row, col);//把怎么被炸死的顯現出來
break;
}
else
{
//不是雷的話統計(x,y)坐標周圍有幾個雷
int count = get_mine_count(mine, x, y);
show[x][y] = count+'0';
//顯示排查出的資訊
DisplayBoard(show, row, col);
win++;
}
}
else
{
printf("坐標不合法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!");
DisplayBoard(mine, row, col);
}
}
test.c —— 測驗游戲
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("**********************\n");
printf("***** 1.play *******\n");
printf("***** 0.exit *******\n");
printf("**********************\n");
}
void game()
{
//創建陣列
char mine[ROWS][COLS] = { 0 };//存放布置好的雷的資訊
char show[ROWS][COLS] = { 0 };//存放排查好的雷的資訊
//初始化mine陣列為全字符'0'
InitBoard(mine,ROWS,COLS,'0');
//初始化show陣列為全'*'
InitBoard(show,ROWS,COLS,'*');
//列印棋盤
DisplayBoard(show, ROW, COL);//只列印9*9的內容
//布置雷
SetMine(mine, ROW, COL);
/*DisplayBoard(mine, ROW, COL);*/
//這是不給玩家看到的
//排查雷
FindMine(mine,show,ROW,COL);//從mine中排查放到show中
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請選擇:\n");
scanf("%d", &input);
switch (input)
{
case 1:
//掃雷
game();
break;
case 0:
break;
default:
printf("選擇錯誤");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
好了,這樣我們就把掃雷游戲撰寫完成了
五.關于游戲的改進的思考
如果你玩過正宗的掃雷游戲,那你肯定知道,掃雷游戲還有兩個功能:
- 如果不是雷并且周圍沒有雷-->展開一片
- 如果我們確定哪個位置我們可以標記雷

這就是我們以后給這個游戲的優化方案
其中第一個功能我們需要使用遞回實作
這些都會再以后更新,歡迎持續關注 !
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/355418.html
標籤:其他
上一篇:請回答c語言-掃雷游戲
