529. 扫雷游戏
已解答
中等
相关标签
相关企业
让我们一起来玩扫雷游戏!
给你一个大小为 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.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'
这是一道leetcode上面的题目,题目本身不难,只需要改变一次状态就行了。改变状态中需要确定点击的是什么内容,如果是空白则需要递归找到所有的空白。
先用AI先了一个python版本:
class Solution:
def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)] # 相邻方向
def count_mines(r, c):
count = 0
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < len(board) and 0 <= nc < len(board[0]) and board[nr][nc] == 'M':
count += 1
return count
def reveal(r, c):
if board[r][c] == 'E':
mines_count = count_mines(r, c)
if mines_count == 0:
board[r][c] = 'B'
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < len(board) and 0 <= nc < len(board[0]):
reveal(nr, nc)
else:
board[r][c] = str(mines_count)
click_r, click_c = click
if board[click_r][click_c] == 'M':
board[click_r][click_c] = 'X'
else:
reveal(click_r, click_c)
return board
python果然更加现代,函数里面可以定义函数。想着将python改写为C++实现,C++虽然无法在函数内部实现函数,但是有lamda表达式,于是写出来下面的版本:
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
int directions[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 相邻方向
auto countMines = [&](int r, int c) -> int {
int count = 0;
for (auto& dir : directions) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size() && board[nr][nc] == 'M') {
++count;
}
}
return count;
};
auto revealFunc = [&](int r, int c) {
if (board[r][c] == 'E') {
int minesCount = countMines(r, c);
if (minesCount == 0) {
board[r][c] = 'B';
for (auto& dir : directions) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size()) {
revealFunc(nr, nc);
}
}
} else {
board[r][c] = '0' + minesCount;
}
}
};
int click_r = click[0], click_c = click[1];
if (board[click_r][click_c] == 'M') {
board[click_r][click_c] = 'X';
} else {
revealFunc(click_r, click_c);
}
return board;
}
};
啊,编译报错了。
error: variable 'revealFunc' declared with deduced type 'auto' cannot appear in its own initializer
23 | revealFunc(nr, nc);
| ^
1 error generated.
还是不行,不能递归调用。
在C++中,Lambda表达式不能直接递归调用自身,因为它的类型是在声明时确定的,而在递归调用时,Lambda表达式的类型还没有完全确定。
为了解决这个问题,你可以将Lambda表达式存储在一个std::function对象中,这样就可以在递归调用中使用它了。std::function是一个可以存储任何可调用对象的通用容器,只要其签名与std::function的模板参数匹配即可。
正确版本:
class Solution {
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
int directions[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 相邻方向
auto countMines = [&](int r, int c) -> int {
int count = 0;
for (auto& dir : directions) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size() && board[nr][nc] == 'M') {
++count;
}
}
return count;
};
std::function<void(int, int)> revealFunc;
revealFunc = [&](int r, int c) {
if (board[r][c] == 'E') {
int minesCount = countMines(r, c);
if (minesCount == 0) {
board[r][c] = 'B';
for (auto& dir : directions) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < board.size() && nc >= 0 && nc < board[0].size()) {
revealFunc(nr, nc);
}
}
} else {
board[r][c] = '0' + minesCount;
}
}
};
int click_r = click[0], click_c = click[1];
if (board[click_r][click_c] == 'M') {
board[click_r][click_c] = 'X';
} else {
revealFunc(click_r, click_c);
}
return board;
}
};
执行用时分布
10ms
击败97.79%使用 C++ 的用户
消耗内存分布
15.11MB
击败15.20%使用 C++ 的用户
C++感觉需要重新学习了。。。