Developer: Khubab Shamsuddin
Live Website: Minesweeper
- Table of contents
- About Minesweeper
- Goals
- User Stories
- User Manual
- Game Design
- Used Technologies
- Features
- Testing
- Deployment
- Credits
Minesweeper is a game designed to entertain Internet users. The game board is made up of many columns and rows, and the player must guess and calculate in order to reveal all cells that do not contain mines. The current game is command-line-based, which receives player-guessed cell coordination as input and checks if it has a mine or not. When all cells are revealed, the player wins; if a cell contains a mine, the player loses.
- Play an interesting logic game.
- Understands how the game works.
- Be able login with a registered account.
- Build an interactive command-line version of the well-known minesweeper game.
- The game should provide amusement and joy to attract more users.
- Promote owner's information and the game description.
- I want to understand the game's rules.
- I want to be able to control the game's difficulty.
- I want to get clear feedback on my inputs.
- I want to be able to review my choices.
- I want the game to be simple and clear.
- I want the game to have a smooth and natural flow.
- I want new users to be able to create a new account.
- I want active users to be able to login to an existing account.
- I want players to see information about the game and its rules.
Click here to see instructions.
Account Menu
When the game starts and after the greeting message, the account menu (have account?) appears with two options:
- Yes, we will ask you to sign in
- No, you can signup to have one Operation: Enter the number of the selected option.
Login
When the user selects the first option in the account menu, login data will be requested. Operation: Enter email, then password. A message will show up to inform the user of the login process status; if login fails, the user will be asked to enter his credentials again.
Sign Up
If the user selects the second choice of the account menu, he will be asked to fill out signup data. Operation: Enter name, email, password, and confirms his password. Name, email, and password must start with a letter, not a number. Email must be formatted as email@provider.com, net, etc. Passwords must be at least eight characters long.
Main Menu
Once user logged in, main menu appears with three options shown:
- Start Game
- Rules
- About Operation: Enter a number in the options range. When the user selects Rules or About, a related text block will be shown, and after a while, the main menu will appear again.
Level Menu
When the user selects the first option in the main menu, he will be asked to choose the level of the game.
- Easy 3x3 (3 Mines)
- Medium 4x4 (6 Mines)
- Hard 6x6 (16 Mines) Each level has a different board size and number of mines, as mentioned.
Game Round
Once the round has begun, the board will be displayed, followed by a request for the row and column of the user's guess. Operation: Enter a row number from zero to the maximum row number on the board, then enter a column number (the same rule applies). User mustn't enter a cell position which entered before. If selected cell has a mine user will be informed and game will be ended, otherwise the board will be shown and neighbouring mines number of the selected cell will appear inside it. Round will be repeated until the player reveal all cells successfully.
Play Again Menu
When the game ends, the player will be asked if he would like to play again.
- Yes
- No Operation: Enter the selected option number. If you answer yes, a game of the same level will begin; otherwise, the main menu will appear.
Note
At any time the user enters an invalid input or an unfound option number, feedback will be prompted and the user will be requested to repeat the operation.
The Process Steps
1. Display the greeting message.
2. Inquiring about the user's account and providing the options "log in" and "sign up."
- (2.1) If the user enters "1" for login, he will be asked to enter his credentials.
- (2.2) If the user enters "2" signup, he will be asked to enter data, and a record will be created as a result.
- (2.3) The authentication process runs after both of the above options to make sure the user has an account; if authentication fails, inform the user of the wrong email or password and go to "Step 2.1. Login."
3. Display the main menu and await the user's choice (1. start, 2. rules, 3. about).
4. If the user types "1," proceed to "Step 7: Level Selection" to begin the game.
5. Display the game rules and return to "Step 3: Main Menu" if the user enters "2."
6. Display game information and return to "Step 3: Main Menu" if the user enters "3."
7. Display the levels menu and wait for the user to select (1. easy, 2. medium, or 3. difficult).
8. If the user enters "1," proceed to "Step 11: Start the Game" in simple mode.
9. If the user enters "2," proceed to "Step 11: Start the Game" mode.
10. If the user enters "3," proceed to "Step 11: Start the Game" in Hard Mode.
11. Start the game by constructing the board with a specified number of rows and columns, as well as the number of randomly distributed mines based on the level selected.
12. Begin a round by displaying the board.
13. Ask the player to enter the coordination (row and column) of his chosen cell.
14. Display the players' choice.
15. If the chosen cell has been revealed before, inform the user and proceed to "Step 13: Ask for a Guess."
16. Check if the cell contains mine if it's going to "Step 20: End Game."
17. Display the board with the chosen cell containing the number of its neighbouring mines.
18. Check to see if all cells have been explored before proceeding to "Step 20: End Game."
19. Proceed to "Step 12: New Round."
20. If a mine is discovered, show the losing message and the real board; otherwise, show the winning message.
21. Show the "play again" menu (1. yes, 2. no).
22. Proceed to "Step 11: Start the Game" if the user enters "1."
23. Proceed to "Step 3: Main Menu" if the user enters "2."
* Any incorrect selection will result in a feedback message and a new request for the user's selection.
-
The game code was written following object-oriented programming principles.
Data Models Details
- Classes Four classes have been written: (Board, User, Game, and UtilityMixin), the last one is a mixin that contains functions such as styled print functions. All other classes inherited the mixin in order to reuse its common functionalities.
- Unit Tests Each Python class in the above list has its own unit testing class to test its main methods.
- Python programming language is the main component for developing this game. - Developed and tested on python version 3.8.11.
Built-in
- Random generate a random number.
- Time pauses the game for a set amount of time.
- Signal change the behaviour of the CTRL+C keyboard input.
- Rich build tables and print markdown-formatted strings.
- Unittest create automated test classes.
- Typing union describes methods with multiple possible types of return.
3rd Party
- Firebase Admin and Firestore: I used these to connect Python code with the Firestore database.
- Bcrypt: I used Bcrypt to store and retrieve hashed and unhashed passwords securely.
- GetPass: I used it to conceal the characters of passwords entered by the user.
- Termcolor: I used this to colour and change the style of text.
- pycodestyle: I used it to validate Python code and ensure that it adhered to conventions.
- Google Firestore is used to store and get the players' account data.
- Lucidchart to design the game flowcharts.
- Gitpod and VS Code for code development and testing.
- Heroku for deploying the live version of this game.
- Github is used for version control.
- Grammarly and QuillBot to detect typos and grammatical errors.
- Node.js, HTML, CSS, and XTERM to create the game's infrastructure layer.
-
Game menus will allow the user to easily navigate all of the game's features by simply entering the number of the option he wants to select. - Covered User stories: 5,6
-
To play the game, first-time users must sign up by providing their name, email address, and password, as well as a confirmation password.
-
Covered User stories: 7
-
Existing users will be able to use their email and password to get into the game.
-
Authentication process is done on each login to check if the user has the right to access the game. Upon successful authentication, a greeting message will be printed.
-
Covered User stories: 3, 8
-
A text block that explains how the game works and how to play it to the user.
-
Covered User stories: 1, 9
-
A text block containing information about the game and the developer.
-
Covered User stories: 9
-
level options are available to provide various difficulty levels.
-
Each level has its own board dimensions (rows and columns) and specific number of mines.
-
Covered User stories: 2
-
Game board is shown in a coloured table style, the board mines' positions generated randomly.
-
Assists the user in determining mine position by providing the number of the neighbouring mine.
-
When the player loses, a real board with mines is displayed to inform the user of his incorrect cell choice.
-
Covered User stories: 4, 5
- Unrevealed cells' content is (?) to indicate that it's available for the user's choice.
- Mines are in the form of red starred (*) shapes.
- The colour of neighbouring mine cells indicates their danger level (red indicates very dangerous, orange indicates dangerous, and green indicates no mines).
- Covered User stories: 3, 5
-
Symbols and Colours Screenshot
![Symbols and Colours](/media/symbol-and-colour-screen.PNG)
-
Invalid user input triggers an appropriate message depending on the requested data.
-
Each user's coordination input is shown on the terminal to help the player track his moves.
-
To make it easier for the user to capture success messages, error messages are printed in red and success messages in green.
-
Covered User stories: 3, 4, 5
- Build a graphical user interface using Textual framework.
User Stories Testing
- I want to understand the game's rules
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Main menu -> Rules | Select option 2 | The rules of the game are presented to the user | Performs as expected |
- I want to be able to control the game's difficulty.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Main Menu -> Start Game | Select option 1 | The user will be asked to select the game level | Performs as expected |
- I want to get clear feedback on my inputs.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Across the game | Valid/ invalid input | The user will see the response to his input, whether it's a message or a menu | Performs as expected |
- I want to be able to review my choices.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Across the game | Valid/ invalid input | The user will be able to scroll and review his previous options | Performs as expected |
- I want the game to be simple and clear.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Menus | Select option number | The user will be asked to enter only selected option's number | Performs as expected |
Board | - | The text is coloured and symbols are used to make the data on the board easier to read | Performs as expected |
- I want the game to have a smooth and natural flow.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Across the game | - | The user is guided through simple instructions and nested options in a circular motion | Performs as expected |
- I want new users to be able to create a new account.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Account Menu -> No (Signup) | Select option 2 | Users are able to signup using un-registered emails | Performs as expected |
- I want active users to be able to login to an existing account.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Account Menu -> Yes (Login) | Select option 1 | Users can log in using their email addresses and passwords | Performs as expected |
- I want players to see information about the game and its rules.
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Main Menu -> Rules | Select option 2 | Users will see the game rules | Performs as expected |
Main Menu -> About | Select option 3 | Users will see information about the game and the developer | Performs as expected |
-
Unit test classes have been written to test the functionalities of the Minesweeper game.
-
The CLI command to run the tests with the print statements buffered is:
python3 test.py -b
-
Test results:
-
The game code has passed the
pycodestyle
linter validations with no errors or warnings shown. -
I applied a filter
**/*.py
on VSCode to show only problems within all Python files. -
Validatior Results:
- Bug: updating an index of the cells 2-d list will affect that all similar index updated with the same value.
- Debugging: found the problem in list creation, I create the one list of row then multiply it by the number of rows and so for the columns which cause Passing the same created list reference for the rest of lists.
- Solution: replace the code of list creation
return [[0] * self.col_size] * self.row_size
With[['?' for col in range(self.col_size)] for row in range(self.row_size)]
.
- Bug: importing
run.py
insidetest.py
file runs the game. - Debugging: Based on this Stackoverflow answer I found that I have to start game when the
__name__
attribute value is__main__
in order to prevent the code from being executed on import statement calls. - Solution: wrap the code of game starting
game = Game() game.run()
Inside the conditionif __name__ == '__main__':
.
- Bug: on the deployed version on
Heroku
I got an errorModuleNotFoundError: No module named 'rich'
even it's working as a charm on local machine. - Debugging: I've looked in requirements.txt I found that rich isn't generated by the
pip3 freeze
command; because it's considered as a built in module probably, I triedpython3 -m pip check
to find missing dependencies on local but I gotNo broken requirements found
. - Solution: I added
rich==12.4.4
manually to the requirements.txt after looking on the issue referred by GaMiNgEr9978 user onGithub
.
- Bug: broken text style when using the deployed version but working fine on local.
- Debugging: I tried to change terminal column size but it was still the same, for tables I noticed that cells with number in it printed with required shape but the ones with emojis crashes and pyfiglet text not works on deployed version as well.
- Solution: I replaced emojis with symbols and copied the text content from the local machine of pyfiglet and added the copied text to print statements.
-
The site was deployed to
Heroku
. The steps to deployment are as follows:Click here to see related deployment instructions
-
After you've signed up, navigate to the Heroku apps page and click
Create New App.
-
Enter the application name and the region, then click on
Create App
. -
Once the app has been created, go to the
Settings
tab. -
In settings, click on
Reveal Config Vars
and set the case-sensitive wordCREDS
to theKEY
field, then copy all of your credentials json file content into theVALUE
area and click on theAdd
button. -
Next, select
Add buildback
Selectpython
as the first buildpack and clickSave changes
then do the same fornode.js
, Following the given sequence is very important. -
Once the settings are complete, navigate to the
Deploy
tab. -
Select
Github
from theDeployment method
options. -
Connect your
Heroku
account withGithub
and grant Heroku` the required authorization. -
Find the name of the repository that you want to deploy.
-
Click
Connect
on the wantedrepo
and select the branch from theChoose a branch to deploy
dropdown button. -
Choose
Automatic deploys
to automatically deploy the application whenever code has been pushed to the selected branch (You recommended having a CI service configured on the repo). -
OR
-
When the
Deploy Branch
button is clicked, selectManual Deploy
to deploy the branch. -
Review the deployment debugger output if there's a deployment issue.
-
When the deployment is complete, you'll see the message
Your app was successfully deployed
and you can open your application page by clicking theView
button. -
The live link can be found here: https://cli-minesweeper.herokuapp.com/
-
-
To clone this repository to your local machine:
Click to see related deployment instructions
-
From Minesweeper Github click on
<> Code
drop-down button and select the suitable clone option. -
Click on the
HTTPS
orSSH
(requires an SSH key to be configured on your machine) tab and copy the URL. -
Open your terminal or
Git
bash window and change the directory to where you want to clone. -
Enter the following command, but don't forget to replace the
<copied URL>
:git clone <copied URL>
-
The same-named directory will be downloaded to the clone path.
-
-
To fork this repository, please follow the below steps:
Click to see related deployment instructions
- If you're not seeing this on Github`, click on this link to open up the repository.
- On the top right side of this page, click on
Fork
. - Change the forked repository if you want to, and you can add a description as well.
- Leave the branch option
Copy the main branch only
checked. - Click on
Create Fork
to complete forking.
-
Flowcharts built with the help of Stuff Made Easy Youtube channel and designed on Lucidcharts.
-
Calling method from a string is a solution on Stackoverflow by Sam Dolan
-
Rich python module used based on posts of Ashutosh Krishna and Martín Lamas.
-
Big titles and fonts are a result of using pyfiglet python module described by Khuyen Tran post and pyfiglet fonts
-
Connecting Google Firestore with the Python code is inspired by Anurag Sharma post.
-
Hiding password characters in a user's input is a solution provided by Have a nice day on Stackoverflow.
-
Email validation code using regular expressions is taken from this Rohit Gupta post.
-
Based on IDOWU OMISOLA, Bcrypt is used for password hashing and hashed password comparison.
-
Writing unit tests followed tutorials posted by Bala Priya C and the geertjanvdk's Stackoverflow solution.
-
Mocking user input inside a unit test is an idea from Pavel Vergeev blog.
-
Writing typing hints for a function with multiple possible types of return is taken from Bhargav Rao's Stackoverflow solution.
-
Rich colours used in this game are brought from the Colours List.
-
This readme file is based on the Code Institute Readme Template.
-
Grammatical errors and typos on this file were discovered and corrected by Grammarly and Quillbot.
-
Special thanks to my mentor, Mr. Mo Shami, for his continuous guidance and support.