✨✨✨学习的道路很枯燥,希望我们能并肩走下来!
编程真是一件很奇妙的东西。你只是浅尝辄止,那么只会觉得枯燥乏味,像对待任务似的应付它。但你如果深入探索,就会发现其中的奇妙,了解许多所不知道的原理。知识的力量让你沉醉,甘愿深陷其中并发现宝藏。
本篇通过扫雷小游戏,加强对循环,选择,分支的练习,对于初学者小游戏能提高我们的兴趣,让我们一起操作起来吧!如有错误,请在评论区指正,让我们一起交流,共同进步! |
本文开始
扫雷这个大家所熟知的小游戏,你是否玩过呢,他是你记忆中的一部分?
今天让我们来实操一下,如何用代码写出简单的扫雷,这里的扫雷,不能像真正的扫雷一样,只是大概思路相同,简单编写一个10个雷的简易模式,如果想让扫雷更加真实,请根据这篇文章,自我思考,自己编写一下吧!
让我们先从 扫雷棋盘的格式 入手:
扫雷的区域构建肯定需要用到二维数组,但怎么考虑呢?
对于9*9的扫雷棋盘我们构建完够用吗?
构建扫雷棋盘我们还应该考虑到对于你选定的位置周围的8个方格如何计算,方格数是否满足?
我们通过以下图片来分析一下.
如何构建扫雷棋盘
对于黑方块所选内容为正常我们需考虑的,使用二维数组对于 红方块内容,则是会 出现越界访问的问题,如何解决呢,这里需要我们主动设置一个更大的扫雷棋盘,满足我们的要求.
需要 9 * 9 扫雷棋盘 --> 9 * 9的二维数组 -->考虑用11*11扫雷棋盘 (如图外层绿色方框)
放置雷,如何安放呢,怎么更好统计呢?
设置两个扫雷棋盘
①这里使用会使用两个扫雷棋盘(两个数组),一个mine数组用来放置雷信息,一个show数组用来放置排查出雷的信息
②开始设置:mine数组(设计者自己观察调整的扫雷棋盘)全初始化 ’0‘,布置为雷时改为 ’1‘;show数组(玩家观看)全初始化为 ’*‘,排雷后,玩家输入的位置改为数字字符(8个方格有几个雷),如:’3‘;
这里会有小伙伴问为什么用两个扫雷棋盘?
如果只有一个扫雷棋盘,计算出玩家所在周围有1个雷,会与开始放置的雷(1为雷)所重复,没法判断是雷(1),还是所处位置周围的雷(1);
为什么不用 *,#直接在一个棋盘表示?
对于扫雷代码,我们一般不放在一个.c文件下,会显得思路不够简洁,代码整体太乱!
所以我们一般分为三个:
①text.c 扫雷游戏的测试逻辑
②game.h 游戏函数的声明
③game.c 游戏函数的实现
先构建扫雷游戏的测试逻辑
制作简易菜单(menu);选择输入是否开始游戏(switch);设置游戏循环条件(do while)
#include"game.h"
void menu()
{
printf("**********************\n");
printf("******* 1.play ******\n");
printf("******* 0.exit ******\n");
printf("***********************\n");
}
void game()
{
printf("扫雷\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择(0/1):>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
当我们构建完主函数,接下来主要构建game()函数
game():
①创建扫雷棋盘
②初始化扫雷棋盘
③布雷
④排雷
[注]由于怕越界,创建扫雷棋盘都以11*11创建
初始化两个扫雷棋盘除了初始化内容不同,其他代码相同,为了使代码简便,我们只把需要初始化的参数传给函数即可,简化了代码
#include"game.h"
void init_board(char board[ROWS][COLS], int rows, int cols,int ret)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
//只需所要的初始化的值传过来就行
mine[i][j] = ret;
}
}
}
//打印扫雷棋盘
void display_board(char mine[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("%c ", mine[i][j]);
}
printf("\n");
}
}
开始打印扫雷棋盘:
扫雷棋盘虽然创建好了,但是不容易看每行坐标,我么来加上序号看一下!
扫雷棋盘优化:
#include"game.h"
void display_board(char board[ROWS][COLS], int row, int col)
{
//row--行,col--列
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
//打印数据开始,先打印每一行行号1-9
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
代码结果:
这里用到之前文章讲的随机函数,产生随机值
rand(),srand(),time();
如果不了解随机值的产生,可以点开这篇文章看一下哦!
猜数字游戏里关于rand,srand的使用说明
[注]
代码示范:
void set_mine(char mine[ROWS][COLS], int row, int col)
{
//布置10个雷
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
//本来余9是得到0-8的数,+1是得到1-9的数,正好与设置的序号对应
int y = rand() & col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
这是玩家所能操作的棋盘,需要玩家输入位置,就开始了扫雷
[注]
代码示范:
int get_mine_count(char mine[ROWS][COLS],int x,int y)
{
return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
+ mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1]-8*'0');
}
void find_mine(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-EASY_COUNT)
{
printf("请输入坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("踩到了雷,被炸死了\n");
display_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
//show中需要存字符数字,需要加上'0'字符0,如:'a'+2=‘c'
display_board(show, ROW, COL);
win++;
}
}
else
{
printf("该坐标已经被排除过了\n");
}
}
else
{
printf("坐标超出范围,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
display_board(mine, ROW, COL);
}
}
//game.h
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 80
#include
#include
#include
//初始化
void init_board(char board[ROWS][COLS], int rows, int cols,int ret);
//打印
void display_board(char board[ROWS][COLS], int row, int col);
//布雷
void set_mine(char mine[ROWS][COLS], int row, int col);
//排雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//text.c
//#include"game.h"
void menu()
{
printf("**********************\n");
printf("******* 1.play ******\n");
printf("******* 0.exit ******\n");
printf("**********************\n");
}
void game()
{
//printf("扫雷\n");
//创建布雷区域
char mine[ROWS][COLS] = { 0 };
//创建显示雷有几个的棋盘--玩家眼中的区域
char show[ROWS][COLS] = { 0 };
//初始化雷区域全为字符0,‘0’
//如何定义一个函数让两个全部初始化,只需要把初始化的内容传参传过去,就可以不要重复写一样的代码了
init_board(mine, ROWS, COLS, '0');
//display_board(mine, ROW, COL);
//打印发现这样不容易观看,我们可以考虑为它们打印序号
//初始化扫雷区域为‘*’
init_board(show, ROWS, COLS, '*');
//display_board(show, ROW, COL);
//布雷
set_mine(mine, ROW, COL);
display_board(mine, ROW, COL);
//排雷
display_board(show, ROW, COL);
find_mine(mine,show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择(0/1):>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
//game,c
//#include"game.h"
void init_board(char board[ROWS][COLS], int rows, int cols, int ret)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = ret;
}
}
}
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
//打印数据开始,先打印每一行行号1-9
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void set_mine(char mine[ROWS][COLS], int row, int col)
{
//布置10个雷
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;//本来余9是得到0-8的数,+1是得到1-9的数,正好与设置的序号对应
int y = rand() & col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int get_mine_count(char mine[ROWS][COLS],int x,int y)
{
return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
+ mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1]-8*'0');
}
void find_mine(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-EASY_COUNT)
{
printf("请输入坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("踩到了雷,被炸死了\n");
display_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';//show中需要存字符数字,需要加上'0'字符0,'a'+2=‘c'
display_board(show, ROW, COL);
win++;
}
}
else
{
printf("该坐标已经被排除过了\n");
}
}
else
{
printf("坐标超出范围,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
display_board(mine, ROW, COL);
}
}
✨✨✨各位读友,本篇分享到内容是否更好的让你理解了扫雷小游戏的乐趣,让你对代码的兴趣有了提升呢?如果文章对你有帮助希望给个赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!