目录
一、实现思路
需要完成的游戏逻辑
①、引导用户选择是否开始游戏;
②、设置棋盘(二维数组);
③、初始化棋盘(二维数组),并展示;
④、在棋盘(二维数组)中埋入地雷;
⑤、引导用户输入坐标;
⑥、以用户所选坐标为中心,统计九宫格内地雷的数量,并于该坐标上显示,若选择的坐标上刚好有地雷,则显示 "game over" ,用户重新跳回游戏界面
二、实现代码
1、头文件中常量以及自定义函数的声明
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROWS ROW+2 //用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define COLS COL+2 //用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define ROW 9 //用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define COL 9 //用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define easy_count 10 //用define定义便于整个代码的复编译
//为使test.c中能够正常调用所有的自定义函数,需要在头文件中,对所有自定义函数进行声明,
//注:头文件的声名格式应当与函数定义格式相同?
void init_board(char board[ROWS][COLS], int rows, int cols, char set); //原则上,init_board 只需一个数组作为函数变量,用一个变量来接收mine 和 show,在test.c中调用两次即可
void display_board(char show[ROWS][COLS], int row, int col); //原则上,display_board 只需一个数组作为函数变量,即,只需要展示 show 即可,游戏中展示 mine 属于作弊行为
void set_mine(char mine[ROWS][COLS], int row, int col); //原则上,set_mine 只需一个数组作为函数变量,因为只有在mine中埋入地雷
void find_mine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col); //find_mine 之所以需要两个形参数组作为函数,一是需要知道所选择坐标的周围范围内存在多少个地雷,其次还要将统计的个数
// 由此可推:数字 + 数字字符'0' = 数字字符
2、main函数
主函数:
#inculde "game.h"
int main()
{
test();//跳转至自定义函数test
return 0;
}
为了引导用户进入游戏,编写自定义函数test:
void test()
{
int input = 0; //使用do while 循环来实现程序
do {
printf("请选择是否开始游戏\n");
menu();
scanf("%d", &input);
switch (input)
{
case 0:
{
printf("退出游戏\n");
break;
}
case 1:
{
printf("开始游戏\n");
game(); //跳转至自定义函数game
break;
}
default:
{
printf("输入有误,重新输入\n");
break;
}
}
} while (input);
}
3、game函数
void game()
{
char mine [ROWS][COLS] = {0}; //为便于实现,需要定义两个数组,其中一个用于布置地雷
char show [ROWS][COLS] = {0}; //还有一个用于显示
//之所以选用11*11二维数组是因为,在初始化棋盘后,mine数组中内所有元素均为字符'0'
//这样在后续统计地雷数时,可以避免用户选择边缘位置时而出现错误,同时也便于代码的实现
//初始化游戏,同时展示show棋盘
init_board(mine, ROWS, COLS, '0'); //mine中全部设为字符'0'
init_board(show, ROWS, COLS, '*'); //show中全部设为字符'*
//向玩家展示内部9*9的大小的棋盘
display_board(show, ROW, COL);
//在mine中设置地雷,其中字符'1'表示地雷,字符'0',表示非雷,同样的,因为玩家只需要在9*9的区域
//内排雷,所以雷只要设置在9*9范围内
set_mine(mine, ROW, COL);
//发现雷,选定坐标,以该坐标为中心,统计周围八个格子中雷的个数,因为数组设置的是11*11大小,
//且所有单元格都初始化为字符0,所以不会存在溢出和多算的情况。每次发现完后
find_mine(mine,show, ROW, COL);
}
4、初始化函数
void init_board(char board[ROWS][COLS], int rows, int cols, char set)//ROWS和COLS是 define定义过的,所以形参中不能再次使用ROWS,COLS
{
int i = 0;
for (i = 0; i < rows; i++)
{
//int j = 0;
for (int j = 0; j < cols; j++)
{
board[i][j] = set; //在自定义函数 game 中,该自定义函数被调用了两次,将mine和show分别进行初始化
}
}
}
5、棋盘展示函数
//棋盘展示
//扫雷游戏在编写过程中,只需要将中间9*9的部分展示给玩家,所以行列分别为 ROW 和 COL 而不是 ROWS和COLS
//同时使用形参 row 和 col 来接收 实参 ROW 和 COL
void display_board(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i); //便于用户确定横坐标
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i); //便于用户确定纵坐标
for (j = 1; j <= col; j++)
{
printf("%c ", show[i][j]); //展示棋盘
}
printf("\n");
}
}
代码实现的结果:
6、布置地雷函数
//在初始化完毕,以及初次打印棋盘后,就要给棋盘中偷偷买入地雷,这一过程玩家是看不见的,但是是实际存在的
//我们所要做的就是在原11*11的数组中,在其中间9*9的部分随机埋入10个地雷,
void set_mine(char mine[ROWS][COLS], int row, int col)
{
int count = easy_count; //easy_count是define定义的变量,不能直接用于+-运算,
while (count>0) //循环埋入地雷,直至埋入10个为止
{
int x = rand() % row +1; //随机埋入
int y = rand() % col +1;
if (mine[x][y] != '1') //该条语句用于确保不会重复埋雷而浪费字数,
{ //开是所产生的随机数x y 以及对应的单元格 mine[x][y]肯定满足
mine[x][y] = '1'; //mine[x][y] != '1',因此if语句能够顺利执行,
count--; //同时确保后面不会重复埋雷
}
}
//display_board(mine, row, col); //作弊器
}
7、发现地雷函数
//找地雷,同时打印棋盘结果
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = row * col - easy_count;//胜利条件
while (win)
{
printf("请输入坐标\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//为确保游戏的正常进行,
{ //需要对输入的坐标是否有效进行判断
if (mine[x][y] == '1')//判断输入坐标是否为雷
{
printf("game over\n");
break;
}
else
{
int count = get_mine(mine, x, y);//不是则将自定义函数get_mine中的值返回到count中
show[x][y] = count + '0';//数字转字符 ,最终以数字字符输出到字符数组中
display_board(show, row, col);//展示棋盘
win--;
}
}
else
{
printf("输入有误,请重新输入\n");
}
}
if (!win)
{
printf("you win\n");
}
}
自定义函数get_mine的实现方式
注:该自定义函数在find_mine 函数前,如果在find_mine 函数后面,则在使用时,需要在find_mine函数前定义该函数
//该函数用于确定以某单元格为中心,周围八个位置有多少个雷
int get_mine(char mine[ROWS][COLS], int x, int y)
{
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
count += mine[x+i][y+j] - '0';//字符转数字
}
}
return count;
}
8、代码的实现效果
注:为便于验证,此处将头文件中 game.h 内的常量 ROW COL 设置为2,easy_count 设置为1
胜利:
失败:
退出游戏:
三、后续改进
1、若中心坐标周围没有雷,递归展开。//这需要用到递归函数,暂时为学
2、能否像游戏一样,标记某个坐标为雷?