Minesweeper

扫雷游戏

题目描述

给定一个代表游戏板的二维字符矩阵。 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字('1' 到 '8')表示有多少地雷与这块已挖出的方块相邻,'X' 则表示一个已挖出的地雷。

现在给出某个未挖出方块的位置,根据以下规则,返回相应位置被点击后对应的面板:

  • 如果一个地雷('M')被挖出,游戏就结束了,把它改为 'X'。

  • 如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的未挖出方块都应该被递归地揭露。

  • 如果一个至少与一个地雷相邻的空方块('E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。

  • 如果在此次点击中,若无更多方块可被揭露,则返回面板。

示例:

输入: 
[
    ['E', 'E', 'E', 'E', 'E'],
    ['E', 'E', 'M', 'E', 'E'],
    ['E', 'E', 'E', 'E', 'E'],
    ['E', 'E', 'E', 'E', 'E']
]

Click : [3,0]

输出: 
[
    ['B', '1', 'E', '1', 'B'],
    ['B', '1', 'M', '1', 'B'],
    ['B', '1', '1', '1', 'B'],
    ['B', 'B', 'B', 'B', 'B']
]

解法

解法一:DFS

  • 时间复杂度:O(mn)

  • 空间复杂度:O(mn)

var offset = [][]int{
    {0, 1}, {0, -1}, {-1, 0}, {1, 0}, {1, 1}, {1, -1}, {-1, -1}, {-1, 1},
}

func updateBoard(board [][]byte, click []int) [][]byte {
    if board[click[0]][click[1]] == 'M' {
        board[click[0]][click[1]] = 'X'
        return board
    }
    updateBoardDfs(board, click[0], click[1])
    return board
}

func updateBoardDfs(board [][]byte, x, y int) {
    if board[x][y] != 'E' {
        return
    }
    count := 0
    for _, v := range offset {
        tmpX, tmpY := x+v[0], y+v[1]
        if tmpX < 0 || tmpX >= len(board) || tmpY < 0 || tmpY >= len(board[0]) {
            continue
        }
        if board[tmpX][tmpY] == 'M' {
            count++
        }
    }
    if count > 0 {
        board[x][y] = byte(count + '0')
        return
    }
    board[x][y] = 'B'
    for _, v := range offset {
        tmpX, tmpY := x+v[0], y+v[1]
        if tmpX < 0 || tmpX >= len(board) || tmpY < 0 || tmpY >= len(board[0]) {
            continue
        }
        if board[tmpX][tmpY] == 'E' {
            updateBoardDfs(board, tmpX, tmpY)
        }
    }
    return
}

解法二:

  • 时间复杂度:O(mn)

  • 空间复杂度:O(mn)

func updateBoard(board [][]byte, click []int) [][]byte {
    if board[click[0]][click[1]] == 'M' {
        board[click[0]][click[1]] = 'X'
        return board
    }

    visited := make([][]bool, len(board))
    for i := range visited {
        visited[i] = make([]bool, len(board[i]))
    }

    directionR := []int{1, -1, 0, 0, 1, 1, -1, -1}
    directionC := []int{0, 0, 1, -1, 1, -1, 1, -1}
    queue := [][]int{click}
    visited[click[0]][click[1]] = true
    for len(queue) > 0 {
        click := queue[0]
        queue = queue[1:]
        count, r, c := 0, click[0], click[1]
        for i := 0; i < 8; i++ {
            tmpR := r + directionR[i]
            tmpC := c + directionC[i]
            if tmpR < 0 || tmpR >= len(board) || tmpC < 0 || tmpC >= len(board[0]) {
                continue
            }
            if board[tmpR][tmpC] == 'M' {
                count++
            }
        }

        if count > 0 {
            board[r][c] = byte(count + '0')
        } else {
            board[r][c] = 'B'
            for i := 0; i < 8; i++ {
                tmpR := r + directionR[i]
                tmpC := c + directionC[i]
                if tmpR < 0 || tmpR >= len(board) || tmpC < 0 || tmpC >= len(board[0]) {
                    continue
                }
                if board[tmpR][tmpC] == 'E' && !visited[tmpR][tmpC] {
                    queue = append(queue, []int{tmpR, tmpC})
                    visited[tmpR][tmpC] = true
                }
            }
        }
    }
    return board
}

Last updated

Was this helpful?