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. shell命令总结一

    简述:这篇总结是在360企业安全实习第一周学到的. Linux中的 2>&1 .if文件命令 .tr .$0等相关参数含义的用法 1. 2>&1 command>/d ...

  2. Linux下的/etc/hosts文件

    在Unix系统下面有一个/etc/hosts文件,在我的Mac上,这个文件的内容如下: ## # Host Database # # localhost is used to configure th ...

  3. React Native 轻松集成统计功能(iOS 篇)

    最近产品让我加上数据统计功能,刚好极光官方支持数据统计 支持了 React Native 版本 第一步 安装: 在你的项目路径下执行命令: npm install janalytics-react-n ...

  4. 听翁恺老师mooc笔记(16)--程序设计与C语言

    问题1:计算机遍布生活的各个方面,若你需要一个功能可以下载APP,我们需要的大部分功能都可以找到对应的APP,如果没有可以自己写一个软件,但是很少人需要这么做,那么我们为什么学习计算机编程语言? 学习 ...

  5. Alpha冲刺No.9

    一.站立式会议 继续解决真实手机中的问题,如果不能解决,请教助教学姐 数据库备忘录的获取和上传 细化界面设计 二.项目实际进展 用一种奇怪的方式解决了真实手机中的问题,在总结里细说. 完成数据库备忘录 ...

  6. 团队作业7——第二次项目冲刺(Beta版本计划及安排)

     Beta版本冲刺       需要改进完善的功能 1.寻找BUG.并解决问题 2.界面的优化 下一阶段新增的功能' 1.个人信息头像上传 2.头像裁剪功能 需要改进的团队分工 1.之前产品的主要工作 ...

  7. C语言——第四次作业

    题目 题目一:计算分段函数 1.实验代码 #include <stdio.h> int main() { double x,y; scanf("%lf",&x) ...

  8. string类的简洁版实现

    说是原创,差不多算是转载了,我也是看了好多大牛的写法,大牛的建议,自己加一总结,形成代码: 实现一个简洁版的string类,我觉得,下面的也够了:另外需要参见另外的写法: http://blog.cs ...

  9. 【技巧】Java工程中的Debug信息分级输出接口

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  10. 裸辞两个月,海投一个月,从Android转战Web前端的求职之路

    前言 看到这个标题的童鞋,可能会产生两种想法: 想法一:这篇文章是标题党 想法二:Android开发越来越不景气了吗?前端越来越火了吗? 我一向不喜欢标题党,标题中的内容是我的亲身经历.我是2016年 ...