Mastermind (a How-to in Python)
A mastermind is a person of outstanding intellect, but you don’t need to be a mastermind to follow this tutorial on how to build a simple game from scratch. Let’s begin!
*Disclaimer: The tutorial assumes basic knowledge in Python3.
*All constants used in the code are linked here
The board game consists of two players: a code maker (may be a bot) and a code breaker. We can code the game without using classes, but since Python is an object-oriented language, we can take advantage of this feature.
Knowing that the game involves two players, we create two classes: CodeMaker
and CodeBreaker
. I decided to create two separate files for my two classes.
CodeBreaker
In codeBreaker.py, we write all methods (functions associated with a class) for the CodeBreaker
class. To help us begin coding, we have to think about what we want the code breaker to be able to do. Based on the game description, the code breaker has one role: make guesses.
We initiate our class and define the __init__
method that will create an instance of CodeBreaker
:
In the above example, the keyword self
represents the instance of a class.
Our next step is to define a method that lets the CodeBreaker make guesses …valid guesses. To make this happen we code our method makeGuess
that will keep asking our code breaker for their guess until they input a valid one. Any helper functions will be made into protected methods.
We see in the above example that we call a helper function _validateUserInput
that validates the guess and another, _printUserFriendlyErrorMessage
that prints the error message if the guess is invalid. The only type of valid guess is a string of 4 colors separated by spaces. If the user enters an invalid guess, they are prompted to enter a new one. The end result is a guess of 4 colors in a list.
The helper functions are defined as follows:
We can see that _validateUserInput
checks if there are 4 items in the player’s guess and if they are all valid colors. _printUserFriendlyErrorMessage
prints an error message based on the error code it receives from _validateUserInput
.
CodeMaker
In the file codeMaker.py, we will be writing all methods (functions relating to a class) for the CodeMaker
class. To help us decide what methods should go in this class, we brainstorm what it is that CodeMaker
does:
- if the code breaker decides to play with a bot,
CodeMaker
will provide a randomly-generated code that the code breaker will try to guess - if the code breaker is playing with another person, the second player will type in their own code
CodeMaker
will validate the code that the second player entersCodeMaker
checks if the code breaker guessed the code correctly and if not, provide feedback to the code breaker
We start by defining the class:
In the above example, the keyword self
represents the instance of a class.
We then define createRandomCode
that returns a randomly-generated code by using the random
module. Don’t forget to import random
! In this example, we use choice
to create a list consisting of 4 random colors that are picked from our PEG_COLORS
list as shown below:
We also define createCode
that returns a validated code, which is a list of 4 colors. This is the same idea of validation as the method in the CodeBreaker
class, but this time for user-generated code. Don’t forget to write your helper functions (_validateUserInput
and _printUserFriendlyErrorMessage
) in this class as well.
Now we get to talk about my favorite part: the feedback algorithm. The feedback colors are red and white. Red means right color and position, while white means right color wrong position. In this algorithm, we check for all ‘reds’ then once we find all ‘reds,’ we look for ‘whites.’
For example, the code maker gives us a code of [blue, orange, black, purple]
. The code breaker guesses the code to be [orange, orange, purple, green]
.
code: [blue, orange, black, purple]
guess: [blue, orange, purple, green]
We expect provideFeedback
to return a feedback of [red, red, white]
. Here’s what happens under the hood:
- We look for matching colors on the same index of both the code and guess list:
code[i] == guess[i]
- If the colors match at any given index, we change these items of the lists to ‘ ’ and ‘-’ in the code list and guess list, respectively. We do not want to utilize these colors when we check for white feedback, and that’s the reason for ‘removing’ them from the list. The reason we use ‘ ’ and ‘-’ and not ‘-’ and ‘-’ or ‘ ’ and ‘ ’, is to also avoid giving an incorrect number of white feedback. Our lists look like this now:
code: [ , , black, purple]
guess: [ -, -, purple, green]
- We look for any colors in
guess
that appears incode
, but is in the wrong position. Do you see why we have to change the colors to ‘ ’ and ‘-’ now? If we change the items in both lists to be of the same character, we will get a false white feedback becausecode[1]
andguess[0]
will match andcode[0]
andguess[1]
will also match as shown below:
code: [ -, - , black, purple]
guess: [ -, -, purple, green]
- As you can see in the above examples, we expect to get a white feedback for purple being the wrong position. We do this by checking if a color at any given index in guess appears in code:
guess[i] in code
. Once we see a match, we find the index where that color appears incode
. The position is returned and we ‘remove’ the color from the lists again:guess[2]=’-’
andcode[3]==' ‘
. We end up with the following lists and afeedback
list is returned:
code: [ , , black, ]
guess: [ -, -, -, green]
Here is how I implemented the provideFeedback
method in my code:
Another method in the same class is _checkWinnerStatus
. This method simply checks if the feedback
list consists of all ‘reds.’ If so, a winner code is returned. If not, the game prints the feedback
list for the player.
Main.py
Main is the point of execution of the entire game. The steps to code it are as follows:
- Import all necessary modules
- Print a welcome message
- Ask for whether the player wants to play with a bot
- Generate or enter code (if code is manually entered, clear the console)
- Let player guess and print feedback for the guess
- Reduce the number of guesses by 1 for any valid guess
The Gameflow
The above example is for a code breaker who chooses to play with another player and not a bot. Once Player 2 enters the code, the console is cleared to hide the code from the code breaker. This is what follows:
Once the player wins, a winning message is displayed:
This project was solely coded by me for Hack Day for the SF campus at Holberton school.
Find the code and instructions to play on my GitHub repo here. Happy coding!