让我们一起来玩扫雷游戏!
给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中:
'M'代表一个 未挖出的 地雷,'E'代表一个 未挖出的 空方块,'B'代表没有相邻(上,下,左,右,和所有4个对角线)地雷的 已挖出的 空白方块,- 数字(
'1'到'8')表示有多少地雷与这块 已挖出的 方块相邻, 'X'则表示一个 已挖出的 地雷。
给你一个整数数组 click ,其中 click = [clickr, clickc] 表示在所有 未挖出的 方块('M' 或者 'E')中的下一个点击位置(clickr 是行下标,clickc 是列下标)。
根据以下规则,返回相应位置被点击后对应的盘面:
- 如果一个地雷(
'M')被挖出,游戏就结束了- 把它改为'X'。 - 如果一个 没有相邻地雷 的空方块(
'E')被挖出,修改它为('B'),并且所有和其相邻的 未挖出 方块都应该被递归地揭露。 - 如果一个 至少与一个地雷相邻 的空方块(
'E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。 - 如果在此次点击中,若无更多方块可被揭露,则返回盘面。
示例 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.lengthn == board[i].length1 <= m, n <= 50board[i][j]为'M'、'E'、'B'或数字'1'到'8'中的一个click.length == 20 <= clickr < m0 <= clickc < nboard[clickr][clickc]为'M'或'E'
解题思路:深度优先遍历 + 模拟
这道题其实难在规则看起来比较杂,但是一旦规则看懂了,其实就是一个模拟题,只不过在模拟题的基础上需要有深度优先遍历操作罢了!这里就不细讲规则了,慢慢读都能读懂!
和前面题目的区别在于这道题因为走的是还没展开的方块,此时就需要根据它外围一圈,包括左上角、右上角、左下角、右下角的方块也要判断,判断有多少个地雷,如果有地雷的话则将当前方块设为地雷的数量(注意是数字字符,不是整型数字),没有的话则可以向外围一圈进行递归处理!
我们前面对于外围一圈只有四个方块来说可以写四个 dfs() 语句,但是这里因为有八个方块需要判断,所以写八个就太麻烦了,所以这里考虑用两个数组 row 和 col,分别代表外围一圈的一对坐标,然后我们只需要遍历数组来进行坐标的累加即可,这样子方便很多!
剩下的其实就是根据规则来走,没什么好说的,具体参考代码:
class Solution {
private:
int row[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };
int col[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };
int m, n;
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
m = board.size(), n = board[0].size();
int x = click[0], y = click[1];
// 如果点击的是地雷直接就炸了
if(board[x][y] == 'M')
{
board[x][y] = 'X';
return board;
}
dfs(board, x, y);
return board;
}
void dfs(vector<vector<char>>& board, int x, int y)
{
// 先统计周围地雷的个数
int count = 0;
for(int i = 0; i < 8; ++i)
{
int tmpx = x + row[i];
int tmpy = y + col[i];
if(tmpx >= 0 && tmpx < m && tmpy >= 0 && tmpy < n && board[tmpx][tmpy] == 'M')
count++;
}
// 有地雷的话,设置为地雷个数然后返回即可
if(count > 0)
{
board[x][y] = count + '0';
return;
}
// 没有地雷的话,则设置为B,然后向还没展开的方块进行递归
board[x][y] = 'B';
for(int i = 0; i < 8; ++i)
{
int tmpx = x + row[i];
int tmpy = y + col[i];
if(tmpx >= 0 && tmpx < m && tmpy >= 0 && tmpy < n && board[tmpx][tmpy] == 'E')
dfs(board, tmpx, tmpy);
}
}
};