[BFS]529. Minesweeper

来源:互联网 发布:招淘宝兼职是真的吗 编辑:程序博客网 时间:2024/04/30 00:53

【记又一次阵亡在“==”上的惨痛经历微笑

题目:

Let's play the minesweeper game (Wikipedia,online game)!

You are given a 2D char matrix representing the game board. 'M' represents anunrevealed 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 thisrevealed 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 adjacentunrevealed 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:

题目分析:

1、根据题目,要求是根据给出的矩阵(包含地雷标记M,和未点开标记E)和输入的点击位置,按要求得出点击后的矩阵并返回。

2、对于点击后的显示规则,大概有三类:①如果是雷,直接标记为X并结束;②如果不是雷且周围有雷,那么将这一格标记为周围雷的数量;③如果不是雷且周围也没有雷,那么就标记为B并递归地继续点开周围标记为E的格子。

3、很容易发现这道题的解决是利用递归的方法,且根据递归的条件容易发现所有的B应该都是连通的,不然没法被递归打开。

4、对于此题的解决算法。考虑先检验这个格子的属于2中的哪个类型,即首先检验是否为M,其次检验是否周围有M,如果都不是则为B且开始递归。至于将递归放在最后的原因,是为了避免在某个格子周围有雷的时候仍然要打开其它E的情况。

5、具体在代码实现中有两个问题。①检验顺序。解决方法前面已经介绍了;②边界检测。由于中间的格子和矩阵边界的格子要打开(检测)的格子(如果要打开)情况不同,那么如果利用循环来遍历周围的八个格子,就必须检测行列参数是否越界。

代码实现:

void func(vector<vector<char>>& board, int row, int col){if(board[row][col] == 'M') {board[row][col] = 'X';return;}else{int count = 0;bool checkM = 0;int i = row - 1;int j = col - 1;if(i < 0) i = 0;if(j < 0) j = 0;for(; i <= row + 1; i++){if(i == board.size())break; for(int j = col - 1; j <= col + 1; j++){if(j == board[0].size())break;if(i == row && j == col)continue;if(board[i][j] == 'M'){checkM = 1;count ++;}}}if(checkM == 1){board[row][col] = count + '0';return;}board[row][col] = 'B';int i = row - 1;int j = col - 1;if(i < 0) i = 0;if(j < 0) j = 0;for(; i <= row + 1; i++){if(i == board.size())break; for(int j = col - 1; j <= col + 1; j++){if(j == board[0].size())break;if(i == row && j == col)continue;if(board[i][j] == 'E')func(board, i, j);}}}}class Solution {public:    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {        func(board, click[0], click[1]);return board;    }};

总结与经验:

1、在开始编写代码之前一定要对整个题目要求有清晰明确的认识。我在刚开始完成这道题的时候并没有注意到如果某个格子周围有雷它就不会去打开周围没有被打开的格子,这导致我在考虑递归的时候是把标记B和数字的格子统一起来的,这就导致发现了问题后要纠正代码时工作量很大;

2、要学会利用错误的答案分析问题所在。在最后几次提交代码测试的时候发现标记B能正常递归,但是本该标记数字的格子却没有变化,然而结果却显示程序在运行途中是知道这个格子应该被标记数字的(因为程序中设置了bool变量来检测)。但是为什么既然检测出来了却并没有任何操作呢?这个问题困扰了我很久很久很久.....甚至最后我都放弃debug了。好在睡了一觉后爬起来继续看了看代码,突然发现检测出周围有M后对本格子的赋值操作是“==”(本来该是“=”)........呵呵,又是熟悉的情景。






0 0
原创粉丝点击