扫雷游戏




方法一:深度优先搜索
- 如果当前点击的是地雷,直接将其修改为$X$即可。
- 如果当前点击未挖出的空方块,那么就先统计该方块周围的地雷数,如果地雷数不为0,那么就将当前空方块改为数字,否则就将该空方块改为$B$,之后继续搜索递归处理周围为$E$的空方块。搜索过程可以使用深度优先搜索。
| 1 | class Solution { | 
| 2 |     int[] dx = {-1,1,0,0,-1,-1,1,1}; | 
| 3 |     int[] dy = {0,0,1,-1,1,-1,1,-1}; | 
| 4 |     int m, n; | 
| 5 |     public char[][] updateBoard(char[][] board, int[] click) { | 
| 6 |         if(board[click[0]][click[1]] == 'M'){ | 
| 7 |             board[click[0]][click[1]] = 'X'; | 
| 8 |             return board; | 
| 9 |         }else{ | 
| 10 |             m = board.length; | 
| 11 |             n = board[0].length; | 
| 12 |             dfs(board, click[0], click[1]); | 
| 13 |         } | 
| 14 |         return board; | 
| 15 |     } | 
| 16 | |
| 17 |     public void dfs(char[][] board, int x, int y){ | 
| 18 |         int count = 0; | 
| 19 |         for(int i=0; i<8; i++){ | 
| 20 |             int mx = x + dx[i]; | 
| 21 |             int my = y + dy[i]; | 
| 22 |             if(mx>=0 && mx<m && my>=0 && my<n && board[mx][my]=='M'){ | 
| 23 |                 count++; | 
| 24 |             } | 
| 25 |         } | 
| 26 |         if(count > 0){ | 
| 27 |             board[x][y] = (char)(count + '0'); | 
| 28 |         }else{ | 
| 29 |             board[x][y] = 'B'; | 
| 30 |             for(int i=0; i<8; i++){ | 
| 31 |                 int mx = x + dx[i]; | 
| 32 |                 int my = y + dy[i]; | 
| 33 |                 if(mx>=0 && mx<m && my>=0 && my<n && board[mx][my]=='E'){ | 
| 34 |                     dfs(board, mx, my); | 
| 35 |                 } | 
| 36 |             } | 
| 37 |         } | 
| 38 |     } | 
| 39 | } | 
复杂度分析:
- 时间复杂度:$O(mn)$。
- 空间复杂度:$O(mn)$。
方法二:广度优先搜索
上面第二种情况的搜索可以用广度优先搜索,但是需要另外一个visited数组来记录访问过的方块避免重复访问。
| 1 | class Solution { | 
| 2 |     int[] dx = {-1,1,0,0,-1,-1,1,1}; | 
| 3 |     int[] dy = {0,0,1,-1,1,-1,1,-1}; | 
| 4 |     boolean[][] visited; | 
| 5 |     public char[][] updateBoard(char[][] board, int[] click) { | 
| 6 |         if(board[click[0]][click[1]] == 'M'){ | 
| 7 |             board[click[0]][click[1]] = 'X'; | 
| 8 |             return board; | 
| 9 |         } | 
| 10 |         int m = board.length; | 
| 11 |         int n = board[0].length; | 
| 12 |         visited = new boolean[m][n]; | 
| 13 |         Queue<int[]> queue = new LinkedList<int[]>(); | 
| 14 |         queue.offer(click); | 
| 15 |         visited[click[0]][click[1]] = true; | 
| 16 |         while(!queue.isEmpty()){ | 
| 17 |             int[] cur = queue.poll(); | 
| 18 |             int x = cur[0]; | 
| 19 |             int y = cur[1]; | 
| 20 |             if(board[x][y] == 'M'){ | 
| 21 |                 continue; | 
| 22 |             } | 
| 23 |             int count = 0; | 
| 24 |             for(int i=0; i<8; i++){ | 
| 25 |                 int mx = x + dx[i]; | 
| 26 |                 int my = y + dy[i]; | 
| 27 |                 if(mx<m && mx>=0 && my<n && my>=0 && board[mx][my]=='M'){ | 
| 28 |                     count++; | 
| 29 |                 } | 
| 30 |             } | 
| 31 |             if(count == 0){ | 
| 32 |                 board[x][y] = 'B'; | 
| 33 |                 for(int i=0; i<8; i++){ | 
| 34 |                     int mx = x + dx[i]; | 
| 35 |                     int my = y + dy[i]; | 
| 36 |                     if(mx<m && mx>=0 && my<n && my>=0 && !visited[mx][my]){ | 
| 37 |                         queue.offer(new int[]{mx,my}); | 
| 38 |                         visited[mx][my] = true; | 
| 39 |                     } | 
| 40 |                 } | 
| 41 |             }else{ | 
| 42 |                 board[x][y] = (char)(count+'0'); | 
| 43 |             } | 
| 44 |         } | 
| 45 |         return board; | 
| 46 | |
| 47 |     } | 
| 48 | } | 
复杂度分析:
- 时间复杂度:$O(mn)$。
- 空间复杂度:$O(mn)$。