[LeetCode] Minesweeper 扫雷游戏
Let's play the minesweeper game (Wikipedia, online game)!
You are given a 2D char matrix representing the game board. 'M' represents an unrevealed mine, 'E' represents an unrevealed empty square, 'B' represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit ('1' to '8') represents how many mines are adjacent to this revealed square, and finally 'X' represents a revealed mine.
Now given the next click position (row and column indices) among all the unrevealed squares ('M' or 'E'), return the board after revealing this position according to the following rules:
- If a mine ('M') is revealed, then the game is over - change it to 'X'.
- If an empty square ('E') with no adjacent mines is revealed, then change it to revealed blank ('B') and all of its adjacent unrevealed squares should be revealed recursively.
- If an empty square ('E') with at least one adjacent mine is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines.
- Return the board when no more squares will be revealed.
Example 1:
Input: [['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'M', 'E', 'E'],
['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'E', 'E', 'E']] Click : [3,0] Output: [['B', '1', 'E', '1', 'B'],
['B', '1', 'M', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']] Explanation:

Example 2:
Input: [['B', '1', 'E', '1', 'B'],
['B', '1', 'M', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']] Click : [1,2] Output: [['B', '1', 'E', '1', 'B'],
['B', '1', 'X', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']] Explanation:

Note:
- The range of the input matrix's height and width is [1,50].
- The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square.
- The input board won't be a stage when game is over (some mines have been revealed).
- For simplicity, not mentioned rules should be ignored in this problem. For example, you don't need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.
这道题就是经典的扫雷游戏啦,经典到不能再经典,从Win98开始,附件中始终存在的游戏,和纸牌、红心大战、空当接龙一起称为四大天王,曾经消耗了博主太多的时间。小时侯一直不太会玩扫雷,就是瞎点,完全不根据数字分析,每次点几下就炸了,就觉得这个游戏好无聊。后来长大了一些,慢慢的理解了游戏的玩法,才发现这个游戏果然很经典,就像破解数学难题一样,充满了挑战与乐趣。花样百出的LeetCode这次把扫雷出成题,让博主借机回忆了一把小时侯,不错不错,那么来做题吧。题目中图文并茂,相信就算是没玩过扫雷的也能弄懂了,而且规则也说的比较详尽了,那么我们相对应的做法也就明了了。对于当前需要点击的点,我们先判断是不是雷,是的话直接标记X返回即可。如果不是的话,我们就数该点周围的雷个数,如果周围有雷,则当前点变为雷的个数并返回。如果没有的话,我们再对周围所有的点调用递归函数再点击即可。参见代码如下:
解法一:
class Solution {
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
if (board.empty() || board[].empty()) return {};
int m = board.size(), n = board[].size(), row = click[], col = click[], cnt = ;
if (board[row][col] == 'M') {
board[row][col] = 'X';
} else {
for (int i = -; i < ; ++i) {
for (int j = -; j < ; ++j) {
int x = row + i, y = col + j;
if (x < || x >= m || y < || y >= n) continue;
if (board[x][y] == 'M') ++cnt;
}
}
if (cnt > ) {
board[row][col] = cnt + '';
} else {
board[row][col] = 'B';
for (int i = -; i < ; ++i) {
for (int j = -; j < ; ++j) {
int x = row + i, y = col + j;
if (x < || x >= m || y < || y >= n) continue;
if (board[x][y] == 'E') {
vector<int> nextPos{x, y};
updateBoard(board, nextPos);
}
}
}
}
}
return board;
}
};
下面这种解法跟上面的解法思路基本一样,写法更简洁了一些。可以看出上面的解法中的那两个for循环出现了两次,这样显得代码比较冗余,一般来说对于重复代码是要抽离成函数的,但那样还要多加个函数,也麻烦。我们可以根据第一次找周围雷个数的时候,若此时cnt个数为0并且标识是E的位置记录下来,那么如果最后雷个数确实为0了的话,我们直接遍历我们保存下来为E的位置调用递归函数即可,就不用再写两个for循环了,参见代码如下:
解法二:
class Solution {
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
if (board.empty() || board[].empty()) return {};
int m = board.size(), n = board[].size(), row = click[], col = click[], cnt = ;
if (board[row][col] == 'M') {
board[row][col] = 'X';
} else {
vector<vector<int>> neighbors;
for (int i = -; i < ; ++i) {
for (int j = -; j < ; ++j) {
int x = row + i, y = col + j;
if (x < || x >= m || y < || y >= n) continue;
if (board[x][y] == 'M') ++cnt;
else if (cnt == && board[x][y] == 'E') neighbors.push_back({x, y});
}
}
if (cnt > ) {
board[row][col] = cnt + '';
} else {
for (auto a : neighbors) {
board[a[]][a[]] = 'B';
updateBoard(board, a);
}
}
}
return board;
}
};
下面这种方法是上面方法的迭代写法,用queue来存储之后要遍历的位置,这样就不用递归调用函数了,参见代码如下:
解法三:
class Solution {
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
if (board.empty() || board[].empty()) return {};
int m = board.size(), n = board[].size();
queue<pair<int, int>> q({{click[], click[]}});
while (!q.empty()) {
int row = q.front().first, col = q.front().second, cnt = ; q.pop();
vector<pair<int, int>> neighbors;
if (board[row][col] == 'M') board[row][col] = 'X';
else {
for (int i = -; i < ; ++i) {
for (int j = -; j < ; ++j) {
int x = row + i, y = col + j;
if (x < || x >= m || y < || y >= n) continue;
if (board[x][y] == 'M') ++cnt;
else if (cnt == && board[x][y] == 'E') neighbors.push_back({x, y});
}
}
}
if (cnt > ) board[row][col] = cnt + '';
else {
for (auto a : neighbors) {
board[a.first][a.second] = 'B';
q.push(a);
}
}
}
return board;
}
};
参考资料:
https://discuss.leetcode.com/topic/80844/c-16-lines-bfs/2
https://discuss.leetcode.com/topic/80802/java-solution-dfs-bfs
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Minesweeper 扫雷游戏的更多相关文章
- Leetcode 529.扫雷游戏
扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖 ...
- Java实现 LeetCode 529 扫雷游戏(DFS)
529. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线) ...
- 529 Minesweeper 扫雷游戏
详见:https://leetcode.com/problems/minesweeper/description/ C++: class Solution { public: vector<ve ...
- 529. Minesweeper扫雷游戏
[抄题]: Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix repre ...
- Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)
Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...
- [Swift]LeetCode529. 扫雷游戏 | Minesweeper
Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...
- [LeetCode] 529. Minesweeper 扫雷
Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...
- Java练习(模拟扫雷游戏)
要为扫雷游戏布置地雷,扫雷游戏的扫雷面板可以用二维int数组表示.如某位置为地雷,则该位置用数字-1表示, 如该位置不是地雷,则暂时用数字0表示. 编写程序完成在该二维数组中随机布雷的操作,程序读入3 ...
- 基于jQuery经典扫雷游戏源码
分享一款基于jQuery经典扫雷游戏源码.这是一款网页版扫雷小游戏特效代码下载.效果图如下: 在线预览 源码下载 实现的代码. html代码: <center> <h1>j ...
随机推荐
- python 信号处理
linux开发中,通常会在进程中设置专门的信号处理方法,比如经常使用的CTRL+C,KILL等信号.如果你熟悉liunx编程,那么python等信号处理方法对你来说就很简单,下面的内容将主要介绍pyt ...
- 201621123050 《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...
- django + nginx + uwsgi + websocket
最近使用django框架做了一个简单的聊天机器人demo, 开发的过程中使用了django自带的websocket模块,当使用django框架自带的wsgi服务去启动的话,没有什么问题.如果要使用uw ...
- hp MSA50 5盘RAID5重建为4盘RAID5怎么恢复数据
[用户单位] XX省电视台[数据恢复故障描述] 一台HP 服务器,挂接一台HP MSA50磁盘阵列,内接5块1TB硬盘,原先结构为RAID5. 使用一段时间后,其中一块硬盘掉线,因RAID5支持一块硬 ...
- c++ 中lambda
C++ 11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作. 1.Lambda表达式完整的声明格式如下: [capture list] (params list) mutable ...
- 02-移动端开发教程-CSS3新特性(中)
1. 新的背景 背景在CSS3中也得到很大程度的增强,比如背景图片尺寸.背景裁切区域.背景定位参照点.多重背景等. 1.1 background-size设置背景图片的尺寸 cover会自动调整缩放比 ...
- Vue 2.0基础语法:系统指令
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. Vue初体验 新建一个空的项目,引入vue.js文件.写如下代码: &l ...
- .NET Core/.NET之Stream简介
之前写了一篇C#装饰模式的文章提到了.NET Core的Stream, 所以这里尽量把Stream介绍全点. (都是书上的内容) .NET Core/.NET的Streams 首先需要知道, Syst ...
- C# 使用 ffmpeg 进行音频转码
先放一下 ffmpeg 的官方文档以及下载地址: 官方文档:http://ffmpeg.org/ffmpeg.html 下载地址:http://ffmpeg.org/download.html 用 f ...
- 微信小程序如何动态增删class类名
简述 由于微信小程序开发不同于以往的普通web开发, 因此无法通过js获取wxml文件的dom结构, 因此从js上直接添加一个类名应该不可能了. 可是我们可以通过微信小程序数据绑定以及view标签的& ...