扫雷的基本实现
一,基本运行的过程
第一步:打印菜单,写开始游戏的程序;
第二步:创建两个地图,一个埋雷,一个用于显示;
第三步:将两个地图初始化;
第四步:排雷;
第五步:判断是否踩雷;
第六步:判断是否排除所有雷;
二,代码实现
一,打印菜单,写开始游戏的程序;
void muen()
{
printf("***********************\n");
printf("*********1.Play********\n");
printf("*********0.Exit********\n");
printf("***********************\n");
}
int main()
{
int a = 1;
do
{
muen();
printf("请选择:>");
scanf("%d", &a);
switch (a)
{
case 1:
game();
break;
case 0:
printf("游戏退出\n");
break;
default:
printf("输入错误,请重新输入:\n");
}
} while (a);
return 0;
}
二,创建两个地图,一个埋雷,一个用于显示;
先定义地图的大小,我们要写的地图为9*9,说以要创建11行11列的地图(为什么要创建11行11列的,待会会说)
#define ROW 9
#define COL 9
#define ROWS 11
#define COLS 11
#define MINE 10
void game()
{
int a = 1;
char show[ROWS][COLS] = { 0 };//创建一个ROW行,COL列的二维数组用于显示扫雷区域
char mine[ROWS][COLS] = { 0 };//创建一个ROW行,COL列的二维数组用于创建扫雷区域
intnshow(show, ROWS, COLS);//初始化展示棋盘,使其全部为*
intnmine(mine, ROWS, COLS);//初始化棋盘使其全部为0
setmine(mine, ROW, COL);
do
{
Displayshow(show, ROW, COL);//打印展示地图
printf("请输入要排查的坐标:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
a=findmine(mine ,show, ROWS, COLS,x,y);
if (a == 0)
break;
a=chakwin(show, ROWS, COLS);
if (a == 0)
{
printf("恭喜你,排查完所有雷!\n");
break;
}
} while (a);
}
用于打印盘的的代码
void Displayshow(char show[ROWS][COLS], int rows, int cols)
{
int i = 0;
int j = 0;
printf("--------------扫雷游戏--------------\n");
for (i = 0; i < rows; i++)
{
if (i == 0)//打印第一行列的坐标
{
printf("%d ", i);
for (j = 0; j < cols; j++)
{
printf("%d ", j + 1);
}
printf("\n");
}
printf("%d ", i+1);//打印行数
for (j = 0; j < cols; j++)
{
printf("%c ", show[i][j]);
}
printf("\n");
}
}
三,初始化地图
void intnshow(char show[ROWS][COLS], int rows, int cols)
{
int i = 0;
int j = 0;
for (i = 0; i <= rows; i++)
{
for (j = 0; j <= cols; j++)
{
show[i][j] = '*';
}
}
}
void intnmine(char show[ROWS][COLS], int rows, int cols)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
show[i][j] = '0';
}
}
}
设置雷
void setmine(char mine[ROWS][COLS], int row, int col)
{
int connut = 0;
srand((unsigned)time(NULL));
while ( connut < MINE)
{
int x = rand() % row+1;//让随机数在1~row
int y = rand() % col+1;//让随机数在1~col
if ((mine[x][y] == '0'))//当坐标不为‘0’时设置雷
{
mine[x][y] = '1';
connut++;
}
}
}
这里使用时间作为随机数的种子
四,排雷
do
{
Displayshow(show, ROW, COL);
printf("请输入要排查的坐标:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
a=findmine(mine ,show, ROWS, COLS,x,y);
if (a == 0)
break;
a=chakwin(show, ROWS, COLS);
if (a == 0)
{
printf("恭喜你,排查完所有雷!\n");
break;
}
用于排雷、检查是否排雷完毕的代码
int findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int x,int y)
{
while (1)
{
if (x >= 1 && x <= row&&y >= 1 && y <= col)
{
if (mine[x][y] == '1')//踩雷
{
printf("很遗憾,你被炸死了!\n");
//Displayshow(mine, ROWS, COLS);
return 0;
}
else
{
int count =get_mine_cunt(mine, x, y);
show[x-1][y-1] = count + '0';
if (count == 0)//当该坐标雷数为0时,根据规则周围都没雷,可以全部展开
{
findmines(mine, show, row, col, x, y-1);
findmines(mine, show, row, col, x, y + 1);
findmines(mine, show, row, col, x - 1, y + 1);
findmines(mine, show, row, col, x - 1, y - 1);
findmines(mine, show, row, col, x + 1, y+1);
findmines(mine, show, row, col, x + 1, y-1);
findmines(mine, show, row, col, x - 1, y);
findmines(mine, show, row, col, x + 1, y);
}
return 1;
}
}
else
{
printf("坐标非法,请重新输入!\n");
return 1;
}
}
}
此处还有数雷的代码
int get_mine_cunt(char mine[ROWS][COLS], int x, int y)
{
return mine[x][y - 1] +
mine[x][y + 1] +
mine[x - 1][y - 1] +
mine[x - 1][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y + 1] +
mine[x - 1][y] +
mine[x + 1][y] - 8 * '0';
}
设定11行11列,只需要其中9行9列,这可以让我们数类似与第一行第一列的代码时更方便
void findmines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
if (x >= 1 && x <= row&&y >= 1 && y <= col)
{
int count = get_mine_cunt(mine, x, y);
show[x - 1][y - 1] = count + '0';
}
}
检查是否排查完毕的代码
int chakwin(char show[ROWS][COL], int row, int col)
{
int count = 0;
int i = 1;
int j = 1;
for (i = 1; i <= ROWS; i++)
{
for (j = 1; j <= COLS; j++)
{
if (show[i][j] == '*')
count++;
}
}
if (count == (MINE+40))
return 0;
else
return 1;
}
三,难点
一,布置雷
利用srand((unsigned)time(NULL));设置时间戳,利用rand函数随机设置雷;学习srand函数时,不知道到要对时间进行无符号类型转化,查阅资料后解决。
二,数雷
这里设置11行11列的地图,目的是能更方便的数1行1列位置的雷,在数第一行第一列的雷时,实际上是在数雷地图上的第2行第2列的坐标,这样就可以使数雷的时候直接数2行2列周围的8个格子就行,用简单代码,完成数雷的操作。
三,雷的放置
放置雷时,由于全部初始化为‘0’,所以放置时只需令其为’1’,数雷时只需将周围8个位置的值相加(建立的类型是char,故相加值是其ASC码值),再减去8*‘0‘就可以得到该坐标雷的数量,打印时要记得加上’0’,才是显示该坐标周围雷的数量。
四,打印、扫雷时
坐标一定要对齐!!!
五,未实现的功能
扫雷时,当该坐标没有雷,有一大片的空白时,需全部打印出来,奈何本人技术不足,难以实现,只能将周围的8个坐标显示出来,欢迎各位大佬给我提供技术支持,这个bug我先记着了,日后学成归来,定解决这个bug!!!
萌新学习,欢迎各位大佬指教!!!