【项目】—— 扫雷小游戏(C语言)
使用C语言实现的一个扫雷小游戏,这里没有美观的鼠标可点触窗口,只有初学者面对的让人心酸的黑框框,以及需要键盘输入坐标的输入模式。
游戏功能
- 打开游戏,有一个进入游戏和退出游戏的界面
- 进入游戏,展示一个 9 × 9 9\times9 9×9的方格,每个位置都是空格
- 玩家开始输入排雷的坐标,如果该位置是雷,则游戏结束,玩家失败
- 如果该位置不是雷,则显示周围一圈的8个格子雷的数量,玩家继续输入坐标排雷
- 所有非雷位置全部排查时,游戏结束,玩家胜利
*
,并提示游戏结束test.c
:测试源文件,含有main函数,是进入程序的入口game.c
:游戏源文件,实现游戏内的函数定义game.h
:游戏头文件,包含源文件需要包含的头文件,实现宏定义,对游戏内的函数进行声名先将二维数组初始化成全0,调用随机函数,生成 9 × 9 9\times9 9×9范围内的坐标,并将该地雷所在坐标置为数字1
#pragma once //防止头文件重复包含
#include
#include //用于调用随机种子
#include //设置随机种子的参数需要调用该库函数time
#include //用于执行一些命令行(后面再看)
#define ROW 9 //设置行
#define COL 9 //设置列
#define COUNT 10 //设置地雷数量
#define ROWS ROW+2 //扫雷数组实际的行
#define COLS COL+2 //扫雷数组实际的列
void InitBoard(char board[ROWS][COLS], int rows, int cols, char c); //初始化
void SetMine(char mine[ROWS][COLS], int row, int col, int count); //部署地雷
void DisplayBoard(char board[ROWS][COLS], int row, int col); //打印展示界面
_Bool FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); //排查地雷
int get_mine_count(char mine[ROWS][COLS], int row, int col, int x, int y); //获取该子周围的雷的数量
将扫雷数组初始化为0
void InitBoard(char board[ROWS][COLS], int rows, int cols, char c)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = c;
}
}
}
在扫雷数组上随机设置地雷为1,为了防止生成坐标重复,使用计数器count
记录设置好的地雷数量,若是地雷成功设置才会计数
void SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
while (count > 0)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
需要打印出9宫格的效果,使用-
字符作为行,|
字符作为列。先打印一行,再打印row
行,最后一行和一列要单独处理
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int k = (col - 5) / 2;
int i = 0;
printf("-");
for (i = 0; i <= col; i++)
{
if (i < k || i >= 5+k)
{
printf("--");
}
else
{
printf("扫雷小游戏");
i += 5;
}
}
printf("\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
将扫雷数组上下左右9个坐标的值加起来就是雷的数量
int get_mine_count(char mine[ROWS][COLS], int row, int col, int x, int y)
{
return (mine[x - 1][y - 1]
+ mine[x - 1][y]
+ mine[x - 1][y + 1]
+ mine[x][y - 1]
+ mine[x][y + 1]
+ mine[x + 1][y - 1]
+ mine[x + 1][y]
+ mine[x + 1][y + 1])
- (8 * '0');
}
输入坐标,并判断是否合法,是否重复,然后判断是否是雷,若都不是,计算该位置周围地雷数量并展示界面,然后判断输赢
_Bool FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int num = 0; //已排查的数量
do
{
printf("请输入坐标>");
scanf("%d %d", &x, &y);
//判断坐标是否非法
if ((0 < x && x <= row) && (0 < y && y <= col))
{
//判断坐标是否重复
if (show[x][y] == '*')
{
//此处是雷
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
}
//此处不是雷
else
{
num++;
int count = get_mine_count(mine, row, col, x, y);
show[x][y] = (char)count + '0';
system("cls");
DisplayBoard(show, row, col);
}
}
else
{
printf("该位置已被排查\n");
}
}
else
{
printf("坐标输入错误\n");
}
//判断输赢
if (num >= row * col - COUNT)
{
printf("恭喜你,你赢了\n");
DisplayBoard(mine, row, col);
break;
}
} while (1);
return 0;
}
测试文件是用来测试游戏实现,并写有main
函数作为启动程序的入口。
只有两个选项,开始游戏和推出游戏
void menu(void)
{
printf("****************************\n");
printf("********* 1. play ********\n");
printf("********* 0. exit ********\n");
printf("****************************\n");
}
将游戏逻辑封装成一个函数,调用该函数就可以完整的启动游戏
void game()
{
char mine[ROWS][COLS] = { '0' };
char show[ROWS][COLS] = { '0' };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//部署地雷
SetMine(mine, ROW, COL, COUNT);
//展示棋盘
DisplayBoard(show, ROW, COL);
//玩家排雷
FindMine(mine, show, ROW, COL);
}
在这里实现菜单和游戏的调用,提供用于开始游戏和结束游戏的选择
int main(void)
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入操作序号>");
scanf("%d", &input);
switch (input)
{
case 0:
printf("欢迎下次光临\n");
break;
case 1:
game();
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (0 != input);
return 0;
}
代码存储于gitee中:点击查看完整代码