目录
一、分块编程
将函数声明,函数定义,函数运行写在不同的game.h,game.c,test.c文件中,可以可读性,可移植性
二、扫雷的分析
1.打印菜单
2.初始化棋盘
3.随机布置雷
4.排查雷:不是雷,显示周围雷的个数
是雷,被炸死,游戏结束
如果雷全被找出来,赢了,游戏结束
三、扫雷的实现
test.c
#include "game.h"
引用“game.h”
打印菜单-menu函数
void menu()
{
printf(" 扫雷游戏!\n");
printf("##################\n");
printf("######1.play######\n");
printf("######0.exit######\n");
printf("##################\n");
}
游戏的实现-game函数
void game()
{
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
Init_Board(mine,ROWS,COLS,'0');
Init_Board(show,ROWS,COLS,'#');
Display_Board(show,ROW,COL);
Set_Mine(mine,ROW,COL);
//Display_Board(mine,ROW,COL);//用来调试
Find_Mine(mine,show,ROW,COL);
}
初始化雷的数组与展示的数组
Init_Board初始化棋盘 mine与show
Display_Board展示棋盘
Set_Mine随机生成雷
Find_Mine排查雷
main函数
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
scanf("%d", &input);
switch(input)
{
case 1:
game();
case 0:
break;
default:
printf("选择错误,重新选择!\n");
}
}while(input);
return 0;
}
srand((unsigned int)time(NULL))来初始化rand()的随机值,只需初始化一次所以放在主函数中
打印菜单,并使用do while循环(先执行,再判断下次循环)
1->执行game函数
0->退出
else->重新选择
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_Count 10
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set);
void Display_Board(char board[ROWS][COLS], int row, int col);
void Set_Mine(char board[ROWS][COLS], int row, int col);
void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
引用所需头文件,在.h文件中引用,其他文件引用“game.h”,避免重复引用
#define定义全局变量,改变大小时方便,不用多处修改
先声明函数,之后在定义
game.c※
Init_Board初始化棋盘
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
可以传入初始化的字符
Display_Board展示棋盘
void Display_Board(char board[ROWS][COLS], int row, int col)
{
for (int i = 0; i <= row; i++)
printf("%d ", i);
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
Set_Mine随机生成雷
void Set_Mine(char board[ROWS][COLS], int row, int col)
{
for (int i = 0; i < Easy_Count; i++)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
board[x][y] = '1';
else
i--;
}
}
利用rand函数生成0-9的随即值,将雷布置为‘1’
如果已经布置为雷,就i--,再重新布置一次
Get_Mine_Count得到周围雷的个数
static int Get_Mine_Count(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] + board[x - 1][y + 1] +
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';
}
static不想除了game.c的文件使用这个函数
数字的ASCII码值减去‘0’,就是它原本的数字
Find_Mine排查雷
void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y, count = 0;
while (1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '0')
{
count++;
show[x][y] = Get_Mine_Count(mine, x, y) + '0';
Display_Board(show, ROW, COL);
}
else
{
printf("砰,你被炸死了!\n");
Display_Board(mine, ROW, COL);
break;
}
if (count == ROW * COL - Easy_Count)
{
printf("你赢了!\n");
break;
}
}
else
printf("坐标非法,重新输入!\n");
}
}
先要排查坐标是否合法,再排查
不是雷,显示周围雷的个数,count++,展示棋盘,继续循环
是雷,被炸死,打印雷的棋盘,游戏结束
赢时,count 等于 格子数减去雷数,游戏结束
四、结语
本人也是刚刚入门c语言,扫雷是一个适合学习完数组和函数及其之前内容的同学,挑战自己,加强自己对所学内容掌握能力的很好的程序,如果在写完程序之后,发现有bug,要善于运用调试,在扫雷这个程序中可以将Display_Board这个函数放在不同位置,打印count,改变雷的数量等方法进行调试,验证程序是否有bug,不要害怕出差,我也是经过多次调试,与修改才完成的
本篇文章如有错误,或者值得优化的地方,还请各位大佬多多指出,感谢大家的阅读
下篇文章,将是扫雷的进阶,扩展发现雷函数,感兴趣的朋友点个关注
五、代码总览
test.c
#include "game.h"
void menu()
{
printf(" 扫雷游戏!\n");
printf("##################\n");
printf("######1.play######\n");
printf("######0.exit######\n");
printf("##################\n");
}
void game()
{
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
Init_Board(mine,ROWS,COLS,'0');
Init_Board(show,ROWS,COLS,'#');
Display_Board(show,ROW,COL);
Set_Mine(mine,ROW,COL);
//Display_Board(mine,ROW,COL);//用来调试
Find_Mine(mine,show,ROW,COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
scanf("%d", &input);
switch(input)
{
case 1:
game();
case 0:
break;
default:
printf("选择错误,重新选择!\n");
}
}while(input);
return 0;
}
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_Count 10
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set);
void Display_Board(char board[ROWS][COLS], int row, int col);
void Set_Mine(char board[ROWS][COLS], int row, int col);
void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
void Expand_Find(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int *count);
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void Display_Board(char board[ROWS][COLS], int row, int col)
{
for (int i = 0; i <= row; i++)
printf("%d ", i);
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void Set_Mine(char board[ROWS][COLS], int row, int col)
{
for (int i = 0; i < Easy_Count; i++)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
board[x][y] = '1';
else
i--;
}
}
static int Get_Mine_Count(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] + board[x - 1][y + 1] +
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 Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y, count = 0;
while (1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '0')
{
count++;
show[x][y] = Get_Mine_Count(mine, x, y) + '0';
Display_Board(show, ROW, COL);
}
else
{
printf("砰,你被炸死了!\n");
Display_Board(mine, ROW, COL);
break;
}
if (count == ROW * COL - Easy_Count)
{
printf("你赢了!\n");
break;
}
}
else
printf("坐标非法,重新输入!\n");
}
}