目录
附上扫雷小游戏链接,先来体味感受下真正的扫雷是怎样的
本文章为手把手讲解实现C语言扫雷(好好看,相信不会太难的说) 当你自己完成后一定成就感幸福感满满的!!
用C语言实现小游戏扫雷初级版(9x9棋盘/10个地雷)
vs2019
尽快找出雷区中的所有不是地雷的方块 根据点击格子出现的数字找出所有非雷格子 同时避免踩雷,踩到一个雷即全盘皆输
1.菜单选择开始或者退出游戏 2.初始化并打印雷区 3.第一次免雷和周边雷排查 4.雷区展开 5.判断胜利 6.游戏结束后展示玩家用时
1.test.c :写整个游戏实现思路流程 2.game.c: 写游戏实现思路中的各个函数的定义,完成函数内容实现函数功用 3.game.h :引用需要用到的头文件,以及对各个自定义函数的声明 (其他模板上方只需要加上 #include “game.h”,避免重复引用相同头文件) 注:模块化便于管理和修改
比较简单直接上代码
//菜单界面
void menu()
{
printf("************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("************************\n");
}
玩家通过输入1/0 来选择是开始游戏还是退出游戏 用do while语句实现比较适合
do
{
menu();
printf("请输入选择:>");
scanf("%d", &input);
switch (input)
{
case 0:
printf("成功退出游戏!\n");
break;
case 1:
printf("欢迎进入游戏!\n");
game();
break;
default:
printf("输入出错,请重新输入\n");
break;
}
} while (input);
因为我们在设计算法时需要统计坐标周围8个方位雷的个数 假如要统计边界坐标周围雷的个数,那么就会有数组越界的问题 那我们就要在9X9的边界多上一圈元素,也就要定义11X11的数组元素 这些元素我们显示给玩家看就可以了
使用9行9列的二维数组来表示,元素类型是char
char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
1.推高代码可读性,后续代码中遇到,方便理解含义 2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便
#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)
{
int i = 0;
for (i = 0; i < rows; i++)//行
{
int j = 0;
for (j = 0; j < cols; j++)//列
{
board[i][j] = '0';
}
}
}
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = COUNT;
while (count)
{
//生成随机下标
int x = rand() % row + 1;//取余后的范围是0-8
int y = rand() % col + 1;//加一后符合游戏范围
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;//设置10个后 count为0 不再循环
}
}
}
什么时候该打印 什么时候不该打印 打印的间距 换行的考虑 打印布局的美观性
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;//在外围打印标数以便于玩家定位坐标
printf("-----------------------------------------\n");
for (i = 0; i <= 9; i++)//0-9打印最上排数字
{
printf("| %d ", i);
}
printf("|\n");
printf("-----------------------------------------\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("| %d |", i);//1-9打印最左排数字
for (j = 1; j <= col; j++)
{
printf(" %c |", board[i][j]);
}
printf("\n");//一定注意要换行
printf("-----------------------------------------\n");//每打印一排内容,再打印一排横线,形成表格,提升美观
}
1.因为实际雷区是11x11的,也就是说显示雷区的下标是从1开始的,符合玩家思维 2.排雷范围 3.第一次免雷 4.显示周围雷数
//第一次免雷
void FirstSafe(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
int count = 0;
if (mine[x][y] == '1')
{
mine[x][y] = '0';//替换
while (1)
{
int rx = rand() % row + 1;
int ry = rand() % col + 1;
if (mine[rx][ry] == '0' && (rx != x) && (ry != y))
{
mine[rx][ry] = '1';//再次布雷
break;
}
}
count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
ExtendNotMine(mine, show, x, y, '0', '*');
DisplayShow(show, row, col);
}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (1)
{
printf("请输入要排查的坐标:>");
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
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';//替换成字符数,显示雷数
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)//获取周边一圈雷个数的信息
{
int ret = 0;
for (int i = x - 1; i <= x + 1; i++)
{
for (int j = y - 1; j <= y + 1; y++)//3X3范围
{
ret += mine[i][j];
}
}
return ret - mine[x][y] - 8 * '0';//注:'1'-'0'=1(ASCII码值)
}//返回值代表雷的个数
考虑用递归实现
//扩展排雷,展开周围非雷区
void ExtendNotMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int n = 0;
n = GetMineCount(mine, x, y);
if (n == 0)
{
show[x][y] = ' ';//如果周围没有雷,将中心赋值为空格
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (mine[i][j] =='0'&& show[i][j]=='*')//周围坐标满足自身不是雷且还是初始化字符,进入递归再次扩展排雷
{
{
ExtendNotMine(mine, show, i, j, '0', '*');//递归排雷
}
}
}
}
else
show[x][y] = n + '0';//如果附近有雷,展示雷的个数
}
遍历雷区剩余的初始值个数进行判断
//求展示扫雷棋盘上含有初始化字符的个数,用来判断游戏何时终止
int AroundInitCount(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (board[i][j] == '0')
count++;
}
}
return count;
}
if (count == EASY_COUNT)
{
printf("恭喜你!扫雷成功!\n");
DisplayShow(mine, ROW, COL);
break;
}
void SpendTime(clock_t start)
{
clock_t end = clock();
clock_t total = end - start;
printf("游戏所用时间为:%.1lf秒!\n", 1.0 * total / CLOCKS_PER_SEC);
}