幅優先探索(BFS)テーマ別のLeetcode -529。マインスイーパ(マインスイーパ)
BFS詳細なエントリ:幅優先探索(BFS)テーマ別-429トラバーサル順序N-ツリー(N進ツリー上位のオーダートラバーサルのLeetcode )。
のは、マインスイーパをプレイしてみましょう!
2次元マトリックスを考えるには、ゲームボードの文字を表します。「M」非掘削鉱山を表す「E」は掘削非空の正方形を示し、「B」は(右、左、下、上方、斜めすべての4つ)が隣接することを示していないが鉱山を有しますデジタル、空白のボックスの外に掘ら(「8」から「1」)は、多くの鉱山がこの隣人と箱から出して掘られているかを示す、「X」地雷が掘り起こされていることを示しています。
全てではなく、今、次のルール、クリックパネルに対応するそれぞれの戻り位置に応じてクリック位置(行と列のインデックス)で掘削ボックス(「M」または「E」)、与えられました:
- 鉱山(「M」)が掘り起こされた場合、ゲームオーバーです - 「X」に変更します。
- 隣接鉱山空の正方形(「E」)が出土した場合、それは(「B」)を修飾、及びその隣接ブロックの全て、再帰的に開示されるべきであるれます。
- 少なくとも一つの隣接する白四角(「E」)と地雷が掘削されている場合、デジタルに変更し(「1」から「8」)、隣接する地雷の数を表します。
- あなたは、より多くのブロックが存在しないことが明らかにすることができる。この上でクリックすると、パネルが返されます。
例1:
入力: [ 'E'、 'E'、 'E'、 'E'、 'E']、 [ 'E'、 'E'、 'M'、 'E'、 'E']、 [「E '' E '' E '' E '' E ']、 [' E '' E '' E '' E '' E「]] をクリックします:[3,0] 出力: [ 'B'、 '1' 、 'E'、' 1' 、 'B']、 [ 'B'、 '1' 、 'M'、' 1' 、 'B']、 [ 'B'、 '1' 、' 1' 、 'B']、」1' [ 'B'、 'B'、 'B'、 'B'、 'B'] 説明:
例2:
入力: [ 'B'、 'E'、 'B']、 '1' ' 1' [ 'B'、 'M'、 'B']、 '1' ' 1' [「B 。。。 ' '1'、 '1'、 '1'、' B ']、 [' B '' B '' B '' B '' B「] をクリック:[1,2] 出力: [ 'B'、 '1' 、 'E'、' 1' 、 'B']、 [ 'B'、 '1' 、 'X-'、' 1' 、 'B']、 [ 'B'、 '1' 、' 1' 、 'B']、」1' [ 'B'、 'B'、 'B'、 'B'、 'B'] 説明:
注意:
- 範囲[1、50]に入力行列の幅と高さ。
- 専用ボックス(「M」または「E」)の外に掘られていない場所をクリックして、これはまた、パネルは、少なくともクリッカブルボックスが含まれていることを意味します。
- 入力パネルは、ゲームの状態の終わりではありません(つまり、地雷が掘り起こされています)。
- 简单起见,未提及的规则在这个问题中可被忽略。例如,当游戏结束时你不需要挖出所有地雷,考虑所有你可能赢得游戏或标记方块的情况。
这题可以用DFS/BFS写,在BFS专题下,我们尝试用BFS求解这题:
思路如下:
1、从Click点开始
- 如果click点是炸弹M,把这个点改成X,直接返回board
- 如果不是M,把click点压入队列,并vis[click]==1,进入第2步
2、BFS
- 计算这个点八个方向的地雷数量,如果数量>0,则把这个点修改为这个数量,返回board
- 如果数量为0,则把八个方向上vis==0的点都压入队列,并把这些点的vis都置1
- 再次进入2
AC代码:
class Solution { public static class POINT { int x, y; POINT(int x, int y) { this.x = x; this.y = y; } } public int getM(char[][] board,int xx,int yy){ int cnt = 0; for (int k = 0; k < 8; k++) { int newx = xx + dirx[k]; int newy = yy + diry[k]; if (newx >= 0 && newx < board.length && newy >= 0 && newy < board[0].length && (board[newx][newy] == 'M' || board[newx][newy] == 'X')) { cnt++; } } return cnt; } int dirx[] = {0, 1, 1, 1, 0, -1, -1, -1}; int diry[] = {1, 1, 0, -1, -1, -1, 0, 1}; int[][] vis ; public char[][] updateBoard(char[][] board, int[] click) { int x = click[0]; int y = click[1]; if (board[x][y] == 'M') { board[x][y] = 'X'; return board; } vis = new int[board.length][board[0].length]; Queue<POINT> queue = new LinkedList<>(); vis[x][y] = 1; queue.offer(new POINT(x,y)); while (!queue.isEmpty()) { POINT point = queue.poll(); int xx = point.x; int yy = point.y; int cnt = getM(board,xx,yy); //附近炸弹数量 if (cnt > 0) { board[xx][yy] = (char) (cnt + '0'); } else { board[xx][yy] = 'B'; for (int k = 0; k < 8; k++) { int newx = xx + dirx[k]; int newy = yy + diry[k]; if (newx >= 0 && newx < board.length && newy >= 0 && newy < board[0].length && vis[newx][newy]==0) { queue.offer(new POINT(newx,newy)); vis[newx][newy] = 1; } } } } return board; } }