#include <stdio.h>  // 引入标准输入输出库

// 计算某个格子周围的地雷数量
int count_mines(char grid[][100], int n, int m, int i, int j) {
    // 定义8个方向(上,下,左,右,左上,右上,左下,右下)
    int directions[8][2] = {
        {-1, 0}, {1, 0}, {0, -1}, {0, 1},  // 上,下,左,右
        {-1, -1}, {-1, 1}, {1, -1}, {1, 1}  // 左上,右上,左下,右下
    };
    
    int count = 0;  // 初始化地雷计数器
    // 遍历8个方向
    for (int k = 0; k < 8; k++) {
        // 计算当前方向的相邻格子坐标
        int ni = i + directions[k][0];
        int nj = j + directions[k][1];
        
        // 检查邻居是否在范围内,并且是否是地雷
        if (ni >= 0 && ni < n && nj >= 0 && nj < m && grid[ni][nj] == '*') {
            count++;  // 如果是地雷,计数加1
        }
    }
    return count;  // 返回周围的地雷数量
}

int main() {
    int n, m;  // n是雷区的行数,m是雷区的列数
    char grid[100][100];  // 存储雷区的二维数组(最大100x100)

    // 输入雷区的行数和列数
    scanf("%d %d", &n, &m);

    // 输入雷区的布局
    for (int i = 0; i < n; i++) {
        // 读取每一行的雷区布局,去掉尾部换行符
        scanf("%s", grid[i]);
    }

    // 处理雷区并输出结果
    for (int i = 0; i < n; i++) {  // 遍历每一行
        for (int j = 0; j < m; j++) {  // 遍历每一列
            // 如果当前格子是地雷,输出'*'
            if (grid[i][j] == '*') {
                printf("*");
            } else {
                // 如果当前格子不是地雷,调用count_mines函数计算周围地雷数
                int mines_count = count_mines(grid, n, m, i, j);
                printf("%d", mines_count);  // 输出周围的地雷数
            }
        }
        printf("\n");  // 输出完一行后换行
    }

    return 0;  // 程序正常结束
}

对于每个方向,directions[k][0]和directions[k][1]代表该方向的行和列偏移量。

  • k = 0:directions[0] = {-1, 0},表示上方的格子(i - 1, j)。
  • k = 1:directions[1] = {1, 0},表示下方的格子(i + 1, j)。
  • k = 2:directions[2] = {0, -1},表示左方的格子(i, j - 1)。
  • k = 3:directions[3] = {0, 1},表示右方的格子(i, j + 1)。
  • k = 4:directions[4] = {-1, -1},表示左上方的格子(i - 1, j - 1)。
  • k = 5:directions[5] = {-1, 1},表示右上方的格子(i - 1, j + 1)。
  • k = 6:directions[6] = {1, -1},表示左下方的格子(i + 1, j - 1)。
  • k = 7:directions[7] = {1, 1},表示右下方的格子(i + 1, j + 1)。

总结:

这段代码通过k遍历所有可能的 8 个方向,使用directions[k][0]和directions[k][1]来计算当前格子周围相邻格子的坐标。这样就能检查当前格子周围的地雷数量或者执行其他操作。