博主学的还不到家,如有问题,请大家指出,博主会多多学习。
首先要创建两个数组,数组的大小最好是比展示出来的数组要大两格,展示出来的数组是比实际的要小两格,这样就可以防止我们判断排查雷的时候不用去做,数组访问是否越界判断,第一个数组用来存放雷的信息,第二个用来打印出来显示给用户看的,通过用户输入的坐标,来判断,如果是雷则游戏失败,如果不是雷,则显示这个坐标周边的雷的数量信息,并展开他周边八个格子,如果不是雷则展开,是雷则不展开,并且雷的上一格和下一格也不展开,保持游戏难度。
首先是test.c的主函数代码内容
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("******************************
");
printf("********* 1.游戏开始 *********
");
printf("********* 0.退出游戏 *********
");
printf("******************************
");
}
void game()
{
char show[ROWS][COLS]={0};//存放展示出来的数据
char mine[ROWS][COLS]={0};//存放雷放置的信息
InitBoard(show, ROWS, COLS, '*');//定义一个初始化函数 把需要初始化的数组地址传过去,还有行和列,和要初始化的内容
InitBoard(mine, ROWS, COLS, '0');//定义一个初始化函数 把需要初始化的数组地址传过去,还有行和列,和要初始化的内容
//布置雷
SetMine(mine, ROW, COL);
//定义一个打印函数
DisPlayBoard(show, ROW, COL);
//DisPlayBoard(mine, ROW, COL);//测试用的,用来显示雷的信息
FineMine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));//这个是随机生成雷的时间传递,时间是变动的,所以传递时间永远都是随机的
int input = 0;
do
{
menu();//菜单页面函数
printf("请选择:");
scanf("%d", &input);
switch (input)//通过switch的逻辑判断 是否继续游戏,或退出游戏
{
case 1:
game();
break;
case 0:
printf("退出成功");
break;
default :
printf("输入错误 请重新输入:");
break;
}
} while (input);
return 0;
}
这是game.h头文件的函数定义
#pragma once
#include <stdio.h>
#include <time.h>
#define ROW 9 //预设一个游戏页面大小 方便修改
#define COL 9//预设一个游戏页面大小 方便修改
#define ROWS ROW+2 //预设一个游戏页面大小 方便修改
#define COLS COL+2 //预设一个游戏页面大小 方便修改
#define EASE_COUNT 10// 这个是雷的分布数量
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化函数的定义
void DisPlayBoard(char board[ROWS][COLS], int row, int col);//打印数组显示
void SetMine(char mine[ROWS][COLS], int row, int col);//布置雷的函数
void FineMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row,int col);//排查雷的函数
这是game.c函数的实现代码 下面一个一个来说明
首先定义一个数组接收,我们之前也说过,实际的数组大小要比展示出来的大两格,所以我们接收要接收全部,不能单独一部份接收,通过 两个for的嵌套,遍历整个数组,初始为想要的字符。
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
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;
}
}
}
这是打印数组的代码实现,也是通过for的嵌套,不过这里我们只需要打印出来展示给用户看的页面,所以对数组的打印是从1开始,到9结束
void DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("****** 扫雷游戏 ******
");
for (j = 0; j <= col; j++)//打印数组内容之前先打印坐标
{
printf("%d ", j);
}
printf("
");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印数组内容之前先打印坐标
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("
");
}
}
这是布置雷的代码实现,主要是通过rand来实现,创建一个计数的,达到要布置雷的数量时停止循环,
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = EASE_COUNT;//雷的数量
while (count)//每布置一个雷count--,直到布置完 结束循环
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')//随机生成的坐标要判断一下,是否布置过雷了
{
mine[x][y] = '1';
count--;
}
}
}
最麻烦的来了,就是排查雷的代码实现,首先对用户输入的坐标进行判断,是否合法,合法后再判断是否排查过,合法并未排查过的话,我们才执行对该坐标是否雷的判断,是雷则游戏结束,不是雷就显示该坐标周边八个格子的雷信息,之前我们把mine数组初始化成字符‘0’了,布置雷的信息初始化为字符‘1’,通过对坐标的周边八个格子相加,再减掉8乘以字符‘0’的ascll码值,这里8乘以字符'0'是计算ascll码,最后再把得到的数值加上一个字符‘0’就是一个数字字符了。
int get_count(char board[ROWS][COLS], int x, int y)//获取用户输入坐标的周边八个格子雷的数量
{
return board[x - 1][y - 1] + board[x - 1][y] +
board[x - 1][y + 1] + board[x][y - 1] +
board[x][y + 1] + board[x + 1][y - 1] +
board[x + 1][y] + board[x + 1][y + 1] - 8 * '0';
}
void Is_Nomine(char show[ROWS][COLS],char mine[ROWS][COLS], int x, int y)//这是对用户输入的坐标来判断,以达到提示周边雷的信息
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (mine[x + i][y + j] != '1')
{
if (show[x + i][y + j] == '*'&&mine[x + i][y-1]!='1' && mine[x + i][y]!='1')
{
//int count = get_count(mine, x, y);
show[x + i][j + y] = ' ';
}
}
}
}
}
void FineMine(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-EASE_COUNT)
{
printf("请输入要排查的坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//检测坐标的合法性
{
if (show[x][y] != '*')
{
printf("该坐标已被排查过,请重新输入:");
}
else
{
if (mine[x][y] == '1')//如果是雷
{
printf("很遗憾,游戏失败");
DisPlayBoard(mine, ROW, COL);
break;
}
else //如果不是雷
{
int count = get_count(mine, x, y);
show[x][y] = count + '0';//+'0'是为了把get_count返回的int型数据转换成数字字符
Is_Nomine(show,mine, x, y);
//Set_Forth(show, mine, x, y);
DisPlayBoard(show, ROW, COL);
}
}
}
else
{
printf("输入坐标非法,请重新输入");
}
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
{
if (show[i][j] != '*')
{
win++;
}
}
}
if (win == row * col - EASE_COUNT)
{
printf("恭喜你,扫雷成功
");
DisPlayBoard(mine, ROW, COL);
}
}
if (win == EASE_COUNT)
{
printf("恭喜你,扫雷成功");
DisPlayBoard(mine, ROW, COL);
}
}
游戏过程,首先打印一个菜单
选择1开始游戏,这是游戏的界面,
对于用递归来判断是否展开一片,博主暂时没有这个能力,只能通过对坐标周边八个格子判断,是否要展示出来