? Hello,各位老铁们,我又来啦,最近疫情比较严重,大家一定要做好个人防护啊。在家闲着无聊,不妨来看看C语言实现扫雷小游戏,在这之前,大家可以看看我之前的一篇关于三子棋的文章,两者类似,这样更方便理解。
//blog.csdn.net/m0_60256026/article/details/119221991?spm=1001.2014.3001.5501
题目:扫雷游戏
编程环境:Visual Studio 2019
(一)创建文件
? 创建新的空项目,创建文件头文件game.h,主要用以放头文件,全局变量,函数声明等等,在其他源文件里只需要引用自己创建的头文件game.h即可,提高效率,避免重复使用。再创建源文件text.c和game.c,text.c内放主函数,用以测试,game.h中放函数,用以游戏函数的实现,如图。
?
(二)代码分析
? 根据经典的扫雷小游戏得知,9*9的方格中有十个雷,对应一个小方格周围如果没有雷的话,就是空白,如果周围有一个雷的话,就显示1,以此类推,玩家根据数字判断雷在哪里,如果所有雷都被排查清楚,那么玩家获胜,选中雷的话,则游戏失败。
? 按照老规矩,菜单先走一遍。
int main()
{
srand((unsigned)time(NULL));
int input;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("即将退出游戏");
break;
default:
printf("输入错误!请重新输入!");
}
} while (input);
return 0;
}
void menu()
{
printf("********************************\n");
printf("********** 1.玩游戏 ************\n");
printf("********** 2.退出游戏 **********\n");
printf("********************************\n");
}
? 判断周围有几个雷的时候,要对上下左右八个地方进行判断,可是如果是边上的雷,就不好判断了,这个时候我们可以定义一个11*11的字符型数组,但是在屏幕上打印的时候,只打印中间部分。在定义数组之后,我们又遇到了一个难题,在游戏进行时,不可以让玩家知道雷所在的地方,这个时候,屏幕上打印的是9*9的星号符号,而判断周围雷个数,需要将数组赋值为1到8的数字,这时,我们不妨定义两个数组,一个专门用来展示,即char show[ROWS][COLS],一个专门用来放雷和数字,即char mine[ROWS][COLS](ROLS和COLS是全局变量,方便日后更改),函数内部,分别对两个数组进行初始化,在show数组内每一个元素都为*,游戏开始则将9*9的星号打印在屏幕上,在mine数组内每一个元素都为#,随机布置的雷赋值为1。
void begin(char board[ROWS][COLS], int rows, int cols, char ch)
{
for (int i = 0;i < rows;i++)
for (int j = 0;j < cols;j++)
board[i][j] = ch;
}
? 随后在mine数组中布置雷,与随机布置三子棋类似,利用srand函数实现真正的随机。其中row和col是全局变量ROW和COL传递过来的,是展示区域的行列数。
void setmine(char board[ROWS][COLS], int row, int col)
{
int x, y;
int i = easy;
while (i)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
i--;
}
}
}
? 点击!开始游戏!先把shou数组的内容打印到屏幕上,为了方便玩家选择行列数,可以在头一行和列标上序号,然后玩家选择坐标(这里注意玩家坐标和数组坐标之间的关系),如果选择判断对应的mine数组是1,那么踩到雷了,直接游戏结束,如果mine数组是#,那么就要判断它周围八个坐标数组是否为1,是则加一,这样计算出此坐标的对应数字。
void Print(char board[ROWS][COLS], int row, int col)
{
printf(" 1 2 3 4 5 6 7 8 9\n");
for (int i = 1;i <= row;i++)
{
printf("%d ", i);
for (int j = 1;j <= col;j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("---------------------\n");
}
void player(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int m, n;
printf("请输入您要下的坐标:");
scanf("%d %d", &m, &n);
while (1)
{
if (m > 0 && m <= 9 && n>0 && n <= 9)
{
if (mine[m][n] == '1')
{
printf("游戏结束!你输了!");
Print(mine,row,col);
break;
}
else
{
int ch=judge(mine, m, n);
mine[m][n] = '0';
show[m][n] = ch+'0';
round(mine, show, m, n);
if (win(mine, row, col) == 0)
{
printf("游戏结束,您赢了!");
Print(mine, row, col);
break;
}
else
{
Print(show, row, col);
player(show, mine, row, col);
}
}
}
else
{
printf("输入的坐标不正确,请重新输入!\n");
player(show, mine, row, col);
}
}
}
int judge(char board[ROWS][COLS], int m, int n)
{
int count = 0;
if (board[m - 1][n - 1] == '1')
count++;
if (board[m][n - 1] == '1')
count++;
if (board[m + 1][n - 1] == '1')
count++;
if (board[m - 1][n] == '1')
count++;
if (board[m + 1][n] == '1')
count++;
if (board[m - 1][n + 1] == '1')
count++;
if (board[m][n + 1] == '1')
count++;
if (board[m + 1][n + 1] == '1')
count++;
return count;
}
? 这下,游戏就可以很好的进行啦,不过,这个游戏什么时候算赢了呢?在引用一个函数进行判断输赢与否,可是怎么判断呢,在前面的player函数中,我们发现了,如果玩家选择的坐标不是雷,就给数组赋值为0,当所有雷都被排查出来的时候,mine数组中不是0就是1,不存在#,利用这一点,判断是否排雷成功。
int win(char board[ROWS][COLS], int row, int col)
{
int i, j;
int flag = 0;
for ( i = 1;i <= row;i++)
{
for( j = 0;j <= col;j++)
{
if (board[i][j] == '#')
flag = 1;
}
}
return flag;
}
? 这样一来,一个简单的扫雷小游戏就制作完成啦!
(三)效果展示
?
|