Let's play the minesweeper game (Wikipediaonline 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:

  1. If a mine ('M') is revealed, then the game is over - change it to 'X'.
  2. 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.
  3. 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.
  4. 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:

  1. The range of the input matrix's height and width is [1,50].
  2. The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square.
  3. The input board won't be a stage when game is over (some mines have been revealed).
  4. 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 扫雷游戏的更多相关文章

  1. Leetcode 529.扫雷游戏

    扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖 ...

  2. Java实现 LeetCode 529 扫雷游戏(DFS)

    529. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线) ...

  3. 529 Minesweeper 扫雷游戏

    详见:https://leetcode.com/problems/minesweeper/description/ C++: class Solution { public: vector<ve ...

  4. 529. Minesweeper扫雷游戏

    [抄题]: Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix repre ...

  5. Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)

    Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...

  6. [Swift]LeetCode529. 扫雷游戏 | Minesweeper

    Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...

  7. [LeetCode] 529. Minesweeper 扫雷

    Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...

  8. Java练习(模拟扫雷游戏)

    要为扫雷游戏布置地雷,扫雷游戏的扫雷面板可以用二维int数组表示.如某位置为地雷,则该位置用数字-1表示, 如该位置不是地雷,则暂时用数字0表示. 编写程序完成在该二维数组中随机布雷的操作,程序读入3 ...

  9. 基于jQuery经典扫雷游戏源码

    分享一款基于jQuery经典扫雷游戏源码.这是一款网页版扫雷小游戏特效代码下载.效果图如下: 在线预览   源码下载 实现的代码. html代码: <center> <h1>j ...

随机推荐

  1. 程序员的入门 简单的编程HelloWord

    那么在上一章章节 http://www.cnblogs.com/Goraidh/p/8674329.html 我们简单的俩了解了一下什么是java和配置编写java的环境,本章呢我们学习如何编写一个简 ...

  2. 关于c++停止工作

    出现这样情况有两种原因 : 1未初始化 2用scanf未用符号& 3当0做分母时

  3. alpha冲刺第七天

    一.合照 二.项目燃尽图 三.项目进展 问答界面问答内容呈现 设置里的帐号设置呈现 能爬取教务处网站的内容保存到本地数据库 四.明日规划 继续完善各个内容的界面呈现 查找关于如何自动更新爬取内容 搜索 ...

  4. 网络1711班 C语言第四次作业批改总结

    网络1711班 C语言第四次作业批改总结 助教有话说(写在前面) 近来,有同学跟老师和助教们反映:博客作业太多太麻烦,而且对编程能力提高似乎没什么帮助?在这里我要谈一谈我的感想. 博客作业的意义? 首 ...

  5. 敏捷开发冲刺--day3

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  6. 项目Alpha冲刺Day12

    一.会议照片 二.项目进展 1.今日安排 修复全局的日期转换问题,完成用户所有相关的模块,对全局的异常处理做优化.其他模块进行一部分实现. 2.问题困难 全局异常处理后发现没有进行按照链进行下去,造成 ...

  7. 高校征信系统项目Postmortem结果

    设想和目标 1 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件需要解决的问题是当前高校学生征信系统建设薄弱的问题,我们试图建立一个征信系统,在完成之后推 ...

  8. JUnit单元测试遇到的问题及解决思路

    JUnit是Java单元测试框架,我们在对开发的系统进行单元测试的时候,也遇到了如何测试多个测试用例的问题.  背景:我们的所有测试用例都保存在Excel文件中,该文件包含测试用例和预期输出.我们希望 ...

  9. RESTful三问

    我觉得学习一个技术,其实就是要弄明白三件事情:是什么(what),为什么(why),怎么用(how).正是所谓的三W方法. 所以打算总结一个"三问"系列.为了自己学习,也分享给别人 ...

  10. NYOJ 炫舞家st

    #include <iostream>#include <cstring>#include <algorithm>using namespace std; cons ...