目录
1.分析与思路
2.头文件说明
3.主函数
4.分支函数的各个功能
5.全部代码
1. 分析与思路:
通过Windows的小游戏扫雷
通过玩这个小游戏,我们不难发现这是一个由二维数组组成的棋盘和一些功能函数组成,所以我们就要先从棋盘做起,再写多个功能函数,
那么第一步就是棋盘的构造,通过观察可得到是两个二维数组,第一个二维数组是棋盘第一层空白格,第二个二维数组就是第二层的雷与安全格 ,第二步就是各种功能函数,优先到后的顺序便是布置雷,输入坐标查找雷,以及不是雷的格子周围雷的数量(为了接近原型,这里在展开空白格这里加一个递归函数),为了方便后续的观看,分多文件的形式来编写代码
2.头文件说明:
#include<stdio.h>
//这个是c语言中输入输出函数的头文件
#include<stdlib.h>
//这个头文件是生成随机数中的rand的头文件,以及srand随机生成的种子的头文件
//srand生成的种子并不是真正意义上的随机,所以要用time(NULL)来做到随机
#include<time.h>
//调用函数time()生成时间戳,来实现srand生成种子的随机
#include<Windows.h>
//调用system()函数,来实现清屏
#define ROW 9 //定义棋盘宽9行
#define COL 9 //定义棋盘长9列
#define ROWS ROW+2 //定义二维数组的行
#define COLS COL+2 //定义二维数组的列
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set);
//在头文件中,声明创建的棋盘函数
void Display(char arr[ROWS][COLS],int row,int col);
//在头文件中,声明显示棋盘的函数
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
//在头文件中,声明查找地雷的函数
void SetMine(char arr[ROWS][COLS], int row, int col);
//在头文件中,声明布置地雷的函数
int Xianshi(char mine[ROWS][COLS], int x, int y);
//在头文件中,声明判断空白格周围雷的个数函数
void DiGui(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
//在头文件中,声明展开空白格的函数
这是创建game.h文件中的头文件,以及每一个头文件对应的意义与作用,当然想实现更多作用,可以调用更多的函数,后面又定义的全局变量数组的行列长度,后面主函数所用到的功能函数在头文件中声明了一次,以便后面调用的时候不用再声明。
3.主函数
这个扫雷的主函数还是比较简单的,通俗易懂的,先看代码
#include"mine.h"
void menu() //设置了一个最开始的菜单函数
{
printf("********************\n");
printf("****** 1. play *****\n");
printf("****** 2. exit *****\n");
printf("********************\n");
} //打印所需要的开局选项和菜单
void game() //扫雷最重要的游戏函数,同时包含了这个游戏的功能函数
{
char mine[ROWS][ROWS]; //定义了第一个二维数组,是后台放雷的棋盘
char show[COLS][COLS]; //定义第二个二维数组,是展示页面空白格
InitBoard(mine, ROWS, COLS, '0');//初始化雷盘
InitBoard(show, ROWS, COLS, '*');//初始化展示棋盘
Display(show, ROW, COL);//显示棋盘
SetMine(mine, ROW, COL);//布雷
FindMine(mine, show, ROW, COL);//查找雷
}
int main()
{
srand((unsigned int)time(NULL));
//为布置雷生成随机位置,调用了time()函数利用空指针来实现srand生成随机雷的位置
int a = 0;
do
{
menu(); //调用菜单函数
printf("输入你的选择:");
scanf("%d", &a); //输入选择的选项
switch (a) //通过输入的选项来判断后续运行
{
case 1:
game(); //调用游戏函数,正式进入游戏
break;
case 2:
printf("退出游戏");
break;
default:
printf("输入错误重新开始\n");
break;
}
} while (a != 2);//不是选择退出则一直循环
return 0;
}
这是扫雷的主函数,各种功能函数已经被调用了,那么接下来就是各个功能性函数的介绍
这是打印的菜单:
4.功能性函数:
1.创建棋盘,比较简单的循环嵌套来完成二维数组的创建
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set)
{
int i;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
//两个for循环定义棋盘,多在函数设一个参数set,可以方便后面改棋盘上字符
}
}
}
2.打印棋盘,并在棋盘的行列上标上对印的序号,代码还是比较通俗易懂
void Display(char arr[ROWS][COLS], int row, int col)
{
int i;
printf("*********扫雷*********\n");
for (i = 0; i <= row; i++)
{
printf("%d ", i); //在棋盘的行标上序号,方便输入坐标
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i); //在棋盘的列标上序号,方便输入坐标
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]); //打印二维数组的棋盘
}
printf("\n");
}
}
这是代码运行出来打印的棋盘显示
3.布置雷的函数,要用到rand,并且主函数调用time()来实现真正的随机
void SetMine(char arr[ROWS][COLS], int row, int col)//布置雷的函数
{
int m = 10; //定义m为雷,并初始化为十个
while (m) //当十个雷都布置完,结束循环
{
int x = rand() % row + 1;//通过rand生成随机数,来确定雷的横坐标
int y = rand() % col + 1;//通过rand生成随机数,来确定雷的横坐标
if (arr[x][y] == '0')
{
arr[x][y] = '1'; //判断这个位置是否布置过雷
m--; //成功布置一个m自减减
}
}
}
4.输入坐标查找雷的函数:
利用了函数的嵌套,在查找雷的函数中重新调用了Xianshi()和Digui函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int num = 71;
while (num!=0) //排除雷后的71个空格被排查完结束循环
{
printf("请输入要排雷的坐标");
scanf("%d %d", &x, &y); //输入坐标
if (x >= 1 && x <= row && y >= 1 && y <= col)//如果输入的坐标在棋盘中
{
if (mine[x][y] == '1') //如果输入的坐标为‘1’ 即是雷
{
printf("很抱歉你被炸死了\n");
Display(mine, ROW, COL); //显示雷的棋盘,也就是答案
break;
}
else //所查找的坐标不是雷的话
{
int n;
n = Xianshi(mine, x, y); //调用一个计算周围有多少雷的函数
show[x][y] = n + '0'; //所查找坐标周围有几个雷就显示数字几
if (n== 0)
{
DiGui(mine, show, x, y, ROW, COL); //调用这个递归函数,来实现展开多空白
}
show[x][y] = n + '0';
Display(show, ROW, COL);//显示棋盘
num--;
}
}
else
printf("输入错误,重新输入:");
}
if (num == 0) //如果把所有的空格都排查完则胜利
{
printf("恭喜你获胜\n");
Display(mine, ROW, COL);
}
}
5.完成一个计算所排查周围有多少雷的函数,并显示在该坐标
int Xianshi(char mine[ROWS][COLS],int x,int y)
{
int count;
return count = mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y]+ mine[x][y + 1] + mine[x - 1][y + 1] + mine[x + 1][y + 1] + 8 * '0';
//定义了一个整型count,把周围八个坐标里的数加起来,因为坐标里边是字符,减0的ASSIC码便变成了整型
}
5.完成一个递归函数,来实现展开大部分空白为零区域
void DiGui(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int row,int col)
{
int count=Xianshi(mine,x,y);
show[x][y]=count+'0'; //调用Xianshi()函数,判断所排查的坐标是否为零
if (count!=0) //不为零则跳出该函数
{
return;
}
int i;
int xx[]={1,1,1,-1,-1,-1,0,0};
int yy[]={1,0,-1,0,1,-1,1,-1};//周围的八个格子的横纵坐标
for(i=0;i<8;i++)//循环八次来判断是否周围有非零的数
{
int dx =x + xx[i];
int dy = y+ yy[i];
if(dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy] == '0' && show[dx][dy]=='*')
{
DiGui(mine,show,dx,dy,ROW,COL);//如果满足为零则再次返回Digui函数,进行递归
}
}
}
5.全部代码
mine.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set);
void Display(char arr[ROWS][COLS],int row,int col);
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
void SetMine(char arr[ROWS][COLS], int row, int col);
int Xianshi(char mine[ROWS][COLS], int x, int y);
void DiGui(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
main.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"mine.h"
void menu()
{
printf("********************\n");
printf("****** 1. play *****\n");
printf("****** 2. exit *****\n");
printf("********************\n");
}
void game()
{
char mine[ROWS][ROWS];
char show[COLS][COLS];
InitBoard(mine, ROWS, COLS, '0');//初始化棋盘
InitBoard(show, ROWS, COLS, '*');
Display(show, ROW, COL);//显示棋盘
SetMine(mine, ROW, COL);//布雷
FindMine(mine, show, ROW, COL);//查找雷
}
int main()
{
srand((unsigned int)time(NULL));
int a = 0;
do
{
menu();
printf("输入你的选择:");
scanf("%d", &a);
switch (a)
{
case 1:
game();
break;
case 2:
printf("退出游戏");
break;
default:
printf("输入错误重新开始\n");
break;
}
} while (a != 2);
return 0;
}
game.c函数
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols,char set)
{
int i;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
void Display(char arr[ROWS][COLS], int row, int col)
{
int i;
printf("*********扫雷*********\n");
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void SetMine(char arr[ROWS][COLS], int row, int col)
{
int m = 10;
while (m)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
m--;
}
}
}
int Xianshi(char mine[ROWS][COLS],int x,int y)
{
int count;
return count = mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y]
+ mine[x][y + 1] + mine[x - 1][y + 1] + mine[x + 1][y + 1] + 8 * '0';
}
void DiGui(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int row,int col)
{
int count=Xianshi(mine,x,y);
show[x][y]=count+'0';
if (count!=0)
{
return;
}
int i;
int xx[]={1,1,1,-1,-1,-1,0,0};
int yy[]={1,0,-1,0,1,-1,1,-1};
for(i=0;i<8;i++)
{
int dx =x + xx[i];
int dy = y+ yy[i];
if(dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy] == '0' && show[dx][dy]=='*')
{
DiGui(mine,show,dx,dy,ROW,COL);
}
}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int num = 71;
while (num!=0)
{
printf("请输入要排雷的坐标");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很抱歉你被炸死了\n");
Display(mine, ROW, COL);
break;
}
else
{
int n;
n = Xianshi(mine, x, y);
show[x][y] = n + '0';
if (n== 0)
{
DiGui(mine, show, x, y, ROW, COL);
}
show[x][y] = n + '0';
Display(show, ROW, COL);//显示棋盘
num--;
}
}
else
printf("输入错误,重新输入:");
}
if (num == 0)
{
printf("恭喜你获胜\n");
Display(mine, ROW, COL);
}
}
6.输出结果:结果比较繁琐,所以只截取了一部分结果,感兴趣的小i伙伴可以下去玩一下
:
感谢小伙伴们的浏览,喜欢的可以点赞三连哦!!!