作者:阿辉不一般
你说呢:生活本来沉闷,但跑起来就有风
专栏:爱上C语言
作图工具:draw.io(免费开源的作图网站)
如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主,如有不足还请指点,博主及时改正,感谢大家支持!!!
大家好啊!今天咱们来整一个有意思的小游戏扫雷,相信大家对扫雷并不陌生,那接下来就跟着阿辉把它拿捏了
1.实现一个函数打印菜单选择玩游戏和退出游戏
2.创建两个二维数组,一个布置雷,一个打印扫雷的游戏的展示棋盘
3.布置雷
4.打印棋盘
5.玩家输入坐标排雷
6.判断坐标是否是雷,是雷game over,不是雷显示周围有几个雷,展开一片
7.判断玩家是否赢了
采用模块化设计,分为game.c
,game.h
,test.c
三部分
#include
#include
#include
//当排雷时判断周围有几个雷,为防止边缘的坐标判断时越界访问,9*9的棋盘实际上用的11*11的数组
#define ROWS 11 //行
#define COLS 11 //列
//虽然用的是11*11的数组,但实际上仅操作里面9*9的部分
#define ROW 9 //行
#define COL 9 //列
//布置雷的数目
#define Easy_mine 10
//初始化棋盘
void Initboard(char show[ROWS][COLS], int row, int col, char set);
//布置雷
void Set_mine(char mine[ROWS][COLS],int row, int col);
//打印棋盘
void Display_show(char show[ROWS][COLS], int row, int col);
//玩家排雷
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//展开一片
void unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int *p);
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()//打印菜单,选择进入游戏还是退出
{
printf("*********************************\n");
printf("************ play:> 1 **********\n");
printf("************ exit:> 0 **********\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, '*');
//给初始化后的mine数组中布置雷,仅仅在要显示的9*9的范围里布置雷
Set_mine(mine, ROW, COL);
//打印棋盘
Display_show(show, ROW, COL);
//Display_show(mine, ROW, COL);
//排查雷
Find_mine(mine,show,ROW,COL);
}
int main()
{
srand((unsigned int)time(NULL));
menu();
int input = 0;
do
{
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新选择!\n");
}
} while (input); //根据玩家输入的值,实现重复游戏和退出游戏
return 0;
}
扫雷游戏逻辑的具体实现
//传入字符数组首地址,行,列以及初始化的类容,可以更根据初始化类容初始化棋盘
void Initboard(char show[ROWS][COLS], int row, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
show[i][j] = set;
}
}
}
void Set_mine(char mine[ROWS][COLS], int row, int col)
{
int count = 0;
while (count < Easy_mine) //雷的数目布置完毕跳出循环
{
//使用rand函数在9*9的范围内随机生成雷
int x = rand() % row + 1;
int y = rand() % col + 1;
//判断要生成雷的坐标是否已经被布置雷了,防止重复布置雷
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count++; //记录成功布置类的个数
}
}
}
界面展示
void Display_show(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("-------------扫雷----------------\n");
//打印第一行的数字,方便玩家输入坐标
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
//11*11的数组但是仅仅打印中间的9*9
for (i = 1; i < row + 1; i++)
{
printf("%d ", i); //打印第一列的数字,方便玩家输入坐标
for (j = 1; j < col + 1; j++)
{
printf("%c ", show[i][j]);
}
printf("\n");
}
printf("-------------扫雷----------------\n");
}
//同时传入mine数组和show数组
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int count = 0;
while (1)
{
int x = 0;
int y = 0;
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y); //玩家输入要排雷的坐标
//判断玩家要排查的坐标是否合法,防止越界
if ((x <= ROW && x > 0) && (y <= COL && y > 0))
{
`//判断玩家要排查的坐标是否未被排查
if (show[x][y] == '*')
{
//判断玩家要排查雷的坐标是否是雷
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
Display_show(mine, ROW, COL);
break;
}
else
{
//玩家要排查的坐标不是雷,则展示周围有几个雷
//传入的count用于记录玩家排的不是雷的坐标
unfold(mine, show, x, y,&count);
//打印排查过后的棋盘show
Display_show(show, ROW, COL);
}
}
else
{
printf("重复输入,请重新输入!\n");
}
}
else
{
printf("输入错误,请重新输入!\n");
}
//count的值为(9*9 - 10)的时候说明玩家排雷成功
if (count ==ROW * COL - Easy_mine)
{
printf("恭喜你,排雷成功!\n");
Display_show(mine, ROW, COL);
break;
}
}
}
void unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* p)
{
int sum = 0;
//判断坐标是否合法,防止越出9*9的范围,判断坐标是否被判断过防止死递归
if ((x <= ROW && x > 0) && (y <= COL && y > 0) && show[x][y] == '*')
{
(*p)++;
//判断玩家要排查的坐标周围8个坐标有几个雷
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
//sum记录周围雷的个数
//因为mine数组中存的是字符,雷是'1',非雷是'0',由于字符在内存中存的是ASC码值,'0'-'0'=数字0,'1'-'0'=数字1
sum = sum + mine[x + i][y + j] - '0';
}
}
//如果要排查坐标周围没有雷,就展开一片
if (sum == 0)
{
//给已经判断周围没有雷的坐标赋上' '(空格),用于打印展示以及作为已经被判断的标志防止死递归
show[x][y] = ' ';
//遍历走位坐标实现展开一片
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
unfold(mine, show, x + i, y + j, &(*p));
}
}
}
//当周围有雷就给坐标对应数组赋上周围雷的个数的数字字符
else
{
show[x][y] = '0' + sum;
return;
}
}
else
return;
}
感谢各位美女帅哥能看到这, 希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力