洛谷P2670扫雷问题反思

题目描述

扫雷游戏是一款十分经典的单机小游戏。在 n 行 m 列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。

现在给出 n 行 m 列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。

注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。

输入格式

第一行是用一个空格隔开的两个整数 n 和 m,分别表示雷区的行数和列数。

接下来 n 行,每行 m 个字符,描述了雷区中的地雷分布情况。字符 ** 表示相应格子是地雷格,字符 ?? 表示相应格子是非地雷格。相邻字符之间无分隔符。

输出格式

输出文件包含 n 行,每行 m 个字符,描述整个雷区。用 ** 表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。

输入输出样例

输入 #1复制

3 3
*??
???
?*?

输出 #1复制

*10
221
1*1

输入 #2复制

2 3
?*?
*??

输出 #2复制

2*1
*21

说明/提示

对于 100%的数据,1≤ n ≤100,1≤ m ≤100。


题解代码如下:

#include <iostream>
using namespace std;
const int dx[] = {1, 1, 1, 0, 0, -1, -1, -1};
const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
char g[105][105];
int n, m;
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)            //从1开始读,代表在地雷阵周边加上了一个空白边框,防止数组越界
        for (int j = 1; j <= m; j++)
            cin >> g[i][j];                 //读入地雷阵
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)
            if (g[i][j] != '*') {
                int cnt = 0;
                for (int k = 0; k < 8; k++)
                    if (g[i + dx[k]][j + dy[k]] == '*') cnt++;          //用循环代替八条if语句判断该点周围是否有地雷
                cout << cnt;
            }
            else cout << "*";               //若该点为地雷,直接输出即可
        cout << endl;
    }
    return 0;
}

 本题难点并不在于如何输入地雷阵,而是如何在代码后半部分的循环中逐个判断地雷阵中的地雷,以及非地雷位周围的地雷数量。

尤其是在地雷阵的边界,若直接采用双重for循环进行数组遍历,再逐个判断,可能造成数组越界。因此,一个处理方式就是开二维数组时在整个地雷阵外围多开一圈,全部置为非地雷位。

这样处理后,可以在遍历数组时不必额外处理地雷阵边界的点。

另外一个值得学习的地方是代码开头定义的两个一维数组,他的意义在于当我们判断地雷阵中每一个位置周围的地雷情况时,可以不用写八条if语句来判断周围是否存在地雷,而是可以直接通过一个for循环来判断(通过改变i、j的值),这样可以大大缩短代码长度,增加代码的可读性。


以后类似用二维数组处理的模拟题,都可以参考此题的解题思路和某些地方的处理(比如数组边界、判断某一点周围的情况等),这样可以大大缩短代码长度。

以上。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YUKIPEDIA~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值