扫雷
游戏思路
1、开始程序;
2、进入菜单menu() 选择是否游戏,接收选择;
3、雷区通过数组方式实现,布置雷采用mine[ ][ ],排查雷采用show[ ][ ];
4、初始化雷区层和排查层 InitBoard() ;
5、打印排查层 DisplayBoard() ,雷区层不用打印,隐藏起来即可;
6、布置地雷 SetMine() ,随机生成 rand() ;
7、排查雷 FindMine() ,接收坐标,先判断合法性,合法之后再判断是否有雷,无雷之后再判断坐标周围有几个雷 get_mine_count() ;
8、判断雷数 get_mine_count() 通过ASCII 码返回字符数字;
9、判断游戏状态 ;
10、游戏结束后显示雷区;
代码实现分为主函数、头文件、头文件.c文件,具体实现如下:
主函数:
#include "game.h"
//开始界面
void menu()
{
printf("***********************************\n");
printf("********* 1.play ********\n");
printf("********* 0.exit ********\n");
printf("***********************************\n");
}
//游戏内容
void game()
{
//设置雷区、排查区
char mine[ROWS][COLS];
char show[ROWS][COLS];
//初始化雷区、排查区
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印雷区、排查区,扫雷只用到中间部分,所以周围一圈不打印
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//设置地雷
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查地雷
FindMine(mine,show, ROW, COL);
//游戏结束后显示雷区
DisplayBoard(mine, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
//开始界面,选择是否游戏
menu();
printf("选择是否游戏,请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
{
game();
break;
}
case 0:
{
printf("退出游戏!\n");
break;
}
default:
{
printf("输入错误,请重新输入:>\n");
}
}
} while(input);
return 0;
}
首先进入菜单,然后选择游戏,输入1则开始游戏;输入0则退出游戏;输入其余数值则提示错误。
开始游戏后依次执行函数,各函数分别设定不同功能,方便调试和调用。
头文件:
#include <stdio.h>
//定义雷数
#define EASY_COUNT 10
//定义行、列
#define ROW 9
#define COL 9
//定义行、列。为方便后续计算,各+2
#define ROWS ROW+2
#define COLS COL+2
//初始化数组
void InitBoard(char Board[ROWS][COLS], int rows,int cols,char ch);
//打印数组
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);
头文件中各个函数功能和声明写清楚,方便后续使用。
头文件.c文件
#include "game.h"
//初始化数组
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
Board[i][j] = ch;
}
}
}
//打印数组
void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------------扫雷-----------\n");
printf("\n");
//打印行列序号
for (i = 0; i <= row; i++)
{
printf(" %d", i);
}
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 get_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* count)
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (mine[x][y] == '0')
{
//排查周围雷数并放入坐标内,若周围无雷则循环排查周围坐标。
int set = get_mine_count(mine, x, y);
if (set == 0)
{
show[x][y] = ' ';
(*count)++;
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*')
{
get_mine(mine, show, i, j, count);
}
}
}
}
else
{
show[x][y] = set + '0';
(*count)++;
}
}
}
}
//排查地雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (count < row * col - EASY_COUNT)
{
char ch;
//清除缓存区。
while ((ch = getchar()) != '\n' && (ch = getchar()) != EOF)
{
;
}
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
//判断状态 继续/被炸死/输入错误。
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '0')
{
//如果排雷成功,则执行是否循环排雷。
get_mine(mine, show, x, y, &count);
DisplayBoard(show, ROW, COL);
}
else
{
//排雷失败,则打印失败页面。
printf("很遗憾,你被炸死了!\n");
break;
}
}
else
{
printf("输入错误,请重新输入:>\n");
}
}
if (count == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
}
}
各项内容具体实现如上。分模块编写函数是为了方便调试,之前编写模块如果没有问题,那问题出现的地方就在新编写的模块函数中,因此出现问题可以很快找到出错点。