一、game.c代码
1、面板初始化
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void Ib(char b[ROWS][COLS], int rows, int cols,char set);
void Ib(char b[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
b[i][j] = set;//分为两种,空心面板传入‘0’,实心面板传入‘*’
}
}
}
那么就该这样调用函数时:
Ib(b, ROWS, COLS,'0');//初始化空心面板
Ib(s, ROWS, COLS,'*');//初始化实心面板
2、布置雷代码
#define EASY 10
void Com(char b[ROWS][COLS], int row, int col)
{
int count = EASY;
while (count)
{
int x = rand() % row + 1; //0(+1)---8(+1)
int y = rand() % col + 1;//设置随机产生的雷,布置在二维数组的1-9的范围内
if (b[x][y] == '0')
{
b[x][y] = '1';
count--;//当布置10个雷之后,跳出循环
}
}
}
3、展示面板代码
void Db(char b[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("***********扫雷游戏**********\n");
for (j = 0; j <= col; j++)//列号
printf(" %d ", j);
printf("\n");
for (i = 1; i <= row; i++)
{
printf(" %d ", i);//行号
for (j = 1; j <= col; j++)
printf(" %c ", b[i][j]);
printf("\n");
}
}
4、计算雷的个数代码
int get_count(char b[ROWS][COLS], int x, int y)
{
return (b[x - 1][y] +
b[x - 1][y - 1] +
b[x - 1][y + 1] +
b[x][y - 1] +
b[x][y + 1] +
b[x + 1][y - 1] +
b[x + 1][y] +
b[x + 1][y + 1] - 8 * '0'); //将排查点一圈其他八个点的值相加
}
5、递归扩散空白格代码
void spread(char b[ROWS][COLS], char s[ROWS][COLS], int x, int y)
{
int count = get_count(b, x, y);//统计排查点周围有几个雷
if (count == 0)//排查的点周围无雷
{
s[x][y] = ' '; //若周围无雷将'*'改为' '
int i = 0;
int j = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
//将扩散的范围控制在1-9的范围,在该范围内,以排查的点(周围无雷)为中心向外扩散
if ((x + i > 0) && (y + j > 0) && (x + i < ROWS) && (y + j < COLS) && s[x + i][y + j] == '*')
spread(b, s, x + i, y + j);//递归此函数,一圈一圈排查
}
}
else //直到扩散到周围有雷的点停止,并将停止的点周围有几颗雷显示出来
s[x][y] = count + '0';//将字符转换为数字显示周围几颗雷
}
6.排查雷和标记雷的代码
void Search(char b[ROWS][COLS], char s[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;//排查或标记的坐标
int flag = EASY;//统计标记的变量,一共只有10次标记机会
int ret = 0;//用于判断是否成功标记到雷的变量,与10比较
int input = 0;//选择模式
//int error = 0;//标记错误点的个数,若ret不为10,则error = 10-ret
again:
printf("请输入要选择的模式(tip:1.排查模式;2.标记模式 特殊坐标:20,20(输入可重新选择模式)):>");
scanf_s("%d",&input);
switch (input)
{
case 1:
while (1)
{
printf("请输入要排查的坐标:>");
scanf_s("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (s[x][y] != '*')
{
printf("该坐标被排查过了,不能重复排查\n");
}
if (b[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Db(b, ROW, COL);
break;
}
else//如果不是雷,统计周围有几个雷,周围八个坐标
{
spread(b,s, x, y);
Db(s, ROW, COL);
}
}
else if (x == 20 && y == 20)
{
goto again;//跳转到选择模式那一步
}
else
{
printf("输入坐标非法,重新输入");
}
}
break;
case 2:
while (1)
{
printf("请输入要标记的坐标:>");
scanf_s("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col && s[x][y] == '*')
{
ret += get_value(b, x, y);
s[x][y] = '?';//标记后显示符号?
flag--;//标记次数-1
Db(s, ROW, COL);
//printf("%d\n", ret);
if(flag > 0)//只有在未完全标记成功显示,若flag = 0,则表示标记成功,不需在提示该语句
{
printf("标记次数剩余:%d\n", flag);
}
}
else if (x >= 1 && x <= row && y >= 1 && y <= col && s[x][y] == '?')//当标记错误后,可取消标记,并返回标记的次数
{
s[x][y] = '*';
if(b[x][y] == '1')
{
ret = ret - 1;
}
flag += 1;
Db(s, ROW, COL);
//printf("%d\n", ret);
printf("标记次数剩余:%d\n", flag);
}
else if (x >= 1 && x <= row && y >= 1 && y <= col && s[x][y] != '?' && s[x][y] != '*')
{
printf("该坐标不可被标记,请重新输入标记坐标\n");//标记在' '或者数字上,显然是错误的
}
if (flag == 0)//标记十次后进行判断
{
if (ret == 10)
{
printf("恭喜你排雷全部正确,游戏胜利!\n");
break;
}
else
{
printf("所标记的点不全为雷,请重新检查\n");
}
}
if (x == 20 && y == 20)
{
goto again;
}
}
break;
default:
printf("输入有误,重新输入\n");
break;
}
}
其中还有一个小方法:
int get_value(char b[ROWS][COLS], int x, int y)
//为统计标记过的点是否为雷,若标记十个点后,进行判断,为10则成功,否则有错误
{
if (b[x][y] == '1')
return 1; //标记对雷则+1
else
return 0;
}
二、game.h代码
#ifndef __GAME_H__
#define __GAME_H__
//将每个文件所用到的头文件都放入该头文件中,其他文件引入game.h头文件即可
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//不同难度雷的数量
#define EASY 10
#define MID 20
#define EXPERT 30
#define MASTER 50
void Ib(char b[ROWS][COLS], int rows, int cols,char set); //初始化面板函数原型
void Db(char b[ROWS][COLS], int row, int col); //展示面板函数原型
void Com(char b[ROWS][COLS], int row, int col); //布置雷函数原型
void Search(char b[ROWS][COLS], char s[ROWS][COLS], int row, int col); //排查、标记雷函数原型
#endif
三、主函数main代码
#include "game.h"
void menu()
{
printf("***********************************\n");
printf("************ 1.play ***********\n");
printf("************ 0.quit ***********\n");
printf("***********************************\n");
}
void game()
{
char b[ROWS][COLS] = {0}; //存放布置好的雷的信息
char s[ROWS][COLS] = {0};//存放排查出的雷的信息
Ib(b, ROWS, COLS,'0');//初始化布置
Ib(s, ROWS, COLS,'*');//初始化排查
//设置雷
Com(b, ROW, COL);//随机分配10个雷
Db(s, ROW, COL);//展示排雷页面
//Db(b, ROW, COL);//展示布雷页面 用户不可以看到这个页面
//排查雷
Search(b,s,ROW,COL);//进行排查和标记动作方法
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//以时间戳做随机数的来源
do
{
printf("扫雷游戏\n");
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;
}