目录
一、全代码
game.h头文件
game.c函数定义
test.c主调函数
二、详细解剖代码段
1.主函数
2.初始化棋盘
3.打印棋盘
4.放置雷
5.排查雷
6.统计周围雷的数量
7.展开周围
8.判断是否已经赢了
三、测试
结束语
一、全代码 game.h头文件
#include
#include
#include
#define ROW 9
#define COL 9
#define ROWS ROW+2 //外围再围上一圈用于之后方便判断雷的数量
#define COLS COL+2
#define EASY_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 board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);
//进阶排雷
void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
game.c函数定义
#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;
}
}
}
//打印棋盘
void DisplayBoard(char board[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 ",board[i][j]);
}
printf("\n");
}
printf("--------扫雷---------\n");
}
//放雷
void Setmine(char board[ROWS][COLS], int row, int col) {
int count = EASY_COUNT;
while (count)
{
int i =rand() % row + 1;
int j =rand() % col + 1;
if (board[i][j] == '0')
{
board[i][j] = '1';
count--;
}
}
}
//统计周围雷的数量
int get_mine_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 Remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//附近都无雷,把棋盘扩展开来知道遇到雷
{
int i = 0;
int j = 0;
show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
if (show[x][y] == '0')
{
show[x][y] = ' ';//如果周围雷的个数为0,则设置此坐标为“空格”
//判断此坐标周围坐标是否还有可设为空格的坐标
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (show[x + i][y + j] == '*')
Remove_NoMine(mine, show, x + i, y + j);//递归
}
}
}
}
//判断是否已经赢了
int Is_win(char show[ROWS][COLS], int row, int col)
{
int win = 0;
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++) {
if (show[i][j] == '*')
win++;
}
}
if (win == EASY_COUNT)
return 1;
else
return 0;
}
//排查雷
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 = Is_win(show,row,col)) != 1)
{
printf("请输入坐标:>");
scanf("%d%d",&x,&y);
if (x>=1 && x<= row && y >= 1 && y <= col )
{
if (show[x][y] != '*')
{
printf("该坐标已被占用,请重新输入:>\n");
}
else
{
//是雷
if (mine[x][y] == '1')
{
printf("很遗憾,被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
//如果不是雷
else
{
//统计mine数组中,x,y周围有几个雷
Remove_NoMine(mine,show,x,y);
DisplayBoard(show, ROW, COL);
}
}
}
else
{
printf("非法坐标,请重新输入\n");
}
}if (win == 1)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
void remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//附近都无雷,把棋盘扩展开来知道遇到雷
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法
{
int i = 0;
int j = 0;
show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
if (show[x][y] == '0')
{
show[x][y] = ' ';//如果周围雷的个数为0,则设置此坐标为“空格”
//判断此坐标周围坐标是否还有可设为空格的坐标
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (show[x + i][y + j] == '*')
remove_NoMine(mine, show, x + i, y + j);//递归
}
}
}
}
}
test.c主调函数
#include "game.h"
//菜单
void menu() {
printf("************************\n");
printf("******** 1.play ********\n");
printf("******** 0.exit ********\n");
printf("************************\n");
}
void gamm() {
char mine[ROWS][COLS] = { 0 }; //存放布置好的雷的信息
char show[ROWS][COLS] = { 0 }; //存放排查好雷的信息
//初始化数组的内容为指定的内容
//规定 mine 数组在没有布置雷的时候,都是 '0'
InitBoard(mine,ROWS,COLS,'0');
//规定 show 数组在没有排查雷的时候,都是 '*'
InitBoard(show,ROWS,COLS,'*');
//设置雷
Setmine(mine,ROW,COL);
打印放雷的棋盘
DisplayBoard(mine,ROW,COL);
//打印玩家棋盘
DisplayBoard(show,ROW,COL);
//排雷
FindMine(mine,show,ROW,COL);
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d",&input);
switch (input)
{
case 1:
gamm();
break;
case 0 :
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择:>\n");
break;
}
} while (input);
return 0;
}
二、详细解剖代码段
1.主函数
int main() {
int input = 0;
srand((unsigned int)time(NULL)); //引入时间戳来为之后的随机放雷服务
do
{
menu(); //打印菜单
printf("请选择:>");
scanf("%d",&input);
switch (input)
{
case 1:
gamm();
break;
case 0 :
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择:>\n");
break;
}
} while (input); //当输入为 0 时游戏退出
return 0;
}
2.初始化棋盘
//初始化棋盘
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;
}
}
}
因此我们在使用的函数的时候把定义好的字符传送过来
//规定 mine 数组在没有布置雷的时候,都是 '0'
InitBoard(mine,ROWS,COLS,'0');
//规定 show 数组在没有排查雷的时候,都是 '*'
InitBoard(show,ROWS,COLS,'*');
注意我们需要知道的是当我们定义好一个数组的时候,在传送数组的同时,无论如何都应该把原汁原味的数组来接收,比如定义好这样的数组,在传送过去后需要用相同的格式来接收
char mine[ROWS][COLS] = { 0 }; //存放布置好的雷的信息
char show[ROWS][COLS] = { 0 }; //存放排查好雷的信息
类似于红色字体
3.打印棋盘void InitBoard(char board[ROWS][COLS] , int rows ,int cols,char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
int i = 0;
int j = 0;
printf("--------扫雷---------\n"); //打印一个边框
for (j = 0; j <= col; j++){ //打印一行数字,来让玩家更容易来找到坐标
printf("%d ",j); //这里从 0 开始可以对齐横纵坐标
}
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");
}
4.放置雷
//放雷
void Setmine(char board[ROWS][COLS], int row, int col) {
int count = EASY_COUNT; //在头文件中定义了雷的数目
while (count)
{
int i =rand() % row + 1; //使用了rand()函数,需要包含stdbli.h 头文件
int j =rand() % col + 1;
if (board[i][j] == '0') //当不是雷的时候就放置一个雷
{
board[i][j] = '1'; //我们需要把雷定义为数字字符 '1' 因为是字符数组
count--; //不过我们需要知道字符1 对应的ASCII值是 49
} //这点我们在之后的排查雷的时候会用到
}
}
5.排查雷
//排查雷
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 = Is_win(show,row,col)) != 1) //这里用到了函数的调用
{
printf("请输入坐标:>");
scanf("%d%d",&x,&y);
if (x>=1 && x<= row && y >= 1 && y <= col )
{
if (show[x][y] != '*')
{
printf("该坐标已被占用,请重新输入:>\n");
}
else
{
//是雷
if (mine[x][y] == '1')
{
printf("很遗憾,被炸死了\n");
DisplayBoard(mine, ROW, COL); //打印棋盘
break;
}
//如果不是雷
else
{
//统计mine数组中,x,y周围有几个雷
Remove_NoMine(mine,show,x,y); //并展开周围没有雷的坐标
DisplayBoard(show, ROW, COL); //打印排查之后的棋盘
}
}
}
else
{
printf("非法坐标,请重新输入\n");
}
}if (win == 1)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL); //打印布置雷的棋盘
}
}
6.统计周围雷的数量
//统计周围雷的数量
int get_mine_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');
}
这个就是一个八面相加然后减去8 * ‘0’ 的值就行了
7.展开周围//当周围有雷时显示周围有多少雷,并展开没有周围数字显示的"空格"
void Remove_NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
//附近都无雷,把棋盘扩展开来知道遇到雷
{
int i = 0;
int j = 0;
show[x][y] = get_mine_count(mine, x, y) + '0';//将展示的数组里坐标更改为周围雷的个数
//转换成数字字符
//字符0,与数字0 相隔48 ,因此减去就行
//这个方法同样的也适用与其他数字字符的转换
if (show[x][y] == '0')
{
show[x][y] = ' '; //如果周围雷的个数为0,则设置此坐标为“空格”
//判断此坐标周围坐标是否还有可设为空格的坐标
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (show[x + i][y + j] == '*')
Remove_NoMine(mine, show, x + i, y + j); //递归直到遇到数字
}
}
}
}
8.判断是否已经赢了
//判断是否已经赢了
int Is_win(char show[ROWS][COLS], int row, int col)
{
int win = 0; //用于统计剩下的*与雷相比较,相同即排雷成功
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++) {
if (show[i][j] == '*')
win++;
}
}
if (win == EASY_COUNT) //用于判断是否需要继续循环
return 1;
else
return 0;
}
三、测试
结束语
为了理解到这个扫雷的代码,还是得花上一点时间啊……
未完持续……
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)