最近乐学来了个花活,“统计一个格子附近雷的个数”
题目搬一下:
每个数字表示了该方格周围到底有几个地雷,当然,一个方格周围最多的时候只会有八个。
输入
输入中将包括一系列的地图,每个地图的第一行有两个整数 n 和 m(0 <n,m <= 100),它们表示了地图的行数和列数。下面的 n 行每行都有 m 个字符,其中 "." 表示安全而 "*" 表示地雷。如果地图的 n 和 m 都为 0,则表示输入结束。
输出
针对每一个地图,首先输出一行:
Field #x:
其中 x 是当前地图的编号(从 1 开始)。下面的 n 行则将地图中的 "." 以数字表示,该数字表示该方格周围有多少颗地雷。
我之前写过一个扫雷的小游戏,于是几乎回想以前的方法就直接给他扬了, 题目是《扫雷-不止于扫雷》,这个标题也是本文的雷。(废话)
主要思路:
要判断一个格子周围是否有雷,如果要讨论边界——四条边加四个角,八个特殊情况,八个if叠加else,复制粘贴也是大工程。我们为何不初始化这个雷区多两行两列,也就是在现有雷区的基础上,边框上围多一圈“安全区”呢?
这样就不需要讨论了,以4x4的初始棋盘为例,见下草图,周围都是点,排到也是安全的,不影响最终计数。

初始化的方法可以选择最笨重的,暴力就完事了:
由于最大棋盘是100x100,然后具体大小要根据输入的x和y微调。
char grid[102][102];
// 初始化棋盘比原始大一圈
for(i=0;i<x+2;i++) // 初始化第一列为点
{
grid[i][0]='.';
grid[i][y+1]='.'; // 初始化最后一列的下一列为点
grid[i][y+2]='\0'; // 再下一列为字符串结束标志,严谨就完事了
}
for(j=0;j<y+2;j++)
{
grid[0][j]='.'; // 初始化第一行为点
grid[x+1][j]='.'; // 初始化最后一行的下一行为点
}
for(i=1;i<x+1;i++)
{
char s[100];
scanf("%s",&s); // 依次输入棋盘的内容,然后顺序读入
int t=0;
for(t=0;t<y;t++)
{
grid[i][t+1]=s[t];
}
}
然后就到排查雷:
这道题自始自终都只有两个字符:'.' 和 '*';
可不可以用一下ascii码呢?少用点判断?——答案是肯定的
这两个字符的ascii码就差了4,把这个点周围的八个ascii加起来,然后用8个理想的安全字符 '.' 减去这个和,然后除以4,得到的刚好就是 * 的个数。
static int get_mine_count(char mine[102][102],int x,int y)
{
return (8*'.'-(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]))/4;
}
这道题最后涉及到的顺序打印棋盘,这里就只给出思路:
(1)能不能创建一个一维整型数组,存储每一次输入的行数?
(2)能不能复制一个棋盘,存储最终的总的所有情况,假如第一次输入4x4,第二次输入3x3,就像这样(下图),最终打印的时候,按照(1)中存储的行数依次打印棋盘呢?

如果你只追求做完这题,那本文结束了,但是按照本文的题目捏,下面还有”亿“些内容
扫雷教程千千万,扫雷方法一二三,如何根据自己的喜好写出自己想要的扫雷游戏而不是照搬呢?
刚才这道题已经解决了扫雷当中”扫描“的步骤,再加一步“诊断是否被炸”就算是游戏的主体了。当然,扫雷离不开“初始化”—>“判断、排雷”(已解决)这一循环周期
“初始化”:
如何设置棋盘的大小服务于后面的游戏主体?
显然,我们可以设置两个棋盘,一个用来埋雷,一个用来给玩家看,让他们排雷。这两个棋盘大小显然不一样,埋雷的棋盘要比排雷的小一圈。
代码仅供参考,内容大可自定义
#define ROWS 10
#define COLS 10
// 初始化棋盘,行列字符,三者自定义
void InitBoard(char board[ROWS][COLS],int rows,int cols,char set)
{
int i=0;
int j=0;
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
board[i][j]=set; // 自定义字符
}
}
}
至于“埋雷”:可以选择用函数生成随机数,并用这个随机数对行列数取模,以次限制,埋雷的范围,当然需要对已有的雷进行表示,防止重复埋雷,导致降低难度。
#define ROWS 10
#define COLS 10
#define Easy_count 10
#define Mid_count 50
#define Hard_count 100
void SetMine(char mine[ROWS][COLS],int row,int col)
{
int count=Easy_count; // 最终布置雷的个数
while(count)
{
int x=rand()%row+1; // 控制随机生成的雷的下标
int y=rand()%col+1;
if(mine[x][y]=='0') // 避免重复设置雷
{
mine[x][y]='1';
count--;
}
}
}
浅浅讲了扫雷的主体思路,更详细的跟好的可以搜其他大佬的。
至此,整个扫雷主体搭建就算完成了,至于输入坐标判断这活,佬们都应该会的,不会就是没好好上课!(不是我讲的不好bushi)
博客详细介绍了扫雷游戏的算法实现,包括初始化棋盘、统计相邻雷数和扫雷游戏的核心逻辑。通过扩展棋盘边界简化边界条件判断,并利用ASCII码差值快速计算雷的数量。还探讨了扫雷游戏的初始化和埋雷过程,提供了相应的代码示例。
245

被折叠的 条评论
为什么被折叠?



