今天就用之前所学的知识来写一个C语言简易版扫雷游戏,主要涉及了C语言中的一些基本知识,循环、分支、函数、数组等等,如果熟练掌握以上的知识其实都不难
游戏规则:
就是在一个棋盘内点击格子,通过出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输
游戏胜利条件:找出所有非雷的格子,同时不能踩到雷
先创建游戏菜单,咱们用do while循环来实现,最开始先执行一次在进行判断,switch用于分支选择,来判断玩家是否要重复进行游戏,然后就是 game()函数,就是游戏的实现了
void menu()
{
printf("**********************\n");
printf("****** 1. 开始 *******\n");
printf("****** 0. 退出 *******\n");
printf("**********************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
咱们先创建一个源文件和一个头文件,分别放game.c (函数功能的实现) 和 game.h (函数的声明)
然后再创建数组,这里数组不建议使用方法一,因为不方便修改,如果我们想扩大棋盘要修改数组的时候,要一个一个地方进行修改
方法二:
推荐大家都这样写
只需要在 game.h 头文件定义个全局变量就可以,方便后期修改
方法一:
void game()
{
char mine[9][9] = { 0 };
char show[9][9] = { 0 };
}
-------------------------------
方法二:
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
}
假设我们建立 9 * 9 的游戏棋盘,那我们真正就要建立 11 * 11 的棋盘,如图,绿色区域就是要扫雷的区域,在绿色区域才会有雷。之所以要建立大一圈的棋盘,是为了后面检测扫雷地址周围雷数目时不越界
game.h 函数声明文件
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
mine用以放置布置雷的信息
show用于放置排查雷的信息
这样做可以方便的显示排查地址周围雷的数量。使用define定义后期想改变棋盘大小更方便
void game()
{
char mine[ROWS][COLS] = { 0 }; 存放的是布置雷的棋盘
char show[ROWS][COLS] = { 0 }; 存放的是排查雷的棋盘
}
将mine初始化为‘0’,布置雷的棋盘
show初始化为‘*’,玩家看到的棋盘,初始化为 *,看起来更有神秘感
这样做是为了让埋雷、计算雷的数量的时候更方便
void game()
{
char mine[ROWS][COLS] = { 0 };//存放布置雷
char show[ROWS][COLS] = { 0 };//存放排查雷的信息
//初始化棋盘
//mine 数组在没有布置雷时,初始化为 - '0'
Isitboard(mine, ROWS, COLS,'0');
//show 数组在没有排查雷时,初始化为 - '*'
Isitboard(show, ROWS, COLS, '*');
}
把全部都初始化为 str 里的元素
void Isitboard(char board[ROWS][COLS], int rows, int cols, char str)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = str;
}
}
}
记住雷是布置在mine数组里的,别传错了,还有就是传的是棋盘大小,不是数组大小
ROWS 和 COLS 是棋盘大小,ROW 和 COL 是棋盘大小
Mine_count是全局变量,Mine_count是雷的个数
前面已经把mine初始化为‘ 0 ’了,现在只需将要放雷的位置的内容改为‘ 1 ’就可以了。这个位置是随机产生的,这里使用了srand函数和rand函数来生成随机数。雷的放置坐标区域是[1][1]到[9][9],也就是上面的绿色区域。所以rand() % row得到0~8的数,要加上1
随机放置雷,雷表示字符 ‘1’
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = Mine_count;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
打印棋盘是和上面布置雷一样传的是棋盘大小(ROW和COL),先把棋盘的全部元素,在一步一步加上行号和列号,别忘了要函数的声明
这样就完成了大半了,就剩下排查雷了
//打印棋盘测试
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("---------扫雷游戏---------\n");
//打印第一行的数字
for (i = 0; i <= col; 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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while ()
{
printf("请输入排雷坐标:\n");
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//如果是雷,结束游戏
if (mine[x][y] == '1')
{
printf("你被炸死了,游戏结束\n");
DisplayBoard(mine, ROW, COL);
break;
}
//如果不是雷
else
{ //计算周围 8 个格子雷的数量
int count = mine_count(mine, x, y);
show[x][y] = count+'0';
DisplayBoard(show, ROW, COL);
}
}
else
printf("坐标非法,重新输入\n");
}
}
雷个数的计算方式就是把坐标周围8个字符加起来再减去8个字符‘0’,得到的就是雷的个数,再加上‘0’字符的形式打印
为什么要减去8个字符‘ 0’
因为字符0是以ASCll码值存储的,字符0的ASCLL值是48,字符‘1’的ASCLL值是49,而周围有8个坐标,加起来在减去8个字符‘ 0’,相减就得出雷的个数
这么写是为了区分开来数字0和字符0
int mine_count(char mine[ROWS][COLS], 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';
}
row*col 是计算数组的个数
-Mine_count 是减去雷的数量
//胜利条件
if (win == row * col - Mine_count)
{
printf("排雷成功\n");
DisplayBoard(show, ROW, COL);
}
#include"game.h"
void menu()
{
printf("**********************\n");
printf("****** 1. 开始 *******\n");
printf("****** 0. 退出 *******\n");
printf("**********************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };// 存放的是布置雷的棋盘
char show[ROWS][COLS] = { 0 };//存放的是排查雷的棋盘
//初始化棋盘
//mine 数组在没有布置雷时,初始化为 - '0'
Isitboard(mine, ROWS, COLS,'0');
//show 数组在没有排查雷时,初始化为 - '*'
Isitboard(show, ROWS, COLS, '*');
//布置雷
SetMine(mine, ROW, COL);
//打印数组测试
//布置雷棋盘
//DisplayBoard(mine, ROW, COL);
//存放排雷棋盘
DisplayBoard(show, ROW, COL);
// 排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
//棋盘的大小
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//雷的数量
#define Mine_count 10
#include
#include
#include
//初始化棋盘
void Isitboard(char board[ROWS][COLS], int rows, int cols, char str);
//布置雷
void SetMine(char mine[ROWS][COLS], int row,int col);
//打印棋盘测试
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
#include"game.h"
//初始化棋盘
void Isitboard(char board[ROWS][COLS], int rows, int cols, char str)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = str;
}
}
}
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = Mine_count;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
//打印棋盘测试
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("---------扫雷游戏---------\n");
//打印第一行的数字
for (i = 0; i <= col; 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");
}
//排查周围雷的数量
int mine_count(char mine[ROWS][COLS], 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';
}
//排查雷
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<row*col-Mine_count)
{
printf("请输入排雷坐标:\n");
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//如果是雷,结束游戏
if (mine[x][y] == '1')
{
printf("你被炸死了,游戏结束\n");
DisplayBoard(mine, ROW, COL);
break;
}
//如果不是雷
else
{
//统计mine数组中 x 和 y坐标周围有几个雷
win++;
int count = mine_count(mine, x, y);
show[x][y] = count +'0';
DisplayBoard(show, ROW, COL);
}
}
else
printf("坐标非法,重新输入\n");
}
//胜利条件
if (win == row * col - Mine_count)
{
printf("排雷成功\n");
DisplayBoard(show, ROW, COL);
}
}