1.题目
题号:NC16491
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
扫雷游戏是一款十分经典的单机小游戏。在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。
现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。
注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。
输入描述:
输入文件第一行是用一个空格隔开的两个整数n和m,分别表示雷区的行数和列数。
接下来n行,每行m个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。
输出描述:
输出文件包含n行,每行m个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。
备注:
对于100%的数据,1≤n≤100,1≤m≤100。
2.分析
第一直觉:在最外层构建一层,使得符号被包围,不用担心越界
3.代码
方法1:构建“九宫格”查找
#include <stdio.h>
#include <string.h>
int main()
{
int n, m;
int i, j;
int Row, Column;
char ChessBoard[150][150] = {'0'}; //棋盘
int Count = 0;
scanf("%d %d", &n, &m);
getchar(); //吞掉\n防止下一步获取
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
scanf("%c", &ChessBoard[i][j]); //依次输入每个字符
getchar(); //吞掉\n
}
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
if (ChessBoard[i][j] == '*')
printf("*");
else
{
Count = 0;
for (Row = i - 1; Row <= i + 1; Row++) //构建九宫格查找
{
for (Column = j - 1; Column <= j + 1; Column++)
{
if (ChessBoard[Row][Column] == '*')
Count++;
}
}
printf("%d", Count);
}
}
printf("\n");
}
return 0;
}
附加例子:
对外层的符号类似这样附加
0 | 0 | 0 |
---|---|---|
0 | * | 0 |
0 | 0 | 0 |
方法2:直接将查找的函数单独分离出来
每一次调用查找函数,并输出相应的值
#include <stdio.h>
#define N 120
char Board[N][N];
int n,m;
void Search(int x,int y);
int main()
{
int i,j;
scanf("%d%d",&n,&m); //输入行 列
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&Board[i][j]);
}
getchar(); //吞 \n
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(Board[i][j]=='*')
printf("*");
else
Search(i,j); //查找
}
printf("\n");
}
return 0;
}
void Search(int x,int y)
{
int Line,Row,count=0;
for(Line=-1;Line<2;Line++)
{
for(Row=-1;Row<2;Row++)
{
int line=x+Line;
int row=y+Row;
if(line>=0&&line<n&&row>=0&&row<m&&Board[line][row]=='*') //当周围有'*'时
count++;
}
}
printf("%d",count);
}
方法3:找到 ’ * ‘令其周围不是’ * '的值+1
#include <stdio.h>
char Board[120][120]={'0'};
int n,m;
void SumCount(int i,int j)
{
if(i>=0&&i<=n&&j>=0&&j<=m&&Board[i][j]!='*')
Board[i][j]++;
}
int main()
{
int i,j;
int Line,Row;
scanf("%d%d",&n,&m); //输入行数和列数
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&Board[i][j]);
if(Board[i][j]!='*') //不是'*'的标记为'0'
Board[i][j]='0';
}
getchar();
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(Board[i][j]=='*')
{
for(Line=i-1;Line<=i+1;Line++)
{
for(Row=j-1;Row<=j+1;Row++)
SumCount(Line,Row); //更新九宫格的值
}
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
printf("%c",Board[i][j]);
printf("\n");
}
return 0;
}
4.总结
灵活运用循环,解决边界条件
合理转化为等价的条件
5.更新日志
2022.3.22 整理