Related
im new in Python and i'm self learner. Actually im trying to create easy word game.
Currently im in stage when im adding monster/player damage and I have three problems which i can't figure out.
I want every room to have a chance for a random monster to appear from "Monster" dictionary. However, after meeting a monster for the first time, the value of his life after the fight is overwritten in the dictionary. This causes the monster to have a negative life when you meet it again. How to fix it?
When i'll find monster in any room, I have set two options "run" and "fight". When someone will type any other command, the loop returns to the draw whether a monster or a chest will appear in the room. I want the return to occur until after the event is randomly selected
I have problem with placing command
if playerLife <= 0:
print("You died, your body will lay in chambers forever")
break
I want to end game immidiatly after players dead.
import random
from enum import Enum
playerDamage = 4
playerLife = 100
def find_aprox_value(value):
lowestValue = 0.9 * value
highestValue = 1.1 * value
return random.randint(lowestValue, highestValue)
def weapon_hit(chance):
if_hit = random.uniform(1, 100)
if if_hit < chance:
monsterLife[drawnMonster] = monsterLife[drawnMonster] - playerDamage
print("You hit a monster and you dealt 4 damage. It has", monsterLife[drawnMonster], " life")
else:
print("You missed")
def monster_hit():
global playerLife
monsterHit = monsterDamage[drawnMonster]
print("Monster did", monsterDamage[drawnMonster], "damage")
playerLife = playerLife - monsterHit
print("You have ", playerLife, "life")
Event = Enum('Event', ['Chest', 'Monster'])
Chest = Enum('Chest', {'greenChest': 'zieloną skrzynię',
'blueChest': 'niebieską skrzynię',
'violetChest': 'fioletową skrzynię',
'orangeChest': 'pomarańczową skrzynię'
})
Monster = Enum('Monster', {'Rat': 'Szczura',
'Bat': 'Nietoperza',
'GiantSpider': 'Ogromnego Pająka',
'Wolf': 'Wilka',
})
Color = Enum('Color', ['greenChest', 'blueChest', 'violetChest', 'orangeChest'])
MonsterKind = Enum('MonsterKind', ['Rat', 'Bat', 'GiantSpider', 'Wolf'])
eventDictionary = {
Event.Chest: 0.4,
Event.Monster: 0.6
}
eventList = list(eventDictionary.keys())
eventProbability = list(eventDictionary.values())
chestDictionary = {
Chest.greenChest: 0.5,
Chest.blueChest: 0.3,
Chest.violetChest: 0.15,
Chest.orangeChest: 0.05
}
PremiumChestDictionary = {
Chest.blueChest: 0.5,
Chest.violetChest: 0.35,
Chest.orangeChest: 0.15
}
MonsterDictionary = {
Monster.Rat: 0.5,
Monster.Bat: 0.3,
Monster.GiantSpider: 0.15,
Monster.Wolf: 0.05
}
chestList = list(chestDictionary.keys())
chestProbability = list(chestDictionary.values())
MonsterList = list(MonsterDictionary.keys())
MonsterProbability = list(MonsterDictionary.values())
PremiumChestList = list(PremiumChestDictionary.keys())
PremiumChestProbability = list(PremiumChestDictionary.values())
colorValue = {
Chest.greenChest: 1000,
Chest.blueChest: 4000,
Chest.violetChest: 9000,
Chest.orangeChest: 16000
}
monsterLife = {
Monster.Rat: 5,
Monster.Bat: 10,
Monster.GiantSpider: 15,
Monster.Wolf: 30
}
monsterDamage = {
Monster.Rat: 3,
Monster.Bat: 5,
Monster.GiantSpider: 8,
Monster.Wolf: 12
}
gameLength = 10
Gold = 0
while gameLength > 0:
gameAnswer = input("Do you want to move forward? \n")
if gameAnswer == "yes":
print("Great, lets see what is inside")
drawnEvent = random.choices(eventList, eventProbability)[0]
if drawnEvent == Event.Chest:
drawnChest = random.choices(chestList, chestProbability)[0]
goldAcquire = find_aprox_value(colorValue[drawnChest])
print("You have find ", drawnChest.value, "inside was", goldAcquire, "gold")
Gold = Gold + goldAcquire
gameLength = gameLength - 1
elif drawnEvent == Event.Monster:
drawnMonster = random.choices(MonsterList, MonsterProbability)[0]
print("Oh no, you have find", drawnMonster.value, "which has", monsterLife[drawnMonster],
"life .If you will defeat him, you will find great treasure.")
eventAnswer = input(" What is your choice?(fight, run)")
if eventAnswer == "fight":
while monsterLife[drawnMonster] > 0:
weapon_hit(70)
if monsterLife[drawnMonster] > 0:
monster_hit()
if playerLife <= 0:
print("You died, your body will lay in chambers forever")
break
drawnPremiumChest = random.choices(PremiumChestList, PremiumChestProbability)[0]
goldAcquire = find_aprox_value(colorValue[drawnPremiumChest])
print("Congratulations, you have defeat a monster, and you found", drawnPremiumChest.value,
", inside was", goldAcquire, " gold")
Gold = Gold + goldAcquire
gameLength = gameLength - 1
elif eventAnswer == "run":
gameLength = gameLength - 1
print("you have successfully run")
else:
print("Only options is run or fight")
continue
else:
print("Your only options is move forward")
continue
print("Congratulations you have acquired", Gold, "gold")
As I mentioned at the beginning, I am just starting to learn python and this is my first post on this forum, so please be understanding and thank you for your help in advance.
There are many solutions to your problem (at least five). Here are the simplest:
The simplest: Instead of break, you can end the program with sys.exit (0) (with code 0 because it's not an error).
More elegant:
# Outer loop:
while gameLength > 0 and playerLife > 0:
# Inner loop:
while monsterLife[drawnMonster] > 0 and playerLife > 0:
# Statement 'if playerLife <= 0' becomes redundant
# Outside the loop:
if playerLife > 0:
print("Congratulations ...")
else:
print("You died, ...")
or:
# Outer loop:
while gameLength > 0 and playerLife > 0:
# Inner loop:
while monsterLife[drawnMonster] > 0:
if playerLife <= 0:
break
# Outside the loop:
if playerLife > 0:
print("Congratulations ...")
else:
print("You died, ...")
More advanced: instead of using break statement, an exception can be thrown. The exception must be handled by the try ... catch statement.
BTW: both continue statements are completely unnecessary - these are the last statements of the loop, so they don't change anything about the execution of the loop.
Have fun with Python.
The title is terrible, but hopefully I can explain in my post. Creating a little game as my pet project for python, and I'm currently creating the inventory. Everything was... ok when developing the game until it came to making the function that will show all of the player's inventory.
elif (prompt == "examine"):
print(inventory[1].name)
gameprompt()
Ok, so I created a list that basically has a bunch of classes from Items in it. To call on the name element of these classes I have to do something like this, otherwise I just get its memory location which is largely useless to the player. I've tried
elif (prompt == "examine"):
print(inventory[].name)
gameprompt()
Thought that this above example would print only the name of all the Item objects, but there's a compilation error instead because I didn't specify which one. So I then tried~
elif (prompt == "examine"):
print(inventory[1:1000].name)
gameprompt()
Thinking that it would print all of the Item objects names up to 1000, but I obviously don't have that so I thought it would print the names up to the latest object that was there and stop but there was another compilation error from this...
If there is anyway to print out an element of a class for all class objects in a list please let me know. The full code of this game is here, although I don't think you'll need it to help me solve my problem (it is also very large.)
playername = input("What is your name?")
zone = 1
movement = 0
restcounter = 0
searchcounter = 0
class Player:
def __init__(self, name, hp, mp, atk, xp, dodgerate, atkrate):
self.name = playername
self.hp = hp
self.mp = mp
self.atk = atk
self.xp = xp
self.dodgerate = dodgerate
self.atkrate = atkrate
class Enemy(Player):
def __init__(self, name, gold, maxhp, hp, mp, atk, xp):
self.name = name
self.gold = gold
self.maxhp = maxhp
self.hp = hp
self.mp = mp
self.atk = atk
self.xp = xp
class Items:
def __init__(self, name, quantity, description, price, weight):
self.name = name
self.quantity = quantity
self.description = description
self.price = price
self.weight = weight
Player = Player(playername, 1, 1, 1, 1, 25, 3)
print(Player.name + " has been created. ")
def raceselection():
raceinput = input("Do you float towards the TEMPLE, CAVE or FOREST?")
if raceinput == "TEMPLE":
print("You are now a high elf. High elves utlize a lot of magical power at the cost of being very frail.")
Player.hp = Player.hp + 24
Player.mp = Player.mp + 100
Player.atk = Player.atk + 50
print("You awaken from your slumber. Your room's walls are gold plated, and you rested on a flat board.")
print("Out the door, you see many elves with robes praying to some goddess.")
print("You walk out of your door and into the praying area. You are immediately greeted by a tall man.")
elif raceinput == "CAVE":
print("You are now an orc.")
Player.hp = Player.hp + 1000
Player.mp = Player.mp + 15
Player.atk = Player.atk + 50
print("cave")
elif raceinput == "FOREST":
print("You are now a human.")
Player.hp = Player.hp + 50
Player.mp = Player.mp + 25
Player.atk = Player.atk + 25
else:
print("You can't float there!")
raceselection()
raceselection()
inventory = []
def gameprompt():
global inventory
global zone
global movement
global restcounter
global searchcounter
if (movement == 5):
movement = movement - movement
zone = zone + 1
print("You have advanced to zone",zone,"!!!")
gameprompt()
if (zone == 1):
print("Welcome to the first zone! Easy enemies are here with not very good loot./fix grammar, add description of zone/")
elif (zone == 2):
print("Hey, it actually travelled to the second zone, awesome!")
elif (zone == 3):
print("No way would this actually work!")
prompt = input("Would you like to walk, search or rest?: ")
if (prompt == "walk"):
encounterchance = random.randint(1, 3)
if (encounterchance == 2):
if (zone == 1):
mobspawnrate = random.randint(1,3)
if (mobspawnrate == 1):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
elif (mobspawnrate == 2):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
elif (mobspawnrate == 3):
Enemy = Enemy("Blue SlimeBall", 50, 0, 25, 15, 25, 0.500)
print("You have encountered a " + Enemy.name + "!!!")
else:
movement = movement + 1
print("You have walked a step. You are now at ",movement," steps")
gameprompt()
elif (prompt == "search"):
if (searchcounter == 3):
print("You cannot search this area anymore! Wait until you reach the next zone!")
gameprompt()
else:
searchchance = random.randint(1, 5)
if (searchchance == 1 or 2 or 3 or 4):
searchcounter = searchcounter + 1
print(searchcounter)
print("You have found something!")
searchchance = random.randint(1,4)
if (searchchance == 1 or 2):
inventory.append(Items("Old Boot", 1, "An old smelly boot. It's a mystery as to who it belongs to...", 5, 50))
print("You have found a Boot!")
print(inventory)
elif(searchchance == 3):
inventory.append(Items("Shiny Boot", 1, "Looks like a boot that was lightly worn. You could still wear this.", 5, 50))
print(inventory)
print("You have found a Shiny Boot!")
elif(searchchance == 4):
inventory.append(Items("Golden Boot", 1, "It's too heavy to wear, but it looks like it could sell for a fortune!", 5, 50))
print("You have found a Golden Boot?")
print(inventory)
else:
searchcounter = searchcounter + 1
print(searchcounter)
print("You did not find anything of value")
gameprompt()
elif (prompt == "rest"):
if (restcounter == 1):
print("Wait until you reach the next zone to rest again!")
gameprompt()
else:
# Add a MaxHP value to the player later, and the command rest will give 25% of that HP back.
Player.hp = Player.hp + (Player.hp / 5)
print("You have restored ",(Player.hp / 5)," hit points!")
restcounter = restcounter + 1
gameprompt()
elif (prompt == "examine"):
print(inventory[1].name)
gameprompt()
gameprompt()
A list comprehension or map would work perfectly here:
print([item.name for item in inventory])
The comprehension iterates the list, and "replaces" each element in the list with whatever the part before for evaluates to. In this case, it's item.name.
° It actually doesn't replace the element in the original list. It evaluates to a new list full of replaced items.
I have been making a text-based game. I have gotten to a point where I am trying to do a battle. I have the enemy's hp going down but when I hit it again, the enemy's hp is back to what I had originally set it as. I hope these help.
while do != 'hit rat with sword' or 'run away':
enemyhp= 50
enemyattack= [0,1,3]
OldSwordattack= [0,1,4]
print('What do you do?(attack or run away)')
do=input()
if do == 'run away':
print('You can\'t leave mom like that!')
if do == 'hit rat with sword':
hit= random.choice(OldSwordattack)
if hit == OldSwordattack[0]:
print('Your swing missed')
print('Enemy\'s HP=' + str(enemyhp))
if hit == OldSwordattack[1]:
print('Your swing hit, but very lightly.')
enemyhp= enemyhp - 1
print('Enemy\'s HP=' + str(enemyhp))
if hit == OldSwordattack[2]:
print('Your swing hit head on!')
enemyhp= enemyhp - 4
print('Enemy\'s HP=' + str(enemyhp))
>In front of mom you see a giant, yellow-teethed rat.
>What do you do?(attack or run away)
>hit rat with sword
>Your swing hit, but very lightly.
>Enemy's HP=49
>What do you do?(attack or run away)
>hit rat with sword
>Your swing hit, but very lightly.
>Enemy's HP=49
>What do you do?(attack or run away)
You see? The above is the program running. I do not see why the value is not being changed.
because you are initializing it at the beginning of the iteration. So just move the
enemyhp= 50
before the while loop, like this
enemyhp= 50
while do != 'hit rat with sword' or 'run away':
Just for fun I've extended your example program to include some more advanced language constructs. May you find it entertaining: (Python 3)
import random
import re
def dice(s, reg=re.compile('(\d+d\d+|\+|\-|\d+)')):
"""
Executes D+D-style dice rolls, ie '2d6 + 3'
"""
total = 0
sign = 1
for symbol in reg.findall(s):
if symbol == '+':
sign = 1
elif symbol == '-':
sign = -1
elif 'd' in symbol:
d,s = [int(k) for k in symbol.split('d')]
for i in range(d):
total += sign * random.randint(1, s)
else:
total += sign * int(symbol)
return total
class Character():
def __init__(self, name, attack, defense, health, weapon):
self.name = name
self.attack = attack
self.defense = defense
self.health = health
self.weapon = weapon
def hit(self, target):
if self.is_dead:
print('{} is trying to become a zombie!'.format(self.name))
return 0
attack = self.attack + self.weapon.attack_bonus + dice('2d6')
defense = target.defense + dice('2d6')
if attack > defense:
damage = int(random.random() * min(attack - defense + 1, self.weapon.damage + 1))
target.health -= damage
print('{} does {} damage to {} with {}'.format(self.name, damage, target.name, self.weapon.name))
return damage
else:
print('{} misses {}'.format(self.name, target.name))
return 0
#property
def is_dead(self):
return self.health <= 0
class Weapon():
def __init__(self, name, attack_bonus, damage):
self.name = name
self.attack_bonus = attack_bonus
self.damage = damage
def main():
name = input("So, what's your name? ")
me = Character(name, 4, 6, 60, Weapon('Old Sword', 2, 4))
mom = Character('Mom', 2, 2, 50, Weapon('Broom', 0, 1))
rat = Character('Crazed Rat', 5, 2, 40, Weapon('Teeth', 1, 2))
print("You are helping your mother clean the basement when a Crazed Rat attacks. "
"You grab your Grandfather's sword from the wall and leap to defend her!")
actors = {me, mom, rat}
coward = False
killer = None
while (me in actors or mom in actors) and rat in actors:
x = random.choice(list(actors))
if x is mom:
mom.hit(rat)
if rat.is_dead:
killer = mom
actors -= {rat}
elif x is rat:
target = random.choice(list(actors - {rat}))
rat.hit(target)
if target.is_dead:
actors -= {target}
if target is mom:
print('Your mother crumples to the floor. AARGH! This rat must die!')
me.attack += 2
else:
print('Well... this is awkward. Looks like Mom will have to finish the job alone...')
else: # your turn!
print('Me: {}, Mom: {}, Rat: {}'.format(me.health, 0 if mom.is_dead else mom.health, rat.health))
do = input('What will you do? [hit] the rat, [run] away, or [swap] weapons with Mom? ')
if do == 'hit':
me.hit(rat)
if rat.is_dead:
killer = me
actors -= {rat}
elif do == 'run':
if me.health < 20:
actors -= {me}
coward = True
else:
print("Don't be such a baby! Get that rat!")
elif do == 'swap':
me.weapon, mom.weapon = mom.weapon, me.weapon
print('You are now armed with the {}'.format(me.weapon.name))
else:
print('Stop wasting time!')
if rat.is_dead:
if mom.is_dead:
print('The rat is gone - but at a terrible cost.')
elif me.is_dead:
print("Your mother buries you with your trusty sword by your side and the rat at your feet.")
elif coward:
print("The rat is gone - but you'd better keep running!")
elif killer is me:
print("Hurrah! Your mother is very impressed, and treats you to a nice cup of tea.")
else:
print('Your mother kills the rat! Treat her to a nice cup of tea before finishing the basement.')
else:
print('I, for one, hail our new rat overlords.')
if __name__=="__main__":
main()
So I have to create a game of craps that takes into account bets for an assignment. So far, my code works in that the dice rolls are correct and other little tidbits the assignment called for. But now I don't know how to record each game as a win / lose for the player or computer so that the pot can be added to the winner's money. I realize that my code is half doe, isn't finished, and doesn't run as is, but I just seriously need some help from someone. Please and thank you. Here are more specific directions on my assignment:
http://www.ics.uci.edu/~kay/courses/i42/hw/labA.html
import random
def craps():
print("Welcome to Sky Masterson's Craps Game")
handle_commands()
def handle_commands(): # Collection -> Collection (plus interaction)
""" Display menu to user, accept and process commands
"""
playerInitial = 500
compInitial = 500
MENU = "How much would you like to bet?: "
while True:
bet = float(input(MENU))
if bet <= playerInitial:
human_game()
elif bet > playerInitial:
print("Sorry, you can't bet more than you have")
def handle_commands2():
MENU2 = "Would you like to play again? (y or n): "
while True:
response = input (MENU2)
if response=="y":
counter = counter + multipleGames()
elif response=="n":
while ( counter < 2000):
roll = random.randint(1, 6) + random.randint(1,6)
updateCount(roll)
counter += 1
print ("Thank you for playing." + "\n" + "\n" + "Distribution of dice rolls: " + "\n")
return
else:
invalid_command(response)
def invalid_command(reponse):
"""print message for invalid menu command.
"""
print("Sorry; '" + response + "' isn't a valid command. Please try again.")
def play_game():
"""prints shooters roll results
"""
diceRoll = 0
roll = random.randint(1, 6) + random.randint(1, 6)
updateCount(roll)
diceRoll = diceRoll + 1
point = 0
print("The roll is " + str(roll))
response = (roll)
if response== 7 or response== 11:
print("Natural; shooter wins" + "\n" + "Thank you for playing")
handle_commands2()
elif response== 2 or response== 3 or response== 12:
print("Crapped out; shooter loses" + "\n" + "Thank you for playing")
handle_commands2()
else:
print("The point is " + str(roll))
point = roll
secondRoll = 0
handle_commands()
while (secondRoll !=point) and (secondRoll != 7):
secondRoll = random.randint(1, 6) + random.randint(1, 6)
updateCount(secondRoll)
diceRoll += 1
print("The roll is " + str(secondRoll))
handle_commands()
if secondRoll== point:
print ("Made the point; shooter wins." + "\n" + "Thank you for playing")
handle_commands2()
elif (secondRoll == 7):
print ("Crapped out; shooter loses." + "\n" + "Thank you for playing")
handle_commands2()
return diceRoll
def multipleGames():
gameCounter = 0
while (gameCounter <= 2000):
print("Your game: ")
gameCounter += play_game()
print("\n")
print("Computer's game: ")
gameCounter += play_game()
print( "\n")
return gameCounter
def updateCount(point):
count =List[point] + 1
List[point] = count
List = {2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0}
def human_game():
playerInitial = 500
compInitial = 500
while True:
play_game()
if
playerInitial += bet
compInitial += bet
counter = 0
counter = counter + multipleGames()
playerInitial -= bet
craps()
for point in List:
print("%2d" %(point) + ": " + "%3d" %(List[point]) + " " + "(" + ("%2d" % (int((List[point])/2000*100)))+ "%" + ")" + " " + ("*" *(int((List[point])/2000*100))))
Use classes:
import random
class Human:
def __init__(self):
self.name = 'Human'
self.wins = []
self.losses = []
self.bets = []
self.total = 0
class Computer:
def __init__(self):
self.name = 'Computer'
self.wins = []
self.losses = []
self.bets = []
self.total = 0
class Game:
def __init__(self):
self.rolls = []
self.currentPlayer = None
def roll(self):
self.rolls.append(random.randint(1, 6))
if __name__ == '__main__':
human = Human()
computer = Computer()
game = Game()
game.roll()
print games.rolls
I won't code all of it for you, but using classes will make things much simpler.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Through trying to explain the Monty Hall problem to a friend during class yesterday, we ended up coding it in Python to prove that if you always swap, you will win 2/3 times. We came up with this:
import random as r
#iterations = int(raw_input("How many iterations? >> "))
iterations = 100000
doors = ["goat", "goat", "car"]
wins = 0.0
losses = 0.0
for i in range(iterations):
n = r.randrange(0,3)
choice = doors[n]
if n == 0:
#print "You chose door 1."
#print "Monty opens door 2. There is a goat behind this door."
#print "You swapped to door 3."
wins += 1
#print "You won a " + doors[2] + "\n"
elif n == 1:
#print "You chose door 2."
#print "Monty opens door 1. There is a goat behind this door."
#print "You swapped to door 3."
wins += 1
#print "You won a " + doors[2] + "\n"
elif n == 2:
#print "You chose door 3."
#print "Monty opens door 2. There is a goat behind this door."
#print "You swapped to door 1."
losses += 1
#print "You won a " + doors[0] + "\n"
else:
print "You screwed up"
percentage = (wins/iterations) * 100
print "Wins: " + str(wins)
print "Losses: " + str(losses)
print "You won " + str(percentage) + "% of the time"
My friend thought this was a good way of going about it (and is a good simulation for it), but I have my doubts and concerns. Is it actually random enough?
The problem I have with it is that the all choices are kind of hard coded in.
Is this a good or bad 'simulation' for the Monty Hall problem? How come?
Can you come up with a better version?
Your solution is fine, but if you want a stricter simulation of the problem as posed (and somewhat higher-quality Python;-), try:
import random
iterations = 100000
doors = ["goat"] * 2 + ["car"]
change_wins = 0
change_loses = 0
for i in xrange(iterations):
random.shuffle(doors)
# you pick door n:
n = random.randrange(3)
# monty picks door k, k!=n and doors[k]!="car"
sequence = range(3)
random.shuffle(sequence)
for k in sequence:
if k == n or doors[k] == "car":
continue
# now if you change, you lose iff doors[n]=="car"
if doors[n] == "car":
change_loses += 1
else:
change_wins += 1
print "Changing has %s wins and %s losses" % (change_wins, change_loses)
perc = (100.0 * change_wins) / (change_wins + change_loses)
print "IOW, by changing you win %.1f%% of the time" % perc
a typical output is:
Changing has 66721 wins and 33279 losses
IOW, by changing you win 66.7% of the time
You mentioned that all the choices are hardcoded in. But if you look closer, you'll notice that what you think are 'choices' are actually not choices at all. Monty's decision is without loss of generality since he always chooses the door with the goat behind it. Your swapping is always determined by what Monty chooses, and since Monty's "choice" was actually not a choice, neither is yours. Your simulation gives the correct results..
I like something like this.
#!/usr/bin/python
import random
CAR = 1
GOAT = 0
def one_trial( doors, switch=False ):
"""One trial of the Monty Hall contest."""
random.shuffle( doors )
first_choice = doors.pop( )
if switch==False:
return first_choice
elif doors.__contains__(CAR):
return CAR
else:
return GOAT
def n_trials( switch=False, n=10 ):
"""Play the game N times and return some stats."""
wins = 0
for n in xrange(n):
doors = [CAR, GOAT, GOAT]
wins += one_trial( doors, switch=switch )
print "won:", wins, "lost:", (n-wins), "avg:", (float(wins)/float(n))
if __name__=="__main__":
import sys
n_trials( switch=eval(sys.argv[1]), n=int(sys.argv[2]) )
$ ./montyhall.py True 10000
won: 6744 lost: 3255 avg: 0.674467446745
Here's my version ...
import random
wins = 0
for n in range(1000):
doors = [1, 2, 3]
carDoor = random.choice(doors)
playerDoor = random.choice(doors)
hostDoor = random.choice(list(set(doors) - set([carDoor, playerDoor])))
# To stick, just comment out the next line.
(playerDoor, ) = set(doors) - set([playerDoor, hostDoor]) # Player swaps doors.
if playerDoor == carDoor:
wins += 1
print str(round(wins / float(n) * 100, 2)) + '%'
Here is an interactive version:
from random import shuffle, choice
cars,goats,iters= 0, 0, 100
for i in range(iters):
doors = ['goat A', 'goat B', 'car']
shuffle(doors)
moderator_door = 'car'
#Turn 1:
selected_door = choice(doors)
print selected_door
doors.remove(selected_door)
print 'You have selected a door with an unknown object'
#Turn 2:
while moderator_door == 'car':
moderator_door = choice(doors)
doors.remove(moderator_door)
print 'Moderator has opened a door with ', moderator_door
#Turn 3:
decision=raw_input('Wanna change your door? [yn]')
if decision=='y':
prise = doors[0]
print 'You have a door with ', prise
elif decision=='n':
prise = selected_door
print 'You have a door with ', prise
else:
prise = 'ERROR'
iters += 1
print 'ERROR:unknown command'
if prise == 'car':
cars += 1
elif prise != 'ERROR':
goats += 1
print '==============================='
print ' RESULTS '
print '==============================='
print 'Goats:', goats
print 'Cars :', cars
My solution with list comprehension to simulate the problem
from random import randint
N = 1000
def simulate(N):
car_gate=[randint(1,3) for x in range(N)]
gate_sel=[randint(1,3) for x in range(N)]
score = sum([True if car_gate[i] == gate_sel[i] or ([posible_gate for posible_gate in [1,2,3] if posible_gate != gate_sel[i]][randint(0,1)] == car_gate[i]) else False for i in range(N)])
return 'you win %s of the time when you change your selection.' % (float(score) / float(N))
print simulate(N)
Not mine sample
# -*- coding: utf-8 -*-
#!/usr/bin/python -Ou
# Written by kocmuk.ru, 2008
import random
num = 10000 # number of games to play
win = 0 # init win count if donot change our first choice
for i in range(1, num): # play "num" games
if random.randint(1,3) == random.randint(1,3): # if win at first choice
win +=1 # increasing win count
print "I donot change first choice and win:", win, " games"
print "I change initial choice and win:", num-win, " games" # looses of "not_change_first_choice are wins if changing
I found this to be the most intuitive way of solving the problem.
import random
# game_show will return True/False if the participant wins/loses the car:
def game_show(knows_bayes):
doors = [i for i in range(3)]
# Let the car be behind this door
car = random.choice(doors)
# The participant chooses this door..
choice = random.choice(doors)
# ..so the host opens another (random) door with no car behind it
open_door = random.choice([i for i in doors if i not in [car, choice]])
# If the participant knows_bayes she will switch doors now
if knows_bayes:
choice = [i for i in doors if i not in [choice, open_door]][0]
# Did the participant win a car?
if choice == car:
return True
else:
return False
# Let us run the game_show() for two participants. One knows_bayes and the other does not.
wins = [0, 0]
runs = 100000
for x in range(0, runs):
if game_show(True):
wins[0] += 1
if game_show(False):
wins[1] += 1
print "If the participant knows_bayes she wins %d %% of the time." % (float(wins[0])/runs*100)
print "If the participant does NOT knows_bayes she wins %d %% of the time." % (float(wins[1])/runs*100)
This outputs something like
If the participant knows_bayes she wins 66 % of the time.
If the participant does NOT knows_bayes she wins 33 % of the time.
Read a chapter about the famous Monty Hall problem today. This is my solution.
import random
def one_round():
doors = [1,1,0] # 1==goat, 0=car
random.shuffle(doors) # shuffle doors
choice = random.randint(0,2)
return doors[choice]
#If a goat is chosen, it means the player loses if he/she does not change.
#This method returns if the player wins or loses if he/she changes. win = 1, lose = 0
def hall():
change_wins = 0
N = 10000
for index in range(0,N):
change_wins += one_round()
print change_wins
hall()
Updated solution
Update, this time using the enum module. Again, going for brevity while using the most expressive features of Python for the problem at hand:
from enum import auto, Enum
from random import randrange, shuffle
class Prize(Enum):
GOAT = auto()
CAR = auto()
items = [Prize.GOAT, Prize.GOAT, Prize.CAR]
num_trials = 100000
num_wins = 0
# Shuffle prizes behind doors. Player chooses a random door, and Monty chooses
# the first of the two remaining doors that is not a car. Then the player
# changes his choice to the remaining door that wasn't chosen yet.
# If it's a car, increment the win count.
for trial in range(num_trials):
shuffle(items)
player = randrange(len(items))
monty = next(i for i, p in enumerate(items) if i != player and p != Prize.CAR)
player = next(i for i in range(len(items)) if i not in (player, monty))
num_wins += items[player] is Prize.CAR
print(f'{num_wins}/{num_trials} = {num_wins / num_trials * 100:.2f}% wins')
Previous solution
Yet another "proof," this time with Python 3. Note the use of generators to select 1) which door Monty opens, and 2) which door the player switches to.
import random
items = ['goat', 'goat', 'car']
num_trials = 100000
num_wins = 0
for trial in range(num_trials):
random.shuffle(items)
player = random.randrange(3)
monty = next(i for i, v in enumerate(items) if i != player and v != 'car')
player = next(x for x in range(3) if x not in (player, monty))
if items[player] == 'car':
num_wins += 1
print('{}/{} = {}'.format(num_wins, num_trials, num_wins / num_trials))
Monty never opens the door with the car - that's the whole point of the show (he isn't your friend an has knowledge of what is behind each door)
Here is different variant I find most intuitive. Hope this helps!
import random
class MontyHall():
"""A Monty Hall game simulator."""
def __init__(self):
self.doors = ['Door #1', 'Door #2', 'Door #3']
self.prize_door = random.choice(self.doors)
self.contestant_choice = ""
self.monty_show = ""
self.contestant_switch = ""
self.contestant_final_choice = ""
self.outcome = ""
def Contestant_Chooses(self):
self.contestant_choice = random.choice(self.doors)
def Monty_Shows(self):
monty_choices = [door for door in self.doors if door not in [self.contestant_choice, self.prize_door]]
self.monty_show = random.choice(monty_choices)
def Contestant_Revises(self):
self.contestant_switch = random.choice([True, False])
if self.contestant_switch == True:
self.contestant_final_choice = [door for door in self.doors if door not in [self.contestant_choice, self.monty_show]][0]
else:
self.contestant_final_choice = self.contestant_choice
def Score(self):
if self.contestant_final_choice == self.prize_door:
self.outcome = "Win"
else:
self.outcome = "Lose"
def _ShowState(self):
print "-" * 50
print "Doors %s" % self.doors
print "Prize Door %s" % self.prize_door
print "Contestant Choice %s" % self.contestant_choice
print "Monty Show %s" % self.monty_show
print "Contestant Switch %s" % self.contestant_switch
print "Contestant Final Choice %s" % self.contestant_final_choice
print "Outcome %s" % self.outcome
print "-" * 50
Switch_Wins = 0
NoSwitch_Wins = 0
Switch_Lose = 0
NoSwitch_Lose = 0
for x in range(100000):
game = MontyHall()
game.Contestant_Chooses()
game.Monty_Shows()
game.Contestant_Revises()
game.Score()
# Tally Up the Scores
if game.contestant_switch and game.outcome == "Win": Switch_Wins = Switch_Wins + 1
if not(game.contestant_switch) and game.outcome == "Win": NoSwitch_Wins = NoSwitch_Wins + 1
if game.contestant_switch and game.outcome == "Lose": Switch_Lose = Switch_Lose + 1
if not(game.contestant_switch) and game.outcome == "Lose": NoSwitch_Lose = NoSwitch_Lose + 1
print Switch_Wins * 1.0 / (Switch_Wins + Switch_Lose)
print NoSwitch_Wins * 1.0 / (NoSwitch_Wins + NoSwitch_Lose)
The learning is still the same, that switching increases your chances of winning, 0.665025416127 vs 0.33554730611 from the above run.
Here's one I made earlier:
import random
def game():
"""
Set up three doors, one randomly with a car behind and two with
goats behind. Choose a door randomly, then the presenter takes away
one of the goats. Return the outcome based on whether you stuck with
your original choice or switched to the other remaining closed door.
"""
# Neither stick or switch has won yet, so set them both to False
stick = switch = False
# Set all of the doors to goats (zeroes)
doors = [ 0, 0, 0 ]
# Randomly change one of the goats for a car (one)
doors[random.randint(0, 2)] = 1
# Randomly choose one of the doors out of the three
choice = doors[random.randint(0, 2)]
# If our choice was a car (a one)
if choice == 1:
# Then stick wins
stick = True
else:
# Otherwise, because the presenter would take away the other
# goat, switching would always win.
switch = True
return (stick, switch)
I also had code to run the game many times, and stored this and the sample output in this repostory.
Here is my solution to the MontyHall problem implemented in python.
This solution makes use of numpy for speed, it also allows you to change the number of doors.
def montyhall(Trials:"Number of trials",Doors:"Amount of doors",P:"Output debug"):
N = Trials # the amount of trial
DoorSize = Doors+1
Answer = (nprand.randint(1,DoorSize,N))
OtherDoor = (nprand.randint(1,DoorSize,N))
UserDoorChoice = (nprand.randint(1,DoorSize,N))
# this will generate a second door that is not the user's selected door
C = np.where( (UserDoorChoice==OtherDoor)>0 )[0]
while (len(C)>0):
OtherDoor[C] = nprand.randint(1,DoorSize,len(C))
C = np.where( (UserDoorChoice==OtherDoor)>0 )[0]
# place the car as the other choice for when the user got it wrong
D = np.where( (UserDoorChoice!=Answer)>0 )[0]
OtherDoor[D] = Answer[D]
'''
IfUserStays = 0
IfUserChanges = 0
for n in range(0,N):
IfUserStays += 1 if Answer[n]==UserDoorChoice[n] else 0
IfUserChanges += 1 if Answer[n]==OtherDoor[n] else 0
'''
IfUserStays = float(len( np.where((Answer==UserDoorChoice)>0)[0] ))
IfUserChanges = float(len( np.where((Answer==OtherDoor)>0)[0] ))
if P:
print("Answer ="+str(Answer))
print("Other ="+str(OtherDoor))
print("UserDoorChoice="+str(UserDoorChoice))
print("OtherDoor ="+str(OtherDoor))
print("results")
print("UserDoorChoice="+str(UserDoorChoice==Answer)+" n="+str(IfUserStays)+" r="+str(IfUserStays/N))
print("OtherDoor ="+str(OtherDoor==Answer)+" n="+str(IfUserChanges)+" r="+str(IfUserChanges/N))
return IfUserStays/N, IfUserChanges/N
I just found that global ratio of winning is 50% and ratio of losing is 50%... It is how the proportion on winning or losing based on selected final option.
%Wins (staying): 16.692
%Wins (switching): 33.525
%Losses (staying) : 33.249
%Losses (switching) : 16.534
Here is my code, that differs from yours + with commented comments so you can run it with small iterations :
import random as r
#iterations = int(raw_input("How many iterations? >> "))
iterations = 100000
doors = ["goat", "goat", "car"]
wins_staying = 0
wins_switching = 0
losses_staying = 0
losses_switching = 0
for i in range(iterations):
# Shuffle the options
r.shuffle(doors)
# print("Doors configuration: ", doors)
# Host will always know where the car is
car_option = doors.index("car")
# print("car is in Option: ", car_option)
# We set the options for the user
available_options = [0, 1 , 2]
# The user selects an option
user_option = r.choice(available_options)
# print("User option is: ", user_option)
# We remove an option
if(user_option != car_option ) :
# In the case the door is a goat door on the user
# we just leave the car door and the user door
available_options = [user_option, car_option]
else:
# In the case the door is the car door
# we try to get one random door to keep
available_options.remove(available_options[car_option])
goat_option = r.choice(available_options)
available_options = [goat_option, car_option]
new_user_option = r.choice(available_options)
# print("User final decision is: ", new_user_option)
if new_user_option == car_option :
if(new_user_option == user_option) :
wins_staying += 1
else :
wins_switching += 1
else :
if(new_user_option == user_option) :
losses_staying += 1
else :
losses_switching += 1
print("%Wins (staying): " + str(wins_staying / iterations * 100))
print("%Wins (switching): " + str(wins_switching / iterations * 100))
print("%Losses (staying) : " + str(losses_staying / iterations * 100))
print("%Losses (switching) : " + str(losses_switching / iterations * 100))