[Rod Stephens Books]
Index Books Python Examples About Rod Contact
[Mastodon] [Bluesky]
[Build Your Own Ray Tracer With Python]

[Beginning Database Design Solutions, Second Edition]

[Beginning Software Engineering, Second Edition]

[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

[WPF 3d, Three-Dimensional Graphics with WPF and C#]

[The C# Helper Top 100]

[Interview Puzzles Dissected]

Title: Expose cells that are neighbors of satisfied cells in the minesweeper game made with Python and tkinter

[A minesweeper game built with Python and tkinter that flags cells that must be mines]

My earlier post Flag cells that must be mines in the minesweeper game made with Python and tkinter includes a method that performs one of the most important logical steps in solving the puzzle. That method flags cells where the number of unrevealed neighbors is the same as the number of unflagged adjacent mines. This post adds another important tool. The new tool finds cells that have the necessary number of flagged neighbors and exposes their unrevealed neighbors.

Revealing Neighbors

[The circled cell has two flagged neighbors and is adjacent to two mines, so its other neighbors are safe.] This tool implements the second main bit of logic for solving the minesweeper puzzle. If a cell is adjacent to N mines and it has N flagged neighbors, then its other neighbors are not mines so the program exposes them.

For example, take a look at the picture on the right. The circled cell is adjacent to two mines and two of its neighbors (to the northeast and southwest) are flagged. That means the cells other neighbors (which are marked with small Xs) are safe so the new tool exposes them.

mnu_expose_neighbors

The following code shows the new tool.

def mnu_expose_neighbors(self): '''Repeatedly expose neighbors of satisfied cells.''' # Loop over the board looking for satisfied cells. any_change = False made_change = True while made_change: made_change = False for row in self.board: for cell in row: if cell.is_satisfied(): made_change = True any_change = True return any_change

This code loops over the board's cells calling each cell's is_satisfied method to execute this logic on the cell. The program makes that test in a loop that executes as long as made_change is True. It uses variable any_change to keep track of whether it exposed any new cells so it can return true if it did.

is_satisfied

The following is_satisfied method does the real work.

def is_satisfied(self): ''' See if this cell is satisfied. If it is, click any hidden neighbors and return True if there were such neighbors. ''' flagged_neighbors = self.flagged_neighbors() if self.is_shown and len(flagged_neighbors) == self.num_adjacent: # We're satisfied. Expose the neighbors. made_changes = False # Click neighbors except flags. for neighbor in self.neighbors(): if not neighbor.is_flagged and not neighbor.is_shown: neighbor.clicked() made_changes = True return made_changes

This code gets a list of the cell's flagged neighbors. (See the previous post for a description of the flagged_neighbors method.) If the cell is shown and the number of its flagged neighbors equals the number of mines adjacent to the cell, then this cell is satisfied. In that case, the code loops through the cell's neighbors. If a neighbor is not flagged as a mine and it is not already shown, the code calls its clicked method to expose that neighbor.

The program uses the made_changes variable to keep track of whether any of the neighbors was exposed. If any neighbor was exposed, the method returns True.

Conclusion

This tool is a little easier to understand than the previous one. Between the two of them, they solve a large part of the minesweeper puzzle. You can alternate between calling the two of them (it's easiest by pressing Ctrl+1 and Ctrl+2), you can get quite far. For example, the picture at the top of this post was generated starting with 10 random guesses and then pressing Ctrl+1 and Ctrl+2 repeatedly.

When these two tools get stuck, you can often study the board to find a few more cells that you can flag or expose and get the tools working again. I may try to implement those kinds of tools later. Meanwhile, download the example to experiment with it and to see additional details.

© 2025 Rocky Mountain Computer Consulting, Inc. All rights reserved.