One, Title Description
给定一个代表游戏板的二维字符矩阵。 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,
'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,
数字('1' 到 '8')表示有多少地雷与这块已挖出的方块相邻,
'X' 则表示一个已挖出的地雷。
现在给出在所有未挖出的方块中('M'或者'E')的下一个点击位置(行和列索引),
根据以下规则,返回相应位置被点击后对应的面板:
如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X'。
如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),
并且所有和其相邻的方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块('E')被挖出,
修改它为数字('1'到'8'),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。
Second, the problem solution
Method One: dfs
More information on the topic, they may wish to split:
- 'M': no dig mines
- 'X': being dug out of mines, met representatives of the game is over X.
- 'E': an unknown box.
- 'B': a box of eight directions are sure there are no mines.
- click [0]: Step 1 abscissa game.
- click [1]: game ordinate Step 1.
algorithm
- If the current position is not mines M, the temporarily marked as B, and then determine whether the distance between the outer mines 8 M direction current position of the step 1, there will be marked with a number of overlay marks countM mines B.
- Otherwise, the location of mines labeled X can be, because there is only one explanation smear landmine M.
int m, n;
private static int[][] dir = {
{-1, 0}, {1, 0},
{0, -1}, {0, 1},
{-1, -1},{-1, 1},
{1, -1}, {1, 1},
};
public char[][] updateBoard(char[][] grid, int[] click) {
m = grid.length;
n = grid[0].length;
dfs(grid, click[0], click[1]);
return grid;
}
//深搜
private void dfs(char[][] grid, int x, int y) {
if (!inArea(x, y))
return;
if (grid[x][y] == 'M') {
grid[x][y] = 'X';
}else if (grid[x][y] == 'E') {
grid[x][y] = 'B';
int countM = countM(grid, x, y);
if (countM > 0) {
grid[x][y] = (char) (countM + '0');
}else {
for (int i = 0; i < 8; i++) {
int newX = x + dir[i][0];
int newY = y + dir[i][1];
dfs(grid, newX, newY);
}
}
}
}
//统计8个方向的地雷数量
private int countM(char[][] grid, int x, int y) {
int count = 0;
for (int i = 0; i < 8; i++) {
int newX = x + dir[i][0];
int newY = y + dir[i][1];
if (inArea(newX, newY) && grid[newX][newY] == 'M') {
count++;
}
}
return count;
}
private boolean inArea(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
}
Complexity Analysis
- time complexity: ,
- Space complexity: ,
Method Two: bfs
No matter what way to solve this problem, in its essence is to traverse the entire grid, just traversed a different way, but the main logic is the same.
int m, n;
private static int[][] dir = {
{-1, 0}, {1, 0},
{0, -1}, {0, 1},
{-1, -1},{-1, 1},
{1, -1}, {1, 1},
};
public char[][] updateBoard(char[][] grid, int[] click) {
m = grid.length;
n = grid[0].length;
Queue<Pos> queue = new LinkedList<>();
queue.add(new Pos(click[0], click[1]));
while (!queue.isEmpty()) {
Pos pos = queue.poll();
if (grid[pos.x][pos.y] == 'E') {
grid[pos.x][pos.y] = 'B';
int count = countM(grid, pos.x, pos.y);
if (count > 0) {
grid[pos.x][pos.y] = ((char) (count + '0'));
} else {
for (int i = 0; i < 8; i++) {
int newX = pos.x + dir[i][0];
int newY = pos.y + dir[i][1];
if (inArea(newX, newY)) {
queue.add(new Pos(newX, newY));
}
}
}
} else if (grid[pos.x][pos.y] == 'M')
grid[pos.x][pos.y] = 'X';
}
return grid;
}
private boolean inArea(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
}
private int countM(char[][] grid, int x, int y) {
int count = 0;
for (int i = 0; i < 8; i++) {
int newX = x + dir[i][0];
int newY = y + dir[i][1];
if (inArea(newX, newY) && grid[newX][newY] == 'M') {
count++;
}
}
return count;
}
class Pos {
int x, y;
public Pos(int _x, int _y) {
x = _x;
y = _y;
}
}
Complexity Analysis
- time complexity: ,
- Space complexity: ,