[NOIP 2015 普及组] 扫雷游戏

GitHub跳转原题关系图返回列表

枚举每个非雷格的八个方向邻格,统计周围地雷数量并生成答案矩阵。

OJ: luogu

题目 ID: P2670

难度:入门

标签:模拟矩阵枚举python

日期: 2026-07-15 21:22

题意

给出扫雷棋盘,* 表示地雷,? 表示非雷格。对每个非雷格,输出它周围八个方向中地雷的个数;地雷格仍输出 *

思路

先列出八个方向:

python
(-1,-1), (-1,0), ..., (1,1)

枚举每个格子:

  • 如果当前是 *,答案也是 *
  • 否则枚举八个邻格,检查是否在边界内且为 *,统计数量。

每一行用字符列表构造,最后 "".join(current) 变成输出字符串。

Python 知识

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:字符网格可按行保存为字符串列表。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/brute_force_validation.md:二维矩阵枚举常用 for row / for col 双循环。
  • 0 <= nr < n and 0 <= nc < m 是常见边界判断。
  • "\n".join(answer) 一次输出多行。

代码

python
directions = [
    (-1, -1), (-1, 0), (-1, 1),
    (0, -1),           (0, 1),
    (1, -1),  (1, 0),  (1, 1),
]

n, m = map(int, input().split())
grid = [input().strip() for _ in range(n)]
answer = []

for row in range(n):
    current = []
    for col in range(m):
        if grid[row][col] == "*":
            current.append("*")
            continue

        count = 0
        for dr, dc in directions:
            nr = row + dr
            nc = col + dc
            if 0 <= nr < n and 0 <= nc < m and grid[nr][nc] == "*":
                count += 1
        current.append(str(count))

    answer.append("".join(current))

print("\n".join(answer))
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 105;

int n, m;
char grid[MAXN][MAXN]; // 地图,'*' 表示地雷

// 8 个方向:上左、上、上右、左、右、下左、下、下右
int dr[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dc[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

// 统计 (r,c) 周围 8 格的地雷数量
int count_mine(int r, int c) {
    int cnt = 0;
    for (int d = 0; d < 8; d++) {
        int nr = r + dr[d];
        int nc = c + dc[d];
        if (nr >= 0 && nr < n && nc >= 0 && nc < m && grid[nr][nc] == '*')
            cnt++;
    }
    return cnt;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> grid[i];
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (grid[i][j] == '*')
                cout << '*';
            else
                cout << count_mine(i, j);
        }
        cout << "\n";
    }

    return 0;
}

复杂度

每个格子最多检查 8 个方向,时间复杂度是 O(nm)O(nm),空间复杂度是 O(nm)O(nm)

总结

网格邻域题先固定方向数组,再对每个格子套同一套边界判断和统计逻辑。