用C语言做扫雷游戏的思路和方法是什么?
扫雷游戏想必大家都有玩过吧,如果我们自己编程该怎样做呢?这篇文章就给大家来分享扫雷游戏的实现,这里是用C语言实现的,下文介绍了实现思路、方法及代码,文中示例代码介绍的很详细,感兴趣的朋友接下来一起跟随小编看看吧。
一,设计思路
这便是一个标准的扫雷,换做代码实现,我们需要考虑以下几点:
1.棋盘的设计与初始化
2.在棋盘中放入雷
3.统计雷数
4.如何实现“一片”的效果
5.输赢的判断
接下来我们进行具体操作。
二.实现方式
1.菜单的打印
对任意一个游戏,菜单是必不可少的,也是最简单的部分,直接上代码
void menu()
{
printf("------------------扫雷------------------\n");
printf("---------------1.开始游戏---------------\n");
printf("---------------0.退出游戏---------------\n");
}
int main()
{
srand((unsigned int)time(NULL));
int a = 0;
do
{
menu();
scanf("%d", &
a);
if (a == 0)
{
break;
}
game();
}
while (a);
return 0;
}
其中srand是为了求随机值,用来布置雷
2.game函数
主菜单完后进入game函数,在game函数里我们就要开始主要的游戏部分,如棋盘初始化与打印等,当然这些步骤都依靠函数完成,game函数只相当于集合了一系列的游戏模块
void game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
initeboard(mine, ROWS, COLS, '0');
initeboard(show, ROWS, COLS, '*');
//初始棋盘
displayboard(show, ROW, COL);
//打印棋盘
mine_make(mine, ROW, COL);
//设置雷
//displayboard(mine, ROW, COL);
find_mine(mine, show, ROWS, COLS);
//排查雷
}
3.棋盘的初始化与打印
可以看到,我在game函数里初始了两个棋盘,为什么要两个呢?
其实,一个是为了放置了雷,一个为了展示给玩家,为什么不用一个呢,我们要在放雷处用'1',表示不放雷处用‘0',这样计算一个坐标周围雷的数量就会更简单,接下来看一段代码:
#define _CRT_SECURE_NO_WARNINGS
#include stdio.h>
#include stdlib.h>
#include time.h>
#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2
这里我们看到定义了一个ROWS和COLS这又是为何呢?
回归棋盘
扫雷时当你确认一个点时,它会对此点周围的八个点进行排查看是否有泪,当坐标位于红线处时没有无法判断八个,因此有了ROWS与COLS,这时,有人就会问了:那埋雷的地方用ROW COL就可以了,还不用担心雷跑到外边我们加的框,想法很好,但我们有两个棋盘,必须对应,而且也不存在跑出雷的情况,往下分析你就会知道
void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盘初始化,此处用了个节省步骤的方法,不用两个棋盘依次初始化
{
int i = 0;
int j = 0;
for (i = 0;
i rows;
i++)
{
for (j = 0;
j cols;
j++)
{
board[i][j] = s;
}
}
}
void displayboard(char board[ROWS][COLS], int row, int col)//棋盘打印
{
int i = 0;
int j = 0;
printf(" ");
//与行中打印的0%d对应
for (j = 0;
j =col;
j++)
{
printf(" %d ", j);
}
printf("\n");
printf("-");
for (j = 1;
j = col + 1;
j++)
{
printf("---");
printf("|");
}
printf("\n");
//列对应打印完成
for (i = 1;
i = row;
i++)
{
if (i = 9)
{
printf(" 0%d ", i);
}
else
printf(" %d ", i);
printf("|");
for (j = 1;
j = col;
j++)
{
printf(" %c ", board[i][j]);
printf("|");
}
printf("\n");
printf("-");
for (j = 1;
j = col+1;
j++)
{
printf("---");
printf("|");
}
printf("\n");
//行对应嵌套在内部 打印的数前加0是为了让当行数大于9时能够对应 如09与10
}
}
棋盘的打印做了行列对应,所以可能有点不明显
4.雷的放置,雷的个数
雷的放置很简单,在棋盘‘0',处放置就行,因为我们对随机数的算式使随机数只会出现在0-9没有跑出的情况
mine_make(char mine[ROWS][COLS], int row, int col)//设置雷
{
int count = 10;
while (count)
{
int x = rand() % 10;
int y = rand() % 10;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
雷的个数就需要一定考虑了:
首先,我们需要把周围八个位置是否有雷,有多少个雷判断出来,这时我们设计‘0' ‘1'类型就排上用场了,但是注意,这是字符,不是数字
一张表 让我们知道如何转型
当然返回的数字记得转成字符类型
int get_mine(char mine[ROWS][COLS], int i, int j)//得到一个坐标附近雷的个数
{
return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +
mine[i][j - 1] + mine[i][j + 1] +
mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';
//此处我们的数字其实是字符,用此方法可以转为数字整形 }
5.递归实现一片效果
当不为雷是会展开附近一片不为雷,提高游戏效率
void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//递归方法实现一大片
{
show[x][y] = ' ';
//先让输入金的坐标处变为空格,因为已经判定过雷所以可以直接转空格
int i = 0;
int j = 0;
int ret = 0;
for (i = x - 1;
i = x + 1;
i++)
{
for (j = y - 1;
j = y + 1;
j++)//嵌套for循环表示输入坐标包括自生及周围八个
{
if (i >
0 &
&
i = ROW &
&
j >
0 &
&
j = COL &
&
mine[i][j] != '1' &
&
show[i][j] == '*')//防止出现负坐标,避免有雷,避免输入重复
{
ret = get_mine(mine, i, j);
//判断ret是0或非0,并得出周围雷数
if (!ret)//如果ret=0,!ret便是非0;为真
{
spread(show, mine, i, j);
//递归
}
if (ret)//ret!=0时为真,便打印数
{
show[i][j] = ret + '0';
//使数字转成对应字符
}
}
}
}
}
效果展示:
6.排查雷
负责判断是否被炸死及游戏胜利
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
printf("请输入坐标\n");
int i = 0;
int j = 0;
int win = 0;
while (row*col-10)//因为是十个雷,所以是—10,因为下总数减10就赢了,所以可以以此跳出循环,当然要是雷部位10,定一个变量就行,此处就不改了
{
scanf("%d %d", &
i, &
j);
if (mine[i][j] == '1')
{
printf("你挂了\n");
displayboard(mine, ROW, COL);
break;
}
else
{
show[i][j] = get_mine(mine, i, j)+'0';
spread(show,mine, i, j);
displayboard(show, ROW, COL);
win++;
}
}
if (win ==row * col - 10)
{
printf("恭喜你,成功了\n");
displayboard(mine, ROW, COL);
}
}
具体注释都在代码里了
正常情况把打印雷盘注释就行,就可以正常游戏了
三.完整代码
#define _CRT_SECURE_NO_WARNINGS
#include stdio.h>
#include stdlib.h>
#include time.h>
#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2
void menu()
{
printf("------------------扫雷------------------\n");
printf("---------------1.开始游戏---------------\n");
printf("---------------0.退出游戏---------------\n");
}
void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盘初始化,此处用了个节省步骤的方法,不用两个棋盘依次初始化
{
int i = 0;
int j = 0;
for (i = 0;
i rows;
i++)
{
for (j = 0;
j cols;
j++)
{
board[i][j] = s;
}
}
}
void displayboard(char board[ROWS][COLS], int row, int col)//棋盘打印
{
int i = 0;
int j = 0;
printf(" ");
//与行中打印的0%d对应
for (j = 0;
j =col;
j++)
{
printf(" %d ", j);
}
printf("\n");
printf("-");
for (j = 1;
j = col + 1;
j++)
{
printf("---");
printf("|");
}
printf("\n");
//列对应打印完成
for (i = 1;
i = row;
i++)
{
if (i = 9)
{
printf(" 0%d ", i);
}
else
printf(" %d ", i);
printf("|");
for (j = 1;
j = col;
j++)
{
printf(" %c ", board[i][j]);
printf("|");
}
printf("\n");
printf("-");
for (j = 1;
j = col+1;
j++)
{
printf("---");
printf("|");
}
printf("\n");
//行对应嵌套在内部 打印的数前加0是为了让当行数大于9时能够对应 如09与10
}
}
mine_make(char mine[ROWS][COLS], int row, int col)//设置雷
{
int count = 10;
while (count)
{
int x = rand() % 10;
int y = rand() % 10;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int get_mine(char mine[ROWS][COLS], int i, int j)//得到一个坐标附近雷的个数
{
return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +
mine[i][j - 1] + mine[i][j + 1] +
mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';
//此处我们的数字其实是字符,用此方法可以转为数字整形
}
void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//递归方法实现一大片
{
show[x][y] = ' ';
//先让输入金的坐标处变为空格,因为已经判定过雷所以可以直接转空格
int i = 0;
int j = 0;
int ret = 0;
for (i = x - 1;
i = x + 1;
i++)
{
for (j = y - 1;
j = y + 1;
j++)//嵌套for循环表示输入坐标包括自生及周围八个
{
if (i >
0 &
&
i = ROW &
&
j >
0 &
&
j = COL &
&
mine[i][j] != '1' &
&
show[i][j] == '*')//防止出现负坐标,避免有雷,避免输入重复
{
ret = get_mine(mine, i, j);
//判断ret是0或非0,并得出周围雷数
if (!ret)//如果ret=0,!ret便是非0;为真
{
spread(show, mine, i, j);
//递归
}
if (ret)//ret!=0时为真,便打印数
{
show[i][j] = ret + '0';
//使数字转成对应字符
}
}
}
}
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
printf("请输入坐标\n");
int i = 0;
int j = 0;
int win = 0;
while (row*col-10)//因为是十个雷,所以是—10,因为下总数减10就赢了,所以可以以此跳出循环,当然要是雷部位10,定一个变量就行,此处就不改了
{
scanf("%d %d", &
i, &
j);
if (mine[i][j] == '1')
{
printf("你挂了\n");
displayboard(mine, ROW, COL);
break;
}
else
{
show[i][j] = get_mine(mine, i, j)+'0';
spread(show,mine, i, j);
displayboard(show, ROW, COL);
win++;
}
}
if (win ==row * col - 10)
{
printf("恭喜你,成功了\n");
displayboard(mine, ROW, COL);
}
}
void game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
initeboard(mine, ROWS, COLS, '0');
initeboard(show, ROWS, COLS, '*');
//初始棋盘
displayboard(show, ROW, COL);
//打印棋盘
mine_make(mine, ROW, COL);
//设置雷
displayboard(mine, ROW, COL);
find_mine(mine, show, ROWS, COLS);
//排查雷
}
int main()
{
srand((unsigned int)time(NULL));
int a = 0;
do
{
menu();
scanf("%d", &
a);
if (a == 0)
{
break;
}
game();
}
while (a);
return 0;
}
总结
以上就是用C语言实现扫雷游戏的介绍了,本文只是提供了一种实现思路,代码仅供参考,需要的朋友可以了解看看,希望对大家学习C语言有帮助,想要了解更多可以继续浏览网络其他相关的文章。
文本转载自脚本之家
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 用C语言做扫雷游戏的思路和方法是什么?
本文地址: https://pptw.com/jishu/655290.html
