Creating a Game Like Minesweeper in Flutter
- Getting Started
- Introducing the Minesweeper Flutter Game
- Playing Minesweeper
- Understanding the Moore Neighborhood
- Understanding the CellModel Class and Properties
- Laying Out Widgets
- Building the Grid
- Using Rows and Columns
- Adding Game Logic
- Generating Mines
- Generating Cell Values
- Adding User Interactions
- Adding onTap to Uncover Cells
- Adding longPress to Flag Cells
- Checking if the Game Is Over
- Checking if the Player Won
- Finishing Up
- Handling Edge Cases
- Adding ProgressBar
- Adding Rules
- Where to Go From Here?
Developing games with Flutter isn’t explored very much. In this tutorial, you’ll build a game like the classic Minesweeper in Flutter. You’ll learn to create the game’s UI and write clean, modular code to implement algorithms that bring the game logic to life.
Here’s a preview of the app you’ll build:
To build this game, you’ll use several Flutter widgets to create the UI and write algorithms to implement the game logic.
While building this app, you’ll learn about:
- Minesweeper’s logic and game theory.
- Implementing the game user interface using Flutter widgets.
- Building a dynamic and random game with a specific difficulty every time.
- Using the
GestureDetectorwidget to detect taps and long-presses.
- Optimizing the game to avoid edge cases.
Download the starter project by clicking Download Materials at the top or bottom of the tutorial.
Click Open an existing Android Studio project and choose the starter folder from your unzipped download.
Run the flutter create command in the starter folder to generate the android and ios folders. Next, download your dependencies by double-clicking pubspec.yaml on the left panel and then clicking pub get at the top of your screen. To avoid problems, delete the test folder, which Flutter generated when you executed the flutter create command.
Finally, build and run to see this:
Here are a few files you’ll see in the starter project’s lib folder:
main.dart is the main file that acts as the entry point for the app. It contains
MyApp, which contains
MaterialApp. This widget uses
MyHomePageas the child. This widget contains the game’s only screen.
cell.dart contains the model for the cells that you’ll lay out in a grid on the screen. It contains a class called
CellWidget, which is a visual representation of a cell on the screen.
Introducing the Minesweeper Flutter Game
Before you get into writing the code to build this Flutter game, it’s important to understand the basics of Minesweeper. It’s a logical single-player game that requires careful assessment of the cells on the board before making the next move. This continues until the player clears the board — or hits a mine. The game originates from the 1960s, and it has been written for many computing platforms in use today. It has many variations and offshoots. Simply do a quick Google search for “Minesweeper”, and you can play a web version of the game right in your browser.
For this project, you’ll need to understand Minesweeper in more detail.
Minesweeper is a simple — but not to be underestimated — puzzle game that consists of a rectangular board of tiles laid out on the screen. The game’s objective is to clear the board without detonating any hidden “mines”, or bombs, by using help from numbers indicating how many mines are in neighboring cells.
The player selects a cell to uncover it. If the cell has a mine, the game is over. Otherwise, the cell displays the number of mines in the cell’s Moore neighborhood. Using these numbers, the player uncovers nearby cells. This continues until either they hit a mine or uncover all the non-mine cells on the board. Therefore, understanding the numbers in the cells is crucial to completing the game.
While the game is in progress, the player can flag a cell for their reference if they suspect it to be a mine. This has no impact on the game logic but allows the player to keep track of the suspected cells. A flagged cell can be either a mine or a non-mine.
Once the player uncovers all the non-mine cells, the game is complete. In this Minesweeper Flutter version, the game restarts with increased difficulty — the size of the grid increases, and the number of mines also increases.
Understanding the Moore Neighborhood
A Moore neighborhood is a 3×3 grid of cells. It consists of one central cell and all its surrounding cells, including cells with sides adjacent to the central cell and those that touch its corners. The Moore neighborhood is named for Edward F. Moore, a computer scientist known for his work in topics including cellular automata and finite state machines. Here’s a diagram of a cell with its Moore neighborhood, with numbers indicating cell coordinates:
In Minesweeper, when the player selects a non-mine cell, the cell reveals a number. This represents the number of mines in the surrounding eight cells, or the cell’s Moore neighborhood. Using the number, the player can make a calculated guess about the next non-mine cell on the board that they can safely uncover. Keep in mind that no mines are uncovered at any point in the game. Tapping a cell with a mine is the only way to uncover a mine, and that ends the game.
When the player taps a non-mine cell, the game also uncovers all the non-mine cells in its Moore neighborhood. As a result, the non-mine cells in overlapping Moore neighborhoods are also uncovered, and this continues until there are no more non-mine cells in the Moore neighborhood of an uncovered cell. You use recursion to implement this in the code.
In the code, you’ll write
unrevealRecursively, which takes in a
CellModel object and uncovers the cells in the Moore neighborhood recursively.
Understanding the CellModel Class and Properties
Inside cell.dart, you’ll find the definition of the class
CellModel. This is the foundational model class you use to keep track of the cells on the board in the memory. You also use this class to represent the cell visually in combination with
In the game, you store all the cells in a 2D array. Since you’re using Dart, you’ll create a
List to store all the cells. So, each cell will have a row number and column number. With this in mind, now look at the properties of the
x is an
integerthat stores the cell’s column number.
y is an
integerthat stores the cell’s row number.
isMine is a
trueif the cell is a mine and
falseif it isn’t. The default value is
isRevealed is a
booleanvariable that stores
trueif the cell has been uncovered or
falseif it hasn’t.
value is an
integervariable that stores the number of mines in the Moore neighborhood of the cell. The default value is zero.
isFlagged is a
booleanvariable that stores
trueif the player has flagged the cell or
falseif not. The default value is