Reveal a Minesweeper Region with Adjacent-Mine Counts
NuroSoftware Engineer · Technical ScreenLast updated
Implement a Minesweeper cell-reveal algorithm that dynamically calculates 8-directional mine adjacencies and expands blank regions while safely avoiding recursion depth pitfalls on large boards.
Problem Statement
In the game of Minesweeper, a board is represented as an m x n 2D grid of characters where each square has one of the following states:
'M': An unrevealed mine.'E': An unrevealed empty square.'B': A revealed blank square that has no adjacent mines (all 8 neighbors are mine-free).'1'to'8': A revealed square indicating the exact number of adjacent mines.'X': A revealed mine (representing a game-over trigger).
You are given the current board and a target cell click = [r, c] representing the coordinate clicked by the player. Implement a function to update and return the board according to the following rules:
- If a mine (
'M') is clicked, change its state to'X'and immediately return the updated board (game over). - If an empty square (
'E') with at least one adjacent mine (in any of the 8 directions) is clicked, change its state to the digit character representing the count of adjacent mines ('1'to'8'). Do not reveal any neighbors. - If an empty square (
'E') with zero adjacent mines is clicked, change its state to'B'. Then, recursively reveal all of its 8-directionally adjacent unrevealed squares ('E'). - If the clicked square is already revealed (
'B','1'–'8', or'X'), leave the board unchanged.
Function Signature
def reveal_board(board: list[list[str]], click: list[int]) -> list[list[str]]:
pass
Constraints
m == len(board)n == len(board[0])1 <= m, n <= 10001 <= m * n <= 100000board[i][j]is one of'M','E','B', or'1'–'8'.clickis a 2-element list[r, c]where0 <= r < mand0 <= c < n.
Examples
Example 1
board = [
["E", "E", "E", "E", "E"],
["E", "M", "E", "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: Cell [3, 0] has 0 adjacent mines, so it becomes 'B'. The reveal propagates to adjacent cells. Cells adjacent to 'M' (such as [0, 1], [1, 0], etc.) stop the propagation and display their adjacent mine counts.
Example 2
board = [
["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: The user clicked a mine at [1, 2]. It turns to 'X' and no other cells are modified.
Hints
Hint 1
Because the total number of cells can reach 100,000, recursive DFS may exceed Python's maximum recursion limit; prefer an iterative BFS or explicit stack.
Hint 2
For any empty square, always count adjacent mines first before deciding whether to label it with a digit or mark it 'B' and explore neighbors.
Hint 3
To avoid duplicate work and infinite loops in your traversal, mark expanding cells immediately when enqueued or processed.
Follow-up questions
- How would you implement the 'chord' feature common in Minesweeper, where clicking an already revealed numbered cell automatically reveals its neighbors if the number of surrounding flagged mines matches the cell's number?
- If the board were sparse (e.g., 1,000,000 x 1,000,000 with only 10,000 mines), how would you change your data structures and traversal algorithm?
- How could this algorithm be adapted to run in parallel or across multiple worker threads if processing very large satellite terrain maps?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.