> ## Documentation Index
> Fetch the complete documentation index at: https://leetcode-py.wisl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> leetcode-py is a Python LeetCode practice environment generator with one CLI: lcpy. It is not a service or platform.
> Each problem is a directory under leetcode/ with README.md, solution.py, test_solution.py, helpers.py, and playground.ipynb. lcpy gen creates them from JSON templates bundled with the package.
> Examples are backed by tests; copy them verbatim.

# Minesweeper Python Solution with Tests

> Tested Python solution for LeetCode 529 with 20 pytest cases. Generate a practice environment with lcpy.

LeetCode 529, [Medium](/catalog/medium). Topics: [Array](/catalog/topics/array), [Depth-First Search](/catalog/topics/depth-first-search), [Breadth-First Search](/catalog/topics/breadth-first-search), [Matrix](/catalog/topics/matrix). [View on LeetCode](https://leetcode.com/problems/minesweeper/description/).

Generate this problem as a practice environment: tested reference solution, 20 [parametrized pytest cases](/practice/testing), and a playground notebook:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
lcpy gen -n 529   # by problem number
lcpy gen -s minesweeper   # by problem name
```

## Problem

Let's play the minesweeper game ([Wikipedia](https://en.wikipedia.org/wiki/Minesweeper_%28video_game%29), [online game](http://minesweeperonline.com))!

You are given an `m x n` char matrix `board` representing the game board where:

* `'M'` represents an unrevealed mine,
* `'E'` represents an unrevealed empty square,
* `'B'` represents a revealed blank square that has no adjacent mines (i.e., above, below, left, right, and all 4 diagonals),
* digit (`'1'` to `'8'`) represents how many mines are adjacent to this revealed square, and
* `'X'` represents a revealed mine.

You are also given an integer array `click` where `click = [clickr, clickc]` represents the next click position among all the unrevealed squares (`'M'` or `'E'`).

Return *the board after revealing this position according to the following rules*:

1. If a mine `'M'` is revealed, then the game is over. You should change it to `'X'`.
2. If an empty square `'E'` with no adjacent mines is revealed, then change it to a revealed blank `'B'` and all of its adjacent unrevealed squares should be revealed recursively.
3. If an empty square `'E'` with at least one adjacent mine is revealed, then change it to a digit (`'1'` to `'8'`) representing the number of adjacent mines.
4. Return the board when no more squares will be revealed.

### Examples

![Example 1](https://assets.leetcode.com/uploads/2023/08/09/untitled.jpeg)

```
Input: board = [["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"]]
```

![Example 2](https://assets.leetcode.com/uploads/2023/08/09/untitled-2.jpeg)

```
Input: 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"]]
```

### Constraints

* `m == board.length`
* `n == board[i].length`
* `1 <= m, n <= 50`
* `board[i][j]` is either `'M'`, `'E'`, `'B'`, or a digit from `'1'` to `'8'`.
* `click.length == 2`
* `0 <= clickr < m`
* `0 <= clickc < n`
* `board[clickr][clickc]` is either `'M'` or `'E'`.

## Solution

Reference implementation from [solution.py on GitHub](https://github.com/wislertt/leetcode-py/blob/main/leetcode/minesweeper/solution.py), full suite in [test\_solution.py](https://github.com/wislertt/leetcode-py/blob/main/leetcode/minesweeper/test_solution.py):

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from collections import deque


class Solution:
    DIRECTIONS: tuple[tuple[int, int], ...] = (
        (-1, -1),
        (-1, 0),
        (-1, 1),
        (0, -1),
        (0, 1),
        (1, -1),
        (1, 0),
        (1, 1),
    )

    # Time: O(m * n)
    # Space: O(m * n)
    def update_board(self, board: list[list[str]], click: list[int]) -> list[list[str]]:
        rows, cols = len(board), len(board[0])
        row, col = click
        if board[row][col] == "M":
            board[row][col] = "X"
            return board

        queue: deque[tuple[int, int]] = deque([(row, col)])
        while queue:
            r, c = queue.popleft()
            mines = self._adjacent_mines(board, r, c)
            if mines:
                board[r][c] = str(mines)
                continue
            board[r][c] = "B"
            for dr, dc in self.DIRECTIONS:
                nr, nc = r + dr, c + dc
                if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc] == "E":
                    board[nr][nc] = "B"
                    queue.append((nr, nc))
        return board

    def _adjacent_mines(self, board: list[list[str]], r: int, c: int) -> int:
        rows, cols = len(board), len(board[0])
        return sum(
            1
            for dr, dc in self.DIRECTIONS
            if 0 <= r + dr < rows and 0 <= c + dc < cols and board[r + dr][c + dc] == "M"
        )
```

## Complexity

| Time | Space |
| - | - |
| O(m \* n) | O(m \* n) |

## Tags


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.