扫雷游戏也是我们常见的小游戏,今天我们来简单实现一下这个小游戏(简陋版).
首先我们创建一个菜单,供玩家选择,菜单跟上一期的三子棋的菜单一样,这里就不多说了;
void menu()
{
printf("*************************************************\n");
printf("************** 1.进入游戏 *****************\n");
printf("************** 0.退出游戏 *****************\n");
printf("*************************************************\n");
printf("*************************************************\n");
}
这里是主函数部分,实现玩家选择哪个菜单的代码:
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏\n");
break;
default:
break;
}
} while (input);
return 0;
}
是实现整个游戏的主体部分,在这里我们一步一步看;
首先创建两个数组mine和show,mine数组是布置雷的信息,show数组是展示给玩家看的扫雷界面;其中ROW=COL=9,ROWS=COLS=ROW+2= COL+2=11,这里创建11×11的数组是为了后面统计雷的个数,但实际玩家操作的是9×9的数组;
InitBoard()函数将两个数组都初始化为对应的字符;
DisplayBoard()函数是打印相应数组的扫雷界面的函数;
SetMine()函数是布置雷的函数;
FindMine()函数是实现排雷的函数;
void game()
{
//雷的信息存储
//1.布置雷的信息
char mine[ROWS][COLS] = { 0 };
//2.排查出雷的信息
char show[ROWS][COLS] = { 0 };
//初始化
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//打印扫雷界面
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine,ROW,COL);
//DisplayBoard(mine, ROW, COL);
//扫雷
FindMine(mine,show,ROW,COL);
}
这里InitBoard()函数是将两个数组初始化成相应的字符,mine数组初始化成’ 0 ',0代表不是雷;show数组初始化成’ * ‘;这里设置一个char set来接收字符,然后数组需要哪个字符就可以用一次循环完成初始化;
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
DisplayBoard()函数是打印当前扫雷界面的函数,在显示给玩家参考的show数组中,我们用’ * ‘给玩家参考;此外,为了让玩家的游戏效率高一些,我们在扫雷游戏的界面打印了列号和行号,方便玩家参考;这里要注意打印字符的循环,下标要从1开始,不能从0开始,我一开始就是从0开始,结果在打印布置完雷的函数的时候,假如布置10个雷,有时候就不够10个雷,结果调试半天才找出这个bug;
void DisplayBoard(char board[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 ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
SetMine()函数是布置雷的函数,我们传入mine数组,行数为row,列数为col,我们需要布置雷的范围是1-9行和1-9列,所以传入的行数和列数分别是row和col;这里调用rand()函数生成随机数,而rand() % row是随机生成0-8的数,所以加1是生成1-9的数,刚好满足行数和列数的要求;我们布置雷的过程是,当这个随机生成的坐标位置是’ 0 ‘,就把当前位置改为’ 1 ',即为雷;否则继续循环生成随机数,当count减到0时循环结束,布置雷成功;
void SetMine(char board[ROWS][COLS], int row, int col)
{
//定义EASY_COUNT为10
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1; //1-9
int y = rand() % col + 1; //1-9
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
(1)FindMine()函数是实现排雷的函数,在这里需要传进来两个数组mine和show,需要对两个数组进行操作;
首先进来先判断坐标合理性,合理则判断是否踩雷,即玩家输入的坐标位置是否是字符 ’ 1 ',若是则提示玩家,退出到游戏菜单;否则提示玩家坐标不合法,重新输入;如果没有踩雷,则提示玩家输入的当前坐标周围的8个坐标雷的个数,这里调用get_mine_count()函数进行统计(下面介绍);当玩家排完雷即提示玩家排雷成功.
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col- EASY_COUNT)
{
printf("请输入排查雷的坐标:\n");
scanf_s("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//坐标合法
//1.踩雷
if (mine[x][y] == '1')
{
printf("很遗憾,您踩雷了\n");
DisplayBoard(mine, row, col);
break;
}
//2.没踩雷
else
{
//计算x,y周围有多少雷
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';//count是数字,相当于把数字转成字符
DisplayBoard(show, row, col);
win++;
}
}
else
printf("输入坐标非法,请重新输入!\n");
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜您,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
(2) get_mine_count()函数
这里将玩家输入坐标的周围8个坐标的雷统计出来,返回这个值;注意棋盘中放的雷和非雷,即1和0都是字符,所以将字符转成数字需要减去字符’ 0 ',计算这8个坐标的和的时候就要减去8 * ’ 0 ';
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y - 1] - 8 * '0';//字符0不是数字0,原数组存放的都是字符,相当于把字符转成数字
}