Monty Hall Problem’s Simulation Using Pygame
In this article, we are going to see how to create Monty Hall games using Pygame in Python. Monty Hall was a game show of the American television game show Let’s Make a Deal.
Suppose you’re on a game show, and you’re given the choice of three doors, Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what’s behind the doors, opens another door, say No. 3, which has a goat. He then says to you, “Do you want to pick door No. 2?” Is it to your advantage to switch your choice?
Demo of what the end product would look like:
Please ensure that the images and the audio used are present in the same folder as the Python file. The images and the audio can be downloaded from here.
Work Flow and Logic
The entire simulation can be condensed into the following points:
- Since there are three doors, a random permutation of the numbers 1, 2, 3 would be generated, each number representing the door number. The first two numbers of this randomly generated permutation would correspond to the doors behind which goats are present, and the third number would be the door number behind which there is a car.
- Once the configuration is generated, the same is represented graphically through images. There is an image for each configuration.
- There is one point to be taken care of — according to the puzzle, after the user has chosen a door number, only the door behind which there is a goat is to be revealed. So, if the user selects the door behind which there is a car, then any of the two remaining doors can be revealed. However, if the user selects a door behind which there is a goat, only one of the two remaining doors can be revealed (as it is not permissible to reveal the door that the user has selected).
Making Imports and Generating Configuration
Only two external modules are needed for this simulation pygame and random. At the beginning of every Pygame program, it is necessary to initialize Pygame by writing pygame.init(). The X and Y values refer to the dimensions of the window in which the simulation would run. These values can be altered based on the desired resolution and the images used. The list, doors, have values between 1 and 3 (inclusive). The order of these values would jumbled each time the program is run. This is done in order to assign the doors behind which there will be goats. According to the problem, there are a total of three doors behind two of these doors, there would be goats, and behind the third door, there would be a car. The variables goat1 and goat2 hold the door numbers behind which there would be goats. These numbers are then added to a list called goats. The third number is assigned to the variable, car.
Adding Background and Music
The display_surface variable is like a canvas, upon which we would be adding entities (images, text etc.) as per the requirements. The argument passed through the display.set_caption function would be the title of the simulation window. The image that is to be shown at first — all three doors closed is loaded. A Boolean variable, change, is used to record changes. The function music is optional to have. Its function is to produce click sound whenever the user presses on a door. Be sure to have the mp3 file of whatever music is wished to be played. The function performs three steps initialize, load and play.
Updating Image Based on the User’s Input
The show_car function may seem a bit cumbersome, but its functionality is fairly trivial. It aims to display the image of the appropriate orientation, i.e., if the car is behind door 3, the image corresponding to that orientation (car at position 3) would be displayed. All the images are available (along with the names used in the code) at the end of this article. The state parameter tells the outcome of the simulation.
There are four possible outcomes:
It is necessary to use pygame.display.update() for any display changes to take place. The font and font size can be altered by changing the parameters in the my_font variable. The first argument of display_surface.blit is the image that is to be rendered, and the second argument is a tuple denoting the X and Y coordinates. my_font has an attribute render used for displayed text. The first argument is the text that is to be displayed, and the third argument is a tuple containing RGB values for specifying the color of the text. display_surface.blit is used to render the text specified by render onto the canvas. The first argument is the specifications of the text, and the second argument has the X and Y coordinates. In order to find the coordinates, use:
This will create a crosshair and the coordinates of the points clicked would be known.
Main Loop and Handling Clicks
Every game contains an infinite loop (while True). It is checked if the type of event registered is QUIT, i.e. the user has closed the Pygame window. In that case, the program terminates. pygame.MOUSEBUTTONDOWN refers to the event of left-clicking a mouse. The if conditions are used to determine the door that has been pressed by the user (based on the coordinates) and the door number is assigned to the variable, user. For example, if the X coordinate (event.pos) of the point where the click has occurred is between 71 and 203, and the Y coordinate (event.pos) is between 387 and 633, register the click has a click on door 1. The clicked Boolean is set to True whenever one of the three doors is clicked.
Loading all Valid Configurations (Images) and Generating Position of Goats
Once a valid click is registered, the six images are loaded. it is checked if the user has clicked on a door that has a goat behind it. As the door selected by the user cannot be opened and the door that can be opened must contain a goat behind it, there is only one possible door that can be opened. Say, goats are behind doors 1 and 2, and the user clicks on door 1, as door 1 cannot be opened, door 2 is the only door that can be opened. The variable, g, stores the valid door that can be opened. If the user did not select a door that has a goat behind it, a goat is randomly assigned using the randint function, and storing either 1 or 0 in the variable, wr.
The variable, user2, stores whether the user chose to stay or switch. The Boolean, clicked2, stores whether the click for determining the choice (stay or switch) has been registered or not.
Displaying Result (Text) Based on the User’s Input
Once the user has selected, it is determined whether they have won or not (whether there is a car behind the door they ultimately chose). Determining the winner can be understood by the following table:
|Action||Initial Selection (Goat or car)||Result|
Below is the complete implementation: