C语言实现简化版扫雷
如果代码有问题,希望大家能指出来!
先简单说一下扫雷的游戏规则吧!
《扫雷》是一款大众类的益智小游戏,游戏规则是在最短的时间内,根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输,但许多玩过扫雷的人却仍然有一些规则不明白。
听说点赞评论的人以后工资能过万。
比如在扫雷的时候棋盘上出现的数字是什么意思?很多人可能现在都搞不懂,所以一直在用运气扫雷
比如这里的数字2,就是说明它周围与它相邻的8个位置有2个雷,同样如果是数字8那它周围全是雷。
然后就来看一下C语言实现简化版扫雷的步骤吧!
1.首先需要一个游戏菜单让玩家选择
2.需要生成扫雷的棋盘,字符‘0’非雷,字符‘1’则是雷
3.再到棋盘上布置雷
4.然后就是扫雷
首先理清游戏思路,一进入游戏肯定是打印游戏菜单然后让用户选择,当然游戏不可能只玩一把,所以用do,while循环可以让游戏一直玩。
void menu()
{
printf("***************************\n");
printf("******** 1.玩游戏 *******\n");
printf("******** 0.退出 *******\n");
printf("***************************\n");
int main()
{
int inpute = 0;
srand((unsigned int)time(NULL));
do
{
menu();//游戏菜单
printf("请选择(1/0)>");
scanf("%d", &inpute);
switch (inpute)
{
case 1://玩游戏
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (inpute);
return 0;
}
当用户选择1开始玩游戏,注意这里的do,while循环的条件是用户选择的时输入的数字,也就是说只有当用户选择0的时候游戏才会退出,不然就是一直玩,哈哈!
然后就到了生成棋盘,这里我们需要生成两个棋盘,一个是用来存放布置好的雷的信息,另一个用来存放排查出雷的信息
这里#define定义了棋盘的行和列方便修改
//雷的个数
这里的ROW行和COL列可以理解,为什么还要定一个+2的行和列呢?
因为我们排雷的时候如果排的是边界上的位置,要统计雷的个数是不好统计的所以要多出两行两列方便统计雷的个数,当然最边界的两行两列不会布置雷用户也看不到
我们在定义的game函数里生成两个二维数组棋盘,再初始化它。定义一个InitBoard函数初始化棋盘,分别把两个二维数组棋盘传过去,生成两个棋盘。这里字符‘0’代表非雷字符,当然最后只有*号是看得见得。生成棋盘我们把两个数组的行列和要放得字符分别传过去,用循环初始化两个棋盘。
void InitBoard(char mine[ROWS][COLS], int rows, int cols, char ret)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
mine[i][j] = ret;
}
}
}
void game()
{
//创建对应的二维数组
char mine[ROWS][COLS];//存放布置好雷的信息
char check[ROWS][COLS];//存放排查出雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(check, ROWS, COLS, '*');
//打印棋盘
//DisplayBoard(mine, ROW, COL);测试查看布置好的雷的
DisplayBoard(check, ROW, COL);
}
初始化棋盘后可以先用定义的DisplayBoard函数打印出棋盘看看效果,这些屏蔽的代码是测试用的。也就是看看棋盘的效果。注意打印棋盘传的是ROW和COL也就是9x9,和初始化不一样,因为9x9才是给用户看的,11x11是我们用来实现扫雷统计个数的
void DisplayBoard(char mine[ROWS][COLS], int row, int col)
{
printf("------扫雷游戏------\n");
int i = 0;
int j = 0;
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 ", mine[i][j]);
}
printf("\n");
}
printf("--------------------\n");
}
这里的打印行号就是方便用户找到行和列不然,鬼知道是几行几列,费眼。
棋盘生成好了,就到了布置雷了。
void SetMine(char mine[ROWS][COLS], int row, int col, int lei)
{
while (lei)
{
//1-9的随机数
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';//坐标没有雷的话就布置一颗雷
lei--;//每布置成功一颗雷就就减一
}
}
void game()
{
//创建对应的二维数组
char mine[ROWS][COLS];//存放布置好雷的信息
char check[ROWS][COLS];//存放排查出雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(check, ROWS, COLS, '*');
//打印棋盘
//DisplayBoard(mine, ROW, COL);测试查看布置好的雷的
DisplayBoard(check, ROW, COL);
SetMine(mine,ROW,COL,THUNDER);//布置雷
//DisplayBoard(mine, ROW, COL);便于查看自己布置的雷
FineMine(mine, check, ROW, COL);//排查雷
}
雷是随机布置的,布置雷的函数传过去的我们已经用#define定义的雷的个数
//雷的个数
这里可能不知道rand函数是什么意思,它和main函数的这条代码是一起用的.因为随机数一个工程只需要生成一次所以放在main函数里
srand((unsigned int)time(NULL));
是用来生成随机数的,我这条博客有详细介绍>随机数,这里我们对行和列取余加1是生成1到9的随机数,用到while循环,当棋盘上是字符‘0’也就是没有布置雷的时候我们就布置一个雷,每布置成功一颗雷就减一,10颗雷布置完后循环结束
while (lei)
{
//1-9的随机数
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';//坐标没有雷的话就布置一颗雷
lei--;//每布置成功一颗雷就就减一
}
}
让后就到了排雷了,排雷两个二维数组都会用到,布置好的雷和排查出的雷,排查出的雷是要被打印查来的
void game()
{
//创建对应的二维数组
char mine[ROWS][COLS];//存放布置好雷的信息
char check[ROWS][COLS];//存放排查出雷的信息
FineMine(mine, check, ROW, COL);//排查雷
排雷也是个循环,先定义个变量用来记录排查的次数,棋盘一共row*col-10个位置不是雷,也就是说有71个地方不是雷,每排查一次win就加一,当win等于71时说明排雷成功
用户输入坐标只能1-9所以要判断是否违规,如果输入正确则需要判断是不是雷,是的话游戏结束把布置好雷的信息打印出来给用户看,不是的话就要统计雷的个数,这里定义了一个函数来统计坐标周围的个数
//计算mine数组周围8个坐标有几个雷
int GeMinelei(char mine[ROWS][COLS],int x ,int y)
{
return mine[x-1][y-1] +
mine[x][y-1] +
mine[x+1][y-1] +
mine[x-1][y] +
mine[x+1][y] +
mine[x-1][y+1]+
mine[x][y+1] +
mine[x+1][y+1] - 8 * '0';
}
因为棋盘上放的时字符‘0’和‘1’,所以只要把它周围的8个位置相加就知道了雷的个数,但这里时字符里而不是数字,所以在最后减去了8*‘0’,因为字符1减去字符0等于1,字符0减去字符0等于0.
‘1’-‘0’=1
‘0’-‘0’=0
计算完后再把排查出雷的信息棋盘打印出来
void FineMine(char mine[ROWS][COLS], char check[ROWS][COLS], int row, int col)
{
int win = 0;
//9*9-10=71
while (win<row*col - THUNDER)
{
int x = 0;
int y = 0;
printf("请输入要排查的x,y坐标>");
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 lei= GeMinelei(mine, x, y);
check[x][y] = lei + '0';//存放的是数字字符
DisplayBoard(check, row, col);
win++;
}
}
else
{
printf("违规坐标,请重新输入!\n");
}
if (win == row*col - THUNDER)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
}
完整代码有点多,我是分3个模块来写的。完整代码在我的仓库扫雷完整代码链接
记得点赞,评论哦。