Leetcode 529. Minesweeper | Python

Time:2020-10-26

529. Minesweeper game


Source: leetcode
https://leetcode-cn.com/problems/minesweeper

subject


Let’s play Minesweeper!

Given a two-dimensional character matrix representing the game board.  MFor oneNot excavatedMine of mine,EFor oneNot excavatedThe empty square of,BRepresents a mine with no adjacent (top, bottom, left, right, and all four diagonals)ExcavatedThe blank box of,number(‘1’ to ‘8’) indicates how many mines are associated with this areaExcavatedIs adjacent to each other,XIt means aExcavatedMine.

Now given in allNot excavatedIn the box of(MperhapsE)The next click position (row and column index) of the corresponding position is returned to the corresponding panel after the corresponding position is clicked according to the following rules:

  1. If a mine(M)Dig it out and the game is over – change it toX
  2. If an empty block without adjacent mines(E)It was dug out and changed to(B)And all adjacentNot excavatedBlocks should be exposed recursively.
  3. If oneAdjacent to at least one mineEmpty square of(E)It was dug out and changed tonumber(‘1’ to ‘8’), indicating the number of adjacent mines.
  4. If there are no more squares to reveal in this click, return to the panel.

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:

Leetcode 529. Minesweeper | Python

Example 2:

Input:

[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'M', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]

Click : [1,2]

Output:

[['B', '1', 'E', '1', 'B'],
 ['B', '1', 'X', '1', 'B'],
 ['B', '1', '1', '1', 'B'],
 ['B', 'B', 'B', 'B', 'B']]

Explanation:

Leetcode 529. Minesweeper | Python

be careful:

  1. The range of the width and height of the input matrix is [1,50].
  2. You can only click on an unearthed square (‘m ‘or’ e ‘), which means that the panel contains at least one clickable square.
  3. The input panel will not be at the end of the game.
  4. For simplicity, rules not mentioned can be ignored in this issue. For example, when the game is over, you don’t need to dig out all the mines, consider all the situations where you might win the game or mark the box.

All the above pictures are from leetcode

Thinking of problem solving


Idea: simulation (DFS, BFS)

Four rules are given in the title. Then we will simulate them according to these rules. Here we will discuss them in different situations

followingadjacentIncludes up, down, left, right, and all four diagonals

  • When you clickUnearthed mines(M) According to rule 1, it is changed to X;
  • When you clickUncut square(E) We will discuss the situation here

    • According to rule 3, if there are mines in the uncut squares adjacent to the current click box, then count the number of mines, and change the current block to a number (corresponding to the number of mines)
    • According to rule 2, if the adjacent square does not contain mines, the current block will be changed to B, and then continue to search the adjacent square.

Then we can use depth first search (DFS), breadth first search (BFS) ideas to achieve.

Depth first search

According to the above analysis, use the idea of DFS to solve the problem.

See code implementation DFS for specific code

Breadth first search

It should be noted here, because a block may be extended to other blocks. In order to avoid repetition, the coordinates corresponding to a block are repeatedly added to the queue, so it needs to be marked here.

For specific code, see code implementation BFS

code implementation


# DFS
class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        #Define 8 directions
        dx = [-1, -1, -1, 0, 1, 1, 1, 0] 
        dy = [-1, 0, 1, 1, 1, 0, -1, -1]

        m = len(board)
        n = len(board[0])

        def in_board(x, y):
            To determine whether the coordinates are within the boundary
            """
            return 0 <= x < m and 0 <= y < n

        def dfs(x, y):
            count = 0
            #First judge whether the adjacent (8 directions) block contains mines
            for i in range(8):
                nx = x + dx[i]
                ny = y + dy[i]
                #If the adjacent blocks are within the limited range and contain mines, count the number of mines
                if in_board(nx, ny) and board[nx][ny] == 'M':
                    count += 1
            if count > 0:
                #Contains mines, modify the current point to a number corresponding to the number of mines, return to
                board[x][y] = str(count)
                return
            #If the adjacent block does not contain mines, change to 'B'
            #And spread the search to adjacent locations
            board[x][y] = 'B'
            for i in range(8):
                nx = x + dx[i]
                ny = y + dy[i]
                if in_board(nx, ny) and board[nx][ny] == 'E':
                    dfs(nx, ny)

        x, y = click

        #If you are currently clicking on an unearthed mine, change it to 'x' and return to
        if board[x][y] == 'M':
            board[x][y] = 'X'
        else:
            #When you click on an uncut square, discuss it according to the situation
            dfs(x, y)

        return board


# BFS
class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        #Define 8 directions
        dx = [-1, -1, -1, 0, 1, 1, 1, 0] 
        dy = [-1, 0, 1, 1, 1, 0, -1, -1]

        m = len(board)
        n = len(board[0])

        def in_board(x, y):
            To determine whether the coordinates are within the boundary
            """
            return 0 <= x < m and 0 <= y < n
        
        def bfs(x, y):
            #Here we should pay attention to a point may extend to other points, pay attention to the mark, to prevent repeated queue
            signed = [[False] * n for _ in range(m)]
            #Mark start point
            signed[x][y] = True
            from collections import deque
            queue = deque()
            #Join the starting point first
            queue.append([x, y])
            
            while queue:
                count = 0
                x, y = queue.popleft()
                #If you directly click a mine, change the current box to 'x' and return directly
                if board[x][y] == 'M':
                    board[x][y] = 'X'
                    return
                #Otherwise, judge the eight directions and see if there are mines
                for i in range(8):
                    nx = x + dx[i]
                    ny = y + dy[i]
                    if in_board(nx, ny) and board[nx][ny] == 'M':
                        count += 1
                if count > 0:
                    #When there are mines, modify the current point to a number, corresponding to the number of mines
                    board[x][y] = str(count)
                else:
                    #Modify the current box to 'B'
                    board[x][y] = 'B'
                    #When there are no mines, mark the surrounding squares into the team and continue searching
                    for i in range(8):
                        nx = x + dx[i]
                        ny = y + dy[i]
                        #When the block is unmarked and within the boundary, join the queue and mark
                        if in_board(nx, ny) and signed[nx][ny] != True:
                            queue.append([nx, ny])
                            signed[nx][ny] = True
                
        x, y = click
        bfs(x, y)
        return board

Achieving results


Leetcode 529. Minesweeper | Python

Leetcode 529. Minesweeper | Python

Welcome to our attention


The official account [book collection]

Recommended Today

Stack chain storage

Linked list implementation stack Create three files: stacklinked. H, stacklinked. C, stacklinkedtest. C stackLinked.h #ifndef STACK_LINKED_H_ #define STACK_LINKED_H_ #ifdef __GNUC__ #define DEPRECATED __attribute__( (deprecated) ) #elif defined(_MSC_VER) #define DEPRECATED __declspec( deprecated ) #else #define DEPRECATED #endif #ifndef PTOI #define PTOI( p ) ((int32_t)(int64_t)(p)) #endif #ifndef ITOP #define ITOP( i ) ((void *)(int64_t)(i)) #endif #define ADT […]