noj大作业c语言扫雷源代码,手把手教你用c语言实现扫雷操作(可能是史上最简单的了吧还有完整代码呢)...

今天我们要做的就是用C语言写出扫雷游戏的代码。对不起,今天是一个没有骚话的很正经的分享。还请继续看下去。不想看讲解的,完整代码在文末。OK,进入正文!

在写代码之前,我们应该要想想设计步骤。同上次写三子棋一样,我们第一步要做的就是打印游戏开始菜单,为了程序整体看上去显得比较整齐,我们把游戏菜单也用一个函数实现。代码如下。

void menu()

{

printf("****************************\n");

printf("******** 1.玩游戏 *******\n");

printf("******** 0.退出 *******\n");

printf("****************************\n");

}

当玩家选择玩游戏后,也就是正式要设计游戏部分了,我们还是要先初始化两个二维数组,初始化两个的目的是分清设计者雷盘和玩家雷盘,我们程序员需要能看到哪些地方有雷哪些地方没有雷,而我们展示给玩家的是一个隐藏了雷的雷盘。所以需要初始化两个雷盘。

这里的ROWS和COLS是我们雷盘的行数和列数,进行初始化时我没有用for循环(比较麻烦,但便于理解,可自行尝试)而是用了memset库函数,这个函数的具体用法如果大家不懂可以自行查阅,这里不做陈述。初始化了雷盘后就要给雷盘里赋值了,我们将玩家雷盘全初始化为’*'星号,将设计者雷盘初始化为’0’字符0。这里为什么将设计者雷盘初始化为字符0而不是其他符号,我们在这里先卖个关子,在后面会解释。

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set) //初始化雷盘

{

memset(&arr[0][0], set, rows*cols*sizeof(arr[0][0]));

}

雷盘初始化之后为了看看我们的雷盘到底有没有初始化好,我们还需要一个打印函数,以便我们将雷盘打印出来检测。打印出来的本应该只是一个雷盘,但为了输入坐标方便,我们将雷盘加上行号和列号。代码如下:

void DisplayBoard(char arr[ROWS][COLS], int row, int col) //打印雷盘

{

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 ",arr[i][j]);

}

printf("\n");

}

}

将雷盘初始化好打印后也没问题,我们就应该向雷盘中布雷了。布雷必定是一个随机的过程,所以我们需要用到随机数,为了让系统产生的随机数在我们雷盘的行和列内,需要对随机数加以限制。并且在布雷前应该先检查这个坐标有没有雷,如果已经有雷了,我们自然要重新选择地方布雷。每布一个雷,总雷数就要减一。

void SetMine(char arr[ROWS][COLS], int row, int col) //布置雷

{

int count = Easy_Count;

int x = 0;

int y = 0;

while(count)

{

x = rand()%row+1;

y = rand()%col+1;

if(arr[x][y] == '0')

{

arr[x][y] = '1';

count--;

}

}

}

完成了上述操作后,我们就应该扫雷了。在扫雷之前我们需要弄清楚几个问题。首先我们为了玩家的游戏体验,是不是让他第一次不被雷炸***,也就是如果玩家第一次踩到雷了,我们需要将雷移到别的地方,保证第一次安全不被炸***。其次如果玩家踩到了非雷的地方,我们是不是应该将这个坐标周围8个位置的雷数告诉玩家,显示出来。再有是不是还需要展开功能呢,如果这个坐标周围8个坐标也都没有雷,我们是不是可以将它们展开,直到遇到雷呢。这样其实就跟我们平时在电脑上玩的扫雷差不多了。所以我们的扫雷函数中应该有实现这几个功能的函数。

首先是我们获取周围雷数的函数。还记得我们开始给设计者雷盘布置时,没有雷的地方都是字符0,有雷的地方是字符1。现在我们需要获取一个坐标周围的雷数时,只需要将它们加起来就是了。而不用循环便利。

int GetMineCount(char mine[ROWS][COLS], int x, int y) //获取雷数

{

return mine[x-1][y-1]+mine[x-1][y]

+mine[x-1][y+1]+mine[x][y-1]+

mine[x][y+1]+mine[x+1][y-1]+

mine[x+1][y]+mine[x+1][y+1]-8*48;

}

下面是第一次保证安全的函数,这个很简单,如果它是雷的话,我们给它重新赋值,让它不是雷就可以了。

void safe(char mine[ROWS][COLS], int x, int y) //第一次安全

{

mine[x][y] = '0';

x = rand()%9+1;

y = rand()%9+1;

mine[x][y] = '1';

}

我们还需要一个判断函数,不然什么时候扫雷结束啊。总不能一直扫下去吧。当玩家没被雷炸***时,这个坐标就会显示出数字。那如果剩下的没扫的地方的和是总雷数,那就是玩家把雷扫完了,也就是游戏胜利了。

int Iswin(char show[ROWS][COLS], int row, int col)//判断胜利条件

{

int i = 0;

int j = 0;

int count = 0;

for(i=1; i<=row; i++)

{

for(j=1; j<=col; j++)

{

if(show[i][j] == '*')

{

count++;

}

}

}

return count;

}

接下来是展开函数,也就是遍历该坐标周围每一点,查它们的周围有没有雷,这个比较简单。

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y) //展开雷阵

{

int ret = 0;

ret = GetMineCount(mine, x, y);

if (ret == 0)

{

show[x][y] = ' ';

if (x - 1>0 && y>0 && show[x - 1][y] == '*')

OpenMine(mine, show, row, col, x - 1, y);

if (x - 1>0 && y + 1 <= col && show[x - 1][y + 1] == '*')

OpenMine(mine, show, row, col, x - 1, y + 1);

if (x>0 && y + 1 <= col && show[x][y + 1] == '*')

OpenMine(mine, show, row, col, x, y + 1);

if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*')

OpenMine(mine, show, row, col, x + 1, y + 1);

if (x + 1 <= row && y>0 && show[x + 1][y] == '*')

OpenMine(mine, show, row, col, x + 1, y);

if (x + 1 <= row && y - 1>0 && show[x + 1][y - 1] == '*')

OpenMine(mine, show, row, col, x + 1, y - 1);

if (x>0 && y - 1>0 && show[x][y - 1] == '*')

OpenMine(mine, show, row, col, x, y - 1);

if (x - 1>0 && y - 1>0 && show[x - 1][y - 1] == '*')

OpenMine(mine, show, row, col, x - 1, y - 1);

}

else

{

show[x][y] = GetMineCount(mine, x, y) + '0';

}

}

完成了上述准备工作后我们就可以正式开始扫雷了。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) //排雷

{

int x = 0;

int y = 0;

int times = 0;

int win = 0;

int count = 0;

while(Iswin(show, row, col) != Easy_Count)

{

printf("输入你要排查的坐标:");

scanf("%d%d",&x, &y);

times++;

if(x>=1 && x<=row && y>=1 && y<=col) //判断坐标合法

{

if(mine[x][y] == '1' ) //为雷分为第一次为雷和其他次为雷

{

if(1 == times) //第一次为雷抢救一下

{

safe(mine, x, y);

count = GetMineCount(mine, x, y);

show[x][y] = count+48;

OpenMine(mine, show, ROW, COL, x, y);

DisplayBoard(show, row ,col);

win++;

}

else //不是第一次不抢救

{

printf("很遗憾,你被炸***了\n");

DisplayBoard(mine, row, col);

break;

}

}

if(mine[x][y] == '0') //输入坐标不是雷

{

count = GetMineCount(mine, x, y); //获取周围雷数

show[x][y] = count+48; //显示雷数

OpenMine(mine, show, ROW, COL, x, y);

DisplayBoard(show, row ,col);

win++;

}

}

else

{

printf("输入坐标无效,重新输入\n");

}

}

if(Iswin(show, row, col) == Easy_Count) //获胜条件

{

printf("恭喜你,排雷成功\n");

printf("共计扫雷次数为%d\n",times);

DisplayBoard(mine, row, col);

}

}

至此我们的函数的游戏部分就完成了,我们需要把它串起来。

完整代码如下,大家自行就能看懂。

2c1a5057602a7f3cdf9059cb629068b0.png

我们将所有代码分成这三个部分,game.h里放我们所有自己编写的函数的头文件。game.c里放我们自己编写的函数。teat.c里面放我们的主函数,以及将游戏串起来的game函数。

game.h内的代码

#ifndef __GAME_H__

#define __GAME_H__

#include

#include

#include

#include

#define ROW 9

#define COL 9

#define ROWS 11

#define COLS 11

#define Easy_Count 10

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set); //初始化雷阵

void DisplayBoard(char arr[ROWS][COLS],int row, int col); //打印雷盘

void SetMine(char arr[ROWS][COLS], int row, int col); //布置雷

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); //扫雷

int GetMineCount(char mine[ROWS][COLS], int row, int col); //获取周围雷数

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y); //展开雷阵

void is_win(char mine[ROWS][COLS], int x, int y);

#endif//__GAME_H__

game.c内的代码

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set) //初始化雷盘

{

memset(&arr[0][0], set, rows*cols*sizeof(arr[0][0]));

}

void DisplayBoard(char arr[ROWS][COLS], int row, int col) //打印雷盘

{

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 ",arr[i][j]);

}

printf("\n");

}

}

void SetMine(char arr[ROWS][COLS], int row, int col) //布置雷

{

int count = Easy_Count;

int x = 0;

int y = 0;

while(count)

{

x = rand()%row+1;

y = rand()%col+1;

if(arr[x][y] == '0')

{

arr[x][y] = '1';

count--;

}

}

}

int GetMineCount(char mine[ROWS][COLS], int x, int y) //获取雷数

{

return mine[x-1][y-1]+mine[x-1][y]

+mine[x-1][y+1]+mine[x][y-1]+

mine[x][y+1]+mine[x+1][y-1]+

mine[x+1][y]+mine[x+1][y+1]-8*48;

}

void safe(char mine[ROWS][COLS], int x, int y) //

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值