目录
前言
一、游戏介绍
上面依次是游戏进行、失败和胜利的界面 。
游戏规则:
游戏玩法:
二、游戏实现思路
三、创建文件
由于该游戏的实现需要大量的代码,为了提高代码的可读性已经方便后续写代码时的自我检查,这里我们创建三个文件来实现该游戏,我们依次将三个文件命名为game.h \ game.c \ test.c。
😆(menu)菜单函数的实现
void menu()
{
printf("\t\t\t\t\t\t\t\t\t\t\t\n");
printf("*********************\n");
printf("***** 1. play *****\n");
printf("***** 0. exit *****\n");
printf("*********************\n");
}
打印结果:
😆game函数的实现
void game()
{
char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
//初始化数组的内容为指定内容
//mine数组在没有布置雷的时候,都是‘0’
InitBoard(mine, ROWS, COLS,'0');
//show数组在没有排查雷的时候都是‘*’
InitBoard(show, ROWS, COLS, '*');
//设置雷
Setmine(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
这里我们需要创建两个数组作为棋盘,但是棋盘比实际的要大一圈,这是因为在对边上的格子进行排查时,往往不满八个格子,对9*9之外的格子访问时会越界,这时我们需要手动创建它周围的格子使得它能够成功访问,这样的话创建的数组棋盘就从9*9变成了11*11。

打印结果:
😆main函数的实现
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:system("cls"); game();
break;
case 0:printf("退出游戏\n");
break;
default:printf("选择错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
这里我们通过do while循环和switch语句来实现游戏的持续进行和对不同输入的选择,输入1,进入游戏,输入0,退出游戏,输入其他时,输出“选择错误,请重新输入!”。
打印结果:
😊书写初始化棋盘函数
//初始化棋盘
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;
}
}
因为有两个棋盘,所以我们需要一个字符型变量(char)set 来设置棋盘初始化的值,如果是mine棋盘,则 set = ‘0’;如果是show棋盘,则 set = ‘*’ 。
😊书写打印棋盘信息的函数
//打印棋盘信息
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------扫雷游戏------\n");
printf("════════════════════\n");//美化棋盘
for (j = 0; j <= col; j++)
{
printf("%d|", j);
}
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");
}
printf("════════════════════\n");//美化棋盘
printf("------扫雷游戏------\n\n");
}
打印结果:
😊书写设置雷的函数(是雷则为‘1’)
//设置雷的函数
void Setmine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
//行1-9 列1-9
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
下面我会针对遇到的问题进行解答👀
👀如何随机设置雷的位置?
使用srand()来随机设置雷的坐标
//test.c
srand((unsigned int)time(NULL));//设置随机数的生成起点
👀如何控制雷的坐标位置合理
int x = rand() % row + 1;//生成1-9的随机数
int y = rand() % col + 1;//生成1-9的随机数
利用rand() 函数取row或col的模再+1来得到1-9的随机数,这样就可以控制雷的位置在棋盘上。
😊书写统计周围雷个数的函数
//统计周围雷数的函数
int get_mine_count(char board[ROWS][COLS], int row, int col,int x,int y)
{
int count = 0;
for(int i=-1;i<=1;i++)
for (int j = -1; j <= 1; j++)
{
if (board[x + i][y + j] == '1')
count++;
}
return count;
/*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 OpenArea(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col,int x, int y)
{
int count = get_mine_count(mine,ROW,COL, x, y);
if (count == 0)
{
show[x][y] = ' ';
for (int i = x - 1; i <= x + 1; i++)
{
for (int j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*' && x >= 1 && x <= row && y >= 1 && y <= col)
{
OpenArea(mine, show,ROW,COL, i, j);
}
}
}
}
else
{
show[x][y] = count + '0';
}
}
因为需要对存储雷位置的棋盘和显示棋盘信息的棋盘进行操作,所以形参中需要两个棋盘。
😊书写计算非雷和非标记的位置个数
//计算非雷和非标记的位置个数
int get_win(char board[ROWS][COLS], int row, int col)
{
int win = 0;
for(int i=1;i<=row;i++)
for (int j = 1; j <= col; j++)
{
if (board[i][j]!='*'&&board[i][j]!='!')
win++;
}
return win;
}
😊书写排查雷的函数
//排雷的函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//1.输入排查的坐标
//2.检查该坐标处是不是雷
//(1) 是雷 - 很遗憾,你被炸死了 - 游戏结束
//(2) 不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
int x = 0;
int y = 0;
int win = 0;
int select = 0;
while (win < row * col - EASY_COUNT)
{
printf("请选择:1.排查雷 2.标记雷\t");
scanf("%d", &select);
if (select == 1)
{
printf("请输入要排查雷的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("\n\n很遗憾,你被炸死了!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
OpenArea(mine, show,ROW,COL, x, y);
//显示排查出的信息
DisplayBoard(show, ROW, COL);
//计算已经排出的非雷位置的个数
win = get_win(show, ROW, COL);
//win++;
}
}
else
{
printf("该位置已被排查过,请重新输入!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
}
else if (select == 2)
{
printf("请输入要标记的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
DisplayBoard(show, ROW, COL);
}
else if(show[x][y]=='!')
{
printf("该位置已被标记,请重新选择!\n");
}
else
{
printf("该位置不能标记,请重新选择!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
}
else
{
printf("输入有误,请重新输入!\n");
}
printf("win=%d\n", win);
}
if (win == row * col - EASY_COUNT)
{
printf("\n恭喜你,排雷成功!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
}
}
//基础功能+拓展功能
//1.标记功能(用'!')
//2.展开一片区域的功能(使用递归)
//*当排查下x,y坐标时:(1)该坐标不是雷 (2)该坐标周围没有雷 (3)该坐标没有被排查过
👀如何排查雷?
printf("请输入要排查雷的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("\n\n很遗憾,你被炸死了!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
OpenArea(mine, show,ROW,COL, x, y);
//显示排查出的信息
DisplayBoard(show, ROW, COL);
//计算已经排出的非雷位置的个数
win = get_win(show, ROW, COL);
//win++;
}
}
else
{
printf("该位置已被排查过,请重新输入!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
👀如何标记雷?
//printf("请选择:1.排查雷 2.标记雷\t");
//scanf("%d", &select);
else if (select == 2)
{
printf("请输入要标记的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
DisplayBoard(show, ROW, COL);
}
else if(show[x][y]=='!')
{
printf("该位置已被标记,请重新选择!\n");
}
else
{
printf("该位置不能标记,请重新选择!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
}
else
{
printf("输入有误,请重新输入!\n");
}
//printf("win=%d\n", win);
}
👀 如何判断输赢?
if (win == row * col - EASY_COUNT)
{
printf("\n恭喜你,排雷成功!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
}
打印结果:
😄需要使用的头文件
#include<stdio.h>
#include<stdlib.h>
#include<time.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);
四、总代码
注意:此代码分为三个部分的代码
(一)game.h文件
#include<stdio.h>
#include<stdlib.h>
#include<time.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);
(二)game.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#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)
{
int i = 0;
int j = 0;
printf("------扫雷游戏------\n");
printf("════════════════════\n");//美化棋盘
for (j = 0; j <= col; j++)
{
printf("%d|", j);
}
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");
}
printf("════════════════════\n");//美化棋盘
printf("------扫雷游戏------\n\n");
}
//设置雷的函数
void Setmine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
//行1-9 列1-9
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//统计周围雷数的函数
int get_mine_count(char board[ROWS][COLS], int row, int col,int x,int y)
{
int count = 0;
for(int i=-1;i<=1;i++)
for (int j = -1; j <= 1; j++)
{
if (board[x + i][y + j] == '1')
count++;
}
return count;
/*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 OpenArea(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col,int x, int y)
{
int count = get_mine_count(mine,ROW,COL, x, y);
if (count == 0)
{
show[x][y] = ' ';
for (int i = x - 1; i <= x + 1; i++)
{
for (int j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*' && x >= 1 && x <= row && y >= 1 && y <= col)
{
OpenArea(mine, show,ROW,COL, i, j);
}
}
}
}
else
{
show[x][y] = count + '0';
}
}
// 计算非雷和非标记的位置个数
int get_win(char board[ROWS][COLS], int row, int col)
{
int win = 0;
for(int i=1;i<=row;i++)
for (int j = 1; j <= col; j++)
{
if (board[i][j]!='*'&&board[i][j]!='!')
win++;
}
return win;
}
//排雷的函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//1.输入排查的坐标
//2.检查该坐标处是不是雷
//(1) 是雷 - 很遗憾,你被炸死了 - 游戏结束
//(2) 不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
int x = 0;
int y = 0;
int win = 0;
int select = 0;
while (win < row * col - EASY_COUNT)
{
printf("请选择:1.排查雷 2.标记雷\t");
scanf("%d", &select);
if (select == 1)
{
printf("请输入要排查雷的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("\n\n很遗憾,你被炸死了!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
OpenArea(mine, show,ROW,COL, x, y);
//显示排查出的信息
DisplayBoard(show, ROW, COL);
//计算已经排出的非雷位置的个数
win = get_win(show, ROW, COL);
//win++;
}
}
else
{
printf("该位置已被排查过,请重新输入!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
}
else if (select == 2)
{
printf("请输入要标记的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
DisplayBoard(show, ROW, COL);
}
else if(show[x][y]=='!')
{
printf("该位置已被标记,请重新选择!\n");
}
else
{
printf("该位置不能标记,请重新选择!\n");
}
}
else
{
printf("坐标不合法,请重新输入!\n");
}
}
else
{
printf("输入有误,请重新输入!\n");
}
//printf("win=%d\n", win);
}
if (win == row * col - EASY_COUNT)
{
printf("\n恭喜你,排雷成功!\n");
printf("雷的分布情况,其中('1'表示雷):\n");
DisplayBoard(mine, ROW, COL);
}
}
//基础功能+拓展功能
//1.标记功能(用'!')
//2.展开一片区域的功能(使用递归)
//*当排查下x,y坐标时:(1)该坐标不是雷 (2)该坐标周围没有雷 (3)该坐标没有被排查过
(三)test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("\t\t\t\t\t\t\t\t\t\t\t\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 };//存放排查出的雷的信息
//初始化数组的内容为指定内容
//mine数组在没有布置雷的时候,都是‘0’
InitBoard(mine, ROWS, COLS,'0');
//show数组在没有排查雷的时候都是‘*’
InitBoard(show, ROWS, COLS, '*');
//设置雷
Setmine(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:system("cls"); game();
break;
case 0:printf("退出游戏\n");
break;
default:printf("选择错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
五、效果展示
扫雷游戏展示
扫雷游戏展示
🔥好了, 今天的内容就分享到这里了。愿这篇博客能够为您带来新的思考和启示。感谢您的耐心阅读和支持。无论在人生的道路上遇到怎样的困难和挑战,记住相信自己的力量,努力前行。期待与您共同探索更多精彩的内容。再次感谢!