529. 扫雷游戏(BFS)

529. 扫雷游戏

让我们一起来玩扫雷游戏!

给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中:

  • 'M' 代表一个 未挖出的 地雷,
  • 'E' 代表一个 未挖出的 空方块,
  • 'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的 已挖出的 空白方块,
  • 数字('1' 到 '8')表示有多少地雷与这块 已挖出的 方块相邻,
  • 'X' 则表示一个 已挖出的 地雷。

给你一个整数数组 click ,其中 click = [clickr, clickc] 表示在所有 未挖出的 方块('M' 或者 'E')中的下一个点击位置(clickr 是行下标,clickc 是列下标)。

根据以下规则,返回相应位置被点击后对应的盘面:

  1. 如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X' 。
  2. 如果一个 没有相邻地雷 的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的 未挖出 方块都应该被递归地揭露。
  3. 如果一个 至少与一个地雷相邻 的空方块('E')被挖出,修改它为数字('1' 到 '8' ),表示相邻地雷的数量。
  4. 如果在此次点击中,若无更多方块可被揭露,则返回盘面。

 

示例 1:

输入:board = [["E","E","E","E","E"],["E","E","M","E","E"],["E","E","E","E","E"],["E","E","E","E","E"]], click = [3,0]
输出:[["B","1","E","1","B"],["B","1","M","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]]

示例 2:

输入:board = [["B","1","E","1","B"],["B","1","M","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]], click = [1,2]
输出:[["B","1","E","1","B"],["B","1","X","1","B"],["B","1","1","1","B"],["B","B","B","B","B"]]

 

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 50
  • board[i][j] 为 'M''E''B' 或数字 '1' 到 '8' 中的一个
  • click.length == 2
  • 0 <= clickr < m
  • 0 <= clickc < n
  • board[clickr][clickc] 为 'M' 或 'E'
 1 class Solution {
 2 public:
 3     // 图中8个方向,顺时针:正上、右上、右、右下、正下、左下、左、左上
 4     vector<vector<int>> g_direction = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
 5     // 是否在游戏界面范围内
 6     bool isInArea(int row, int col, int x, int y) {
 7         return (x >= 0 && x < row && y >= 0 && y < col);
 8     }
 9     void bfs(vector<vector<char>>& board, int x, int y) {
10         queue<pair<int, int>> q;
11         int row = board.size();
12         int col = board[0].size();
13         vector<vector<bool>> visited(row, vector<bool>(col, 0));
14         q.push(make_pair(x, y));
15         visited[x][y] = true;
16         while (!q.empty()) {
17             auto pos = q.front();
18             q.pop();
19             int cnt = 0;
20             int x = pos.first;
21             int y = pos.second;
22             for (auto &direction : g_direction) {
23                 int nextX = x + direction[0];
24                 int nextY = y + direction[1];
25                 if (!isInArea(row, col, nextX, nextY)) {
26                     continue;
27                 }
28                 if (board[nextX][nextY] == 'M') {
29                     cnt++;
30                 }
31             }
32             if (cnt > 0) {
33                 // 规则 3
34                 board[x][y] = cnt + '0';
35             } else {
36                 // 规则 2
37                 board[x][y] = 'B';
38                 for (auto &direction : g_direction) {
39                     int nextX = x + direction[0];
40                     int nextY = y + direction[1];
41                     // 这里不需要在存在 B 的时候继续扩展,因为 B 之前被点击的时候已经被扩展过了
42                     if (!isInArea(row, col, nextX, nextY) || board[nextX][nextY] != 'E' || visited[nextX][nextY]) {
43                         continue;
44                     }
45                     q.push(make_pair(nextX, nextY));
46                     visited[nextX][nextY] = true;
47                 }
48             }
49         }
50     }
51 
52     vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
53         int x = click[0], y = click[1];
54         if (board[x][y] == 'M') {
55             // 规则 1
56             board[x][y] = 'X';
57         } else {
58             bfs(board, x, y);
59         }
60         return board;
61     }
62 };
posted @ 2022-05-22 02:19  跳动的休止符  阅读(38)  评论(0)    收藏  举报