HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Monty Hall Simulator - Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simulatorhallpythonmonty

Problem

I'm pretty new to Python (I've been doing it for about 4 months, but not every day) and I've been struggling to get to grips with how to use functions and deploy them efficiently to solve problems. To test my abilities, I created the below program to simulate the Monty Hall problem. The program does the following things:

  • It chooses a winning door at the start from list door = [1,2,3].



  • It then asks the user to choose a door.



  • Then it checks to see if the user's guess matches the winning door.



  • If the user guesses the winning door, it randomly selects one of the two remaining doors to 'open'. If, however, the user doesn't guess the winning door, it 'opens' the one remaining unpicked door.



  • It then asks the user if they want to switch doors. If the user picked the correct door first time out, then sticking with that choice wins the game and switching loses. The reverse is true if the user didn't pick the correct door first time.



  • Finally, it updates a running tally of wins and losses, then asks the user if he wants to play again.



The program works and the probabilities are correct (I ran it 100 times just to make sure and got 74 wins and 26 losses, which is around about what I'd expect). I'm just not sure the program is as efficient as it could be. In fact, given my relative lack of experience I'm pretty sure it isn't. Would anyone be able to tell me how good they think the code is, how I could go about improving it?

```
import random

win = 0
lose = 0

while True:

door = [1,2,3]
x = 0

def pick_answer():
"""Computer chooses the winning door"""
answer = random.choice(door)
return answer
a = pick_answer()

def pick_guess():
"""User guesses winning door"""
guess = int(input("Please choose a door (1-3): ").strip())
return guess
b = pick_guess()

if a == b:
def montys_door_if_a_is_b():
"""If answer = guess, pick one of the remaining doors to open"""

Solution

Functions should be used to cut down on code repetition so as to make code more concise and more readable. But you are constantly defining functions only to immediately invoke them once on the very next line. That makes the code less concise and less readable, and also forces you to introduce superfluous global variables. (It also seems like a JavaScript idiom -- are you coming from that language?) The code can be made more concise like this:

import random

win = 0
lose = 0
playing = True

while playing:

    door = [1,2,3]
    x = 0
    a = random.choice(door) #Computer chooses the winning door
    b = int(input("Please choose a door (1-3): ")) #User guesses winning door -- .strip() is pointless
    if a == b:
        #If answer = guess, pick one of the remaining doors to open
        door.remove(a)
        x = random.choice(door)
        c = x
        print("You chose door {}".format(b))
        print("I choose door {}".format(c))

        #Tells user which 2 doors are now left:
        door = [1,2,3]
        door.remove(x)
        door.remove(a)
        d = door[0]
        print("You're left with doors {} and {}".format(b,d))
        choice = input("Will you SWITCH to door {}? y/n: ".format(d)) 

        #Ask user if they want to switch. y = Lose / n = win
        if choice == "y":
            print("Bad luck.  You lost.  You should have stuck as you already had the right answer.")
            lose += 1
        else:
            print("Huzzah! You made the right choice by STICKING!")
            win += 1
        print("{} wins and {} losses".format(win,lose))
    else:
        #If answer != guess, remove answer & guess and 'open' the remaining door
        door.remove(a)
        door.remove(b)
        e = door[0]
        print("You chose door {}".format(b))
        print("I choose door {}".format(e))

        #Ask user to choose between answer & guess
        print("You're left with doors {} and {}".format(a,b))
        choice = input("Will you SWITCH to door {}? y/n: ".format(a)) 

        #Since answer != guess, if user sticks, he loses but if he switches he wins
        if choice == "y":
            print("HUZZAH!  YOU WIN")
            win +=1
        else:
            print("Bad luck.  You should have switched. You chose the wrong door at the start")
            lose += 1
        print("{} wins and {} losses".format(win,lose))

    ans = input("\nPress Enter to play again, 'q' to quit")
    if len(ans) > 0: playing = False


A few other points:

1) int() strips its input -- so the .strip() there was pointless

2) You are setting door = [1,2,3] more often than needed

3) Things like win = win + 1 were replaced by win += 1

4) The line print("{} wins and {} losses".format(win,lose)) was moved to after then if statement

5) montys_final_choice_if_a_not_b had absolutely no effect and was simply removed

6) I made it so that it you can break out of the infinite loop without closing the Python shell.

There are still improvements that can be made. In particular, you should find a way so that the code for the dialogue to switch doors occurs only once rather than twice, but this should be enough to get you started.

Code Snippets

import random

win = 0
lose = 0
playing = True

while playing:

    door = [1,2,3]
    x = 0
    a = random.choice(door) #Computer chooses the winning door
    b = int(input("Please choose a door (1-3): ")) #User guesses winning door -- .strip() is pointless
    if a == b:
        #If answer = guess, pick one of the remaining doors to open
        door.remove(a)
        x = random.choice(door)
        c = x
        print("You chose door {}".format(b))
        print("I choose door {}".format(c))

        #Tells user which 2 doors are now left:
        door = [1,2,3]
        door.remove(x)
        door.remove(a)
        d = door[0]
        print("You're left with doors {} and {}".format(b,d))
        choice = input("Will you SWITCH to door {}? y/n: ".format(d)) 

        #Ask user if they want to switch. y = Lose / n = win
        if choice == "y":
            print("Bad luck.  You lost.  You should have stuck as you already had the right answer.")
            lose += 1
        else:
            print("Huzzah! You made the right choice by STICKING!")
            win += 1
        print("{} wins and {} losses".format(win,lose))
    else:
        #If answer != guess, remove answer & guess and 'open' the remaining door
        door.remove(a)
        door.remove(b)
        e = door[0]
        print("You chose door {}".format(b))
        print("I choose door {}".format(e))

        #Ask user to choose between answer & guess
        print("You're left with doors {} and {}".format(a,b))
        choice = input("Will you SWITCH to door {}? y/n: ".format(a)) 

        #Since answer != guess, if user sticks, he loses but if he switches he wins
        if choice == "y":
            print("HUZZAH!  YOU WIN")
            win +=1
        else:
            print("Bad luck.  You should have switched. You chose the wrong door at the start")
            lose += 1
        print("{} wins and {} losses".format(win,lose))

    ans = input("\nPress Enter to play again, 'q' to quit")
    if len(ans) > 0: playing = False

Context

StackExchange Code Review Q#162177, answer score: 2

Revisions (0)

No revisions yet.