🌊 Section 6: Reveal + Zero Flood

📝 Summary

In this section, you will add the reveal() method inside the Board class. This method reveals cells, performs a “zero flood” (so empty areas open up automatically), checks for win/loss, and returns a list of changed cells so the Tkinter UI can repaint only what needs updating.

✅ Checklist

  • Add a reveal(self, r, c) method inside class Board (after toggle_flag).
  • If the game is over, ignore reveal attempts.
  • If mines are not placed yet, place them on the first click (safe first click).
  • Ignore reveals on flagged or already-revealed cells.
  • If the player reveals a mine, set game over and return the changed cell.
  • Use a queue (deque) to flood-reveal connected zero-adjacent cells.
  • After revealing, check the win condition and update _game_over / _win.
  • Return a list of changed coordinates for the UI.

🎓 Core Concepts

First-click safety: In Minesweeper, the first click should never lose. That’s why we delay mine placement until the first reveal. When reveal() runs for the first time, it calls _place_mines(r, c) so the clicked cell (and its neighbors) stay safe.

Zero flood: When a cell has adjacent == 0, it means there are no mines around it. Minesweeper reveals a whole region of connected zeros automatically, plus the numbered “border” cells around them. We implement that flood using a queue.

Breadth-first search (BFS) with deque: BFS is a pattern for exploring “neighbors” in layers. A deque lets us efficiently pop from the front (popleft()) as we work through cells to reveal. This is a good match for flood fill because it stays responsive and gives us a clean list of changes to send to the UI.

Changed-cells list: Instead of redrawing everything, the model returns [(r, c), ...] so Tkinter can update only the buttons that changed. This keeps the UI fast.

💻 Code to Write (inside class Board in model.py)

Type this by hand so you understand each piece. (You already imported deque at the top of model.py in an earlier section.)

Code image: s06-code

🧠 Code Review & Key Concepts

if not self._mines_placed: self._place_mines(r, c) guarantees mines exist after the first click and keeps the first click fair.

if start.is_flagged or start.is_revealed: return [] prevents accidental reveals on flagged cells and avoids double-counting revealed cells.

The “mine path” reveals exactly one cell, sets _game_over, and returns immediately. This gives the UI a clean signal to stop normal play.

The BFS loop uses deque: - q = deque([(r, c)]) starts the flood from the clicked cell. - popleft() processes the next cell to reveal. - Zero cells enqueue neighbors so the empty region expands outward.

The win check compares _revealed_count to the total number of safe cells. When they match, the player has revealed everything that is not a mine.

🧪 Test File (create s6_test.py)

Code image: s06-test

This test checks three key behaviors: - A flagged cell cannot be revealed (so the UI doesn’t accidentally open a flagged square). - Revealing a zero cell causes a flood reveal and can trigger a win when all safe cells are revealed. - After mines are placed, revealing a mine ends the game and returns a change list containing the mine cell.