对扫雷游戏进行编程,我们将扫雷游戏分成三个文件来进行编程,这有利于我们养成良好的习惯。
一、扫雷游戏的框架
我们将扫雷游戏分为这三个文件来编程,它们分别是:
1.test.c文件:在这个文件中,我们主要实现整个游戏的逻辑,只编写一个主函数,便于观看。
2.game.c文件:在这个文件中,我们要实现这个游戏的具体功能,即编写各个函数来实现扫雷游戏对应的功能,这个部分是实现扫雷游戏最为重要的代码。
3.game.h文件:在这个文件中,主要包含了相关的头文件,后续编程中所需要用到的全局变量和所需函数的声明。
二、扫雷游戏的具体实现
1.菜单函数:每个游戏在开始时都会显示一个菜单来供你选择,你要通过输入一个数字来选择是否进行游戏。
do
{
menu();
printf("请输入一个数字来选择:");
scanf_s("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束!\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
void menu()
{
printf("**********\n");
printf("**1.play**\n");
printf("**0.exit**\n");
printf("**********\n");
}//展示菜单
我们用switch语句来实现菜单的选择功能,do while语句来控制循环,只有当输入的数字为0时,才跳出循环,游戏也就结束了,当选择1时,就会调用game函数,进行游戏的游玩,输入其他数字时会提醒你输入错误并重新输入。
2.game函数:这是游戏主要功能的实现。
void game()
{
char mine[ROWS][COLS] = { 0 };//存放雷的数组
char show[ROWS][COLS] = { 0 };//展示给玩家看的数组,排查出雷的信息
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
setMine(mine, ROW, COL);
//Boardprint(mine, ROW, COL);
Boardprint(show, ROW, COL);
findMine(mine, show, ROW, COL);
}
在这里面有许多其他的函数,下面会给大家一一解释,先给大家解释二维数组mine和show,mine数组是用来存放雷的数组,show数组是展示给玩家看的数组,我们要做的扫雷游戏的棋盘是9×9的棋盘,但我们定义的二维数组是11×11的,这是因为后面我们要排查雷的个数,要对周围雷的个数进行排查,这种情况下可能会造成数组下标越界的情况。
像上图所示那样,当我要排查1所在的那个格子周围有多少个雷时,也要对下面三个格子进行排查,这个时候就会造成数组下标越界,所以,我们将数组定义成11×11的数组,这样在排查时就不会造成数组下标越界。
3.initBoard函数(初始化数组(棋盘)函数):
void initBoard(char a[ROWS][COLS], int b, int c, char d)//初始化数组(棋盘)
{
int i, j;
for (i = 0; i < b; i++)
{
for (j = 0; j < c; j++)
{
a[i][j] = d;
}
}
}
将数组全部初始化为某个字符,取决于你传参传进来哪个字符。
4.setMine函数(设置雷函数):
当棋盘初始化完后,我们便要设置雷了。
void setMine(char a[ROWS][COLS], int b, int c)//布置雷
{
int count = minecount;
while (count)
{
int x = rand() % b + 1;//随机生成雷的行坐标
int y = rand() % c + 1;//随机生成雷的列坐标
if (a[x][y] == '0')//只有不是雷时才能设置雷
{
a[x][y] = '1';
count--;
}
}
}
我们利用srand和rand函数随机在棋盘上布置雷,定义雷的个数minecount为10,每成功布置了一个雷,count就减减,布置完10个雷后就跳出循环。
5.Boardprint函数(棋盘打印函数)
在设置好雷后,我们便要打印show数组让玩家进行排雷游戏。
void Boardprint(char a[ROWS][COLS], int b, int c)//打印棋盘
{
int i, j;
for (i = 0; i <= c; i++)
{
printf("%d ", i);//打印列坐标
}
printf("\n");
for (i = 1; i <= b; i++)
{
printf("%d ", i);//打印行坐标
for (j = 1; j <= c; j++)
{
printf("%c ", a[i][j]);
}
printf("\n");
}
}
将行列坐标打印出来便于玩家选择排查的坐标,也将棋盘打印出来。
6.findMine函数(排查函数)
我们需要选择一个坐标进行排查,排查后显示该坐标周围有几个雷,以及判断玩家是否赢得游戏的条件。
void findMine(char a[ROWS][COLS], char b[ROWS][COLS], int c, int d)//排查雷
{
int x, y;
int win = 0;
while (win<c*d-minecount)
{
printf("请输入要排查的坐标:");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= c && y >= 1 && y <= d)//判断坐标是否有效
{
if (a[x][y] == '1')
{
printf("很遗憾,你被炸死,游戏结束。\n");
Boardprint(a, ROW, COL);
break;
}
else
{
int count=getMinecount(a, x, y);
b[x][y] = count + '0';
Boardprint(b, ROW, COL);
win++;
}
}
else
{
printf("输入错误,请重新输入:");
}
}
if (win == c * d - minecount)
{
printf("恭喜你,排雷成功\n");
Boardprint(a, ROW, COL);
}
}
,先输入一个排查的坐标,判断坐标是否合法,然后显示周围雷的个数,当踩到雷时,游戏结束,将所有不是雷的坐标找出,游戏也胜利。
7.getMinecount函数(排查周围雷的个数函数)
int getMinecount(char a[ROWS][COLS], int b, int c)//排查周围雷的个数
{
int count = a[b - 1][c] +
a[b - 1][c - 1] +
a[b][c - 1] +
a[b + 1][c - 1] +
a[b + 1][c] +
a[b + 1][c + 1] +
a[b][c + 1] +
a[b - 1][c + 1] - 8 * '0';
return count;
}
因为棋盘是由字符构成的,对周围八个格子累加再减去8ב0’即可得知有几个雷。
三、扫雷游戏完整代码:
test.c文件:
#include"game.h"
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入一个数字来选择:");
scanf_s("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束!\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
game.c文件:
#include"game.h"
void menu()
{
printf("**********\n");
printf("**1.play**\n");
printf("**0.exit**\n");
printf("**********\n");
}//展示菜单
void game()
{
char mine[ROWS][COLS] = { 0 };//存放雷的数组
char show[ROWS][COLS] = { 0 };//展示给玩家看的数组,排查出雷的信息
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
setMine(mine, ROW, COL);
//Boardprint(mine, ROW, COL);
Boardprint(show, ROW, COL);
findMine(mine, show, ROW, COL);
}
void initBoard(char a[ROWS][COLS], int b, int c, char d)//初始化数组(棋盘)
{
int i, j;
for (i = 0; i < b; i++)
{
for (j = 0; j < c; j++)
{
a[i][j] = d;
}
}
}
void Boardprint(char a[ROWS][COLS], int b, int c)//打印棋盘
{
int i, j;
for (i = 0; i <= c; i++)
{
printf("%d ", i);//打印列坐标
}
printf("\n");
for (i = 1; i <= b; i++)
{
printf("%d ", i);//打印行坐标
for (j = 1; j <= c; j++)
{
printf("%c ", a[i][j]);
}
printf("\n");
}
}
void setMine(char a[ROWS][COLS], int b, int c)//布置雷
{
int count = minecount;
while (count)
{
int x = rand() % b + 1;//随机生成雷的行坐标
int y = rand() % c + 1;//随机生成雷的列坐标
if (a[x][y] == '0')//只有不是雷时才能设置雷
{
a[x][y] = '1';
count--;
}
}
}
int getMinecount(char a[ROWS][COLS], int b, int c)//排查周围雷的个数
{
int count = a[b - 1][c] +
a[b - 1][c - 1] +
a[b][c - 1] +
a[b + 1][c - 1] +
a[b + 1][c] +
a[b + 1][c + 1] +
a[b][c + 1] +
a[b - 1][c + 1] - 8 * '0';
return count;
}
void findMine(char a[ROWS][COLS], char b[ROWS][COLS], int c, int d)//排查雷
{
int x, y;
int win = 0;
while (win<c*d-minecount)
{
printf("请输入要排查的坐标:");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= c && y >= 1 && y <= d)//判断坐标是否有效
{
if (a[x][y] == '1')
{
printf("很遗憾,你被炸死,游戏结束。\n");
Boardprint(a, ROW, COL);
break;
}
else
{
int count=getMinecount(a, x, y);
b[x][y] = count + '0';
Boardprint(b, ROW, COL);
win++;
}
}
else
{
printf("输入错误,请重新输入:");
}
}
if (win == c * d - minecount)
{
printf("恭喜你,排雷成功\n");
Boardprint(a, ROW, COL);
}
}
game.h文件:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define minecount 10
void initBoard(char a[ROWS][COLS], int b, int c, char d);//初始化数组(棋盘)
void Boardprint(char a[ROWS][COLS], int b, int c);//打印棋盘
void setMine(char a[ROWS][COLS], int b, int c);//设置雷
void findMine(char a[ROWS][COLS],char b[ROWS][COLS], int c, int d);//排查雷
int getMinecount(char a[ROWS][COLS], int b, int c);//查找周围有几个雷
四、游戏功能测试:
为了方便测试,我们先将雷的分布图打印出来。
可见,坐标2 6周围有两个雷,所以在棋盘上显示2,而2 7是雷,排查2 7后踩到雷游戏结束。
由于判断胜利的条件需要将剩余的不是雷的71个坐标全部找出,不方便证明,于是我将雷改为80个,将剩余1个不是雷的坐标找出来证明。
可见坐标6 7不是雷,将坐标6 7排查后,游戏成功。这就是排雷游戏的基本实现过程。