高度提示:这里的题目解析,表示的是此人的理解和想法
题目大意:
扫雷游戏是一款十分经典的单机小游戏。在 n行 m 列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。
现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。
注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。
输入描述
输入文件第一行是用一个空格隔开的两个整数n和m,分别表示雷区的行数和列数。
接下来 n行,每行m 个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。
输出描述
输出文件包含 n 行,每行 m 个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。
例如
输入:
3 3
*??
???
?*?
输出:
*10
221
1*1
题目解析
扫雷游戏理解
首先:我们先了解一下扫雷这个游戏(ps:Windows内置的小游戏中有扫雷,可以到扫雷游戏查看)
扫雷就是在规定时间内找出所有不含雷的空格
如图
那么我们来观察输入和输出的东西:
题目分析
知识点概要:
1.数组的运用:
这次我们要用到的是二维数组
前两个数字则是雷区的长和宽
用二维数组能更好的处理和输出。
首先:创建二维数组
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b;//分别输入的长和宽
cin>>a>>b;
char arr[a+2][b+2]={};
int arr_number[a+2][b+2]={};
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
cin>>arr[i][j];
if(arr[i][j]=="*") arr_number[i][j]=10//这里的10表示雷
}
}
return 0;
}
此处a,b两个数字分别是长和宽,接着再创捷两个数组
一个是char类型 一个是 int 类型
why?
那是因为 同个数组当中不会是两种或多种不同类型的数据存入,所以我们要在每个char数组的下面,弄一个int 类型的数组在进行定值,
那么为什么要在a,b后面都加2呢
那是因为我们要侦测的是一个格子周围八个格子是否有雷,当列表超出范围时,程序则会报错
所以我们需要扩大范围
则当a,b为3时,列表的情况
X X X X X
X * ? ? X
X ? ? ? X
X ? * ? X
X X X X X
(此处已赋值)
并且赋值要从(1,1)开始 到(a,b)结束
将所有的数据都设为空 是为了防止其他不需要的空间对结果造成的干扰;
为了避免输出时int 类型char类型混一起造成程序报错 我们将“*”作为int类型数组中的10
因为一个格子周围最多也就8颗雷为什么是10
因为我喜欢
接着:我们再来实现对每个格子的遍历
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
if(arr_number[i][j]==10) continue;
for(int x=i-1;x<=i+1;x++)
{
for(int y=j-1;y<=j+1;y++)
{
if(arr_number[x][y]==10) arr_number[i][j]=arr_number[i][j]+1;
}
}
}
}
这里有些复杂,我们拆开分析
首先:我们先分析遍历每个格子
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
//此处为每个格子的程序编写
}
}
通过for循环我们可以获取每个子的数据,这里就不用多说了
然后 就是每个格子的程序分析
if(arr_number[i][j]==10) continue;
for(int x=i-1;x<=i+1;x++)
{
for(int y=j-1;y<=j+1;y++)
{
if(arr_number[x][y]==10) arr_number[i][j]=arr_number[i][j]+1;
}
}
第一个if条件语句 判断是不是雷
如果是雷那么就跳过进行下一个格子的分析
如果不是则开始这个格子周围区域的分析
那么两次的for是什么意思呢?
如图
x-1 x x+1
y-1 ???
y ?X ?
y+1 ???
假如 说X是我们要检验的格子
要判断周围八个?的格子,我们就需要for循环对9个格子的是否有雷情况进行判断(中间为什么要判断,那是因为我懒得写中间跳过的程序)
当周围有雷时,那个空格就要加几
最后:我们要进行输出
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
if(arr_number[i][j]==10) cout<<"*";
else cout<<arr_number[i][j];
}
cout<<endl;
}
前两个for循环我就不多说了
看中间部分,当arr_number数组的遍历抽到10时,我们就要输出“*”
否则我们就要输出这个格子中所含有的数字。
最后的最后,我们进行代码呈现
此处实际代码与上文的代码会有所不同
#include<iostream>
using namespace std;
int main() {
int a,b;
cin>>a>>b;
char arr[a+2][b+2]={};
int arr_number[a+2][b+2]={};
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
cin>>arr[i][j];
if(arr[i][j]=='*') arr_number[i][j]=101;
}
}
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
if(arr_number[i][j]==101) continue;
for(int x=i-1;x<=i+1;x++)
{
for(int y=j-1;y<=j+1;y++)
{
if(arr_number[x][y]==101) arr_number[i][j]=arr_number[i][j]+1;
}
}
}
}
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
if(arr_number[i][j]==101) cout<<"*";
else cout<<arr_number[i][j];
}
cout<<endl;
}
return 0;
}