Interested in the source code? You can find it on GitHub!

A python game similar to Minesweeper where you need to reveal all fields on a board without revealing a trapped field.

📦 Used Libraries

All libraries stem from Python 3.12.2. The following libraries are used in the game:

  • random
  • os
  • sys

🏗️ Architectural Description

The project is split into four files:

  • main.py
  • util.py
  • text.py
  • board.py

main.py

The main.py file contains the game loop and various setup logic. When the game is started, the main function first prints the main menu and then listens for user input. Refer to ➡️ Program Flow for more information. The primary game loop is also included here.

util.py

The util.py file contains various utility functions, mostly related to the size of the console window and the conversion of one type to another (strings to integers).

text.py

The text.py file could almost be treated as a second util file, as it contains utility functions for text formatting, such as bold(), italic(), and various other functions for coloring text.

board.py

The board.py file contains the Board class, which contains all data about the map while the user is playing, such as the fields that have been revealed, where the bombs are located, etc. It also exposes functions for drawing various parts of the map.

👤 User Interface

Since this game is entirely terminal-based, all user input is made in and collected using Python’s built-in input method. Menu navigation differs from game controls mostly by style - the user has to enter numbers instead of coordinates. See the ➡️ Program Flow for more information. When in-game, the user has to enter coordinates ([LETTER][NUMBER]) instead of numbers, with the Letter symbolizing the row and the number symbolizing the column of the tile they want to reveal.

Earlier in the project, attempts were made to use an event-listener based method, where the user could use the arrow keys to move focus on the board. However, this idea had to be abandoned after the it became clear that neither the keyboard nor the time module could be used.

➡️ Program Flow

When the program is started, the user will enter the main menu. From there, they can choose one of three options: “Play Game”, “Leaderboard” or “Quit game”. The user is able to choose one of these options by entering the number on the command line.

Option 1 - Play Game

When “Play Game” is selected, the user is first asked for the board size. They can enter any number greater than 5, with virtually no limitation on the board size above that, besides the terminal window size and the user’s RAM. They are then asked to choose their difficulty - easy, medium or hard. The difficulty will be used later to generate the amount of mines and apply a multiplier to the user’s score. As soon as the user has entered the difficulty, they are thrown into the so-called “game loop”, the console window gets cleared and the playing field is drawn. A check is also made to ensure the user’s terminal is large enough to fit the playing field in it’s entirety. This check is made on every iteration of the loop to ensure the user can see the board. If the user’s terminal is too small, they are asked to resize it and then press a key of their choice. Once the board and instructions have been printed, the user has to input the coordinates of a field they want to reveal. An easter egg can be found here: when entering uuddlrlrba, (an abbreviated version of the Konami Code), a cheat mode will be enabled that colors all squares with traps on them red instead of green. If cheats are enabled, the user will not be able to save their score to the leaderboard once the game has concluded. The player can also enter q to quit the game immediately. After a valid coordinate has been entered, the field is checked for whether it is a trapped field or not. If it is trapped, the game ends immediately, and the user is promoted to press any key to return to the main menu. If the field does not contain a trap, the players score is increased by , multiplied by the aforementioned difficulty modifier ( for easy, for medium, for hard). Additionally, the sum of the revealed field is added to the score as well. Once the field has been revealed, another check is made to verify whether the player has revealed all fields without traps on them. If so, a victory screen is shown where the player can enter their name so the score gets saved in the leaderboard file. After the score has been saved, they are returned to the main menu. If there are still fields left to reveal, the console is cleared and the board is re-drawn, with the revealed field’s score now displayed instead of the question mark. (The score is calculated as the sum of all adjacent fields which have traps on them.)

Option 2 - Leaderboard

The leaderboard option will check for an existing leaderboard.csv file in the root of the project. If no file exists, or no entries are found in the file, a “No scores found.” message is displayed. Should the file contain scores, they are sorted and printed in the console sorted by the highest score obtained. Both the name entered by the user and their score are displayed.

Option 3 - Quit game

When “Quit game” is selected, the program shuts down immediately without further checks.

✅ Test, Type Checker & Linter Results

Test / Type Checker / LinterResult (Score)
Coverage (Unittest)No issues found (100% coverage)
PylintNo issues found (10.00 / 10)
MyPyNo issues found