craps in python - python

I'm trying to simulate n games of craps. The code seems to make sense to me but I never get the right result. For example, if I put in n = 5 i.e. fives games the wins and losses sum to something greater than 5.
Here's how it's supposed to work: if initial roll is 2, 3, or 12, the player loses. If the roll is 7 or 11, the player wins. Any other initial roll causes the player to roll again. He keeps rolling until either he rolls a 7 or the value of the initial roll. If he re-rolls the initial value before rolling a 7, it's a win. Rolling a 7 first is a loss.
from random import randrange
def roll():
dice = randrange(1,7) + randrange (1,7)
return dice
def sim_games(n):
wins = losses = 0
for i in range(n):
if game():
wins = wins + 1
if not game():
losses = losses + 1
return wins, losses
#simulate one game
def game():
dice = roll()
if dice == 2 or dice == 3 or dice == 12:
return False
elif dice == 7 or dice == 11:
return True
else:
dice1 = roll()
while dice1 != 7 or dice1 != dice:
if dice1 == 7:
return False
elif dice1 == dice:
return True
else:
dice1 = roll()
def main():
n = eval(input("How many games of craps would you like to play? "))
w, l = sim_games(n)
print("wins:", w,"losses:", l)

The problem is with
if game():
wins = wins + 1
if not game():
losses = losses + 1
Instead, it should be
if game():
wins = wins + 1
else:
losses = losses + 1
In your code, you are simulating two games instead of one (by calling game() twice). This gives four possible outcomes instead of two (win/loss), giving inconsistent overall results.

In this code
for i in range(n):
if game():
wins = wins + 1
if not game():
losses = losses + 1
you call game() twice, so you play two games right there. What you want is a else block:
for i in range(n):
if game():
wins = wins + 1
else:
losses = losses + 1
Btw, you can simplify the logic with in:
def game():
dice = roll()
if dice in (2,3,12):
return False
if dice in (7,11):
return True
# keep rolling
while True:
new_roll = roll()
# re-rolled the initial value => win
if new_roll==dice:
return True
# rolled a 7 => loss
if new_roll == 7:
return False
# neither won or lost, the while loop continues ..
The code is quite literally the description you gave.

Don't do this
for i in range(n):
if game():
wins = wins + 1
if not game():
losses = losses + 1
It doesn't work out well at all.

There are numerous problems with this code. Most importantly, you're calling game() twice per loop. You need to call it once and store the result, and switch based on that.

An OO rewrite:
import random
try:
rng = xrange # Python 2.x
inp = raw_input
except NameError:
rng = range # Python 3.x
inp = input
def makeNSidedDie(n):
_ri = random.randint
return lambda: _ri(1,n)
class Craps(object):
def __init__(self):
super(Craps,self).__init__()
self.die = makeNSidedDie(6)
self.firstRes = (0, 0, self.lose, self.lose, 0, 0, 0, self.win, 0, 0, 0, self.win, self.lose)
self.reset()
def reset(self):
self.wins = 0
self.losses = 0
def win(self):
self.wins += 1
return True
def lose(self):
self.losses += 1
return False
def roll(self):
return self.die() + self.die()
def play(self):
first = self.roll()
res = self.firstRes[first]
if res:
return res()
else:
while True:
second = self.roll()
if second==7:
return self.lose()
elif second==first:
return self.win()
def times(self, n):
wins = sum(self.play() for i in rng(n))
return wins, n-wins
def main():
c = Craps()
while True:
n = int(inp("How many rounds of craps would you like to play? (0 to quit) "))
if n:
print("Won {0}, lost {1}".format(*(c.times(n))))
else:
break
print("Total: {0} wins, {1} losses".format(c.wins, c.losses))
if __name__=="__main__":
main()

Related

PIL, Pillow, Images Not Displaying In console, python

Program iterates through the first roll of Craps, which is supposed to output corresponding text and pictures based on each random roll.
from random import randint
from PIL import Image
"""
You are going to code the game of craps.
_____________________________________________________________________________
1. You will create 2 dice to roll. You will include a graphic of the dice for each roll.
2. On the first roll, if the dice total a 7 or 11 you win, print to the screen “You win",
3. If the dice total 2, 3, 12 you lose, print to the screen "You lose".
4. Any other number you keep rolling until you win or lose.
5. You can include a loop to prompt for ending or continuing the game so you do not have to rerun the program.
6. When you exit the game, print to the screen the number of wins and loses.
A return value of 1 means you win, a return value of 0 means you lost. You can use a different variable to keep track of your wins and loses.
"""
roll = []
wins = 0
losses = 0
d1 = 0
d2 = 0
rollResults = 0
dieOne = Image.open('dieOne.jpeg')
dieTwo = Image.open('dieTwo.jpeg')
dieThree = Image.open('dieThree.jpeg')
dieFour = Image.open('dieFour.jpeg')
dieFive = Image.open('dieFive.jpeg')
dieSix = Image.open('dieSix.jpeg')
def getRollFaces(d1,d2):
### RETURNS OUR DICE GRAPHIC FOR EACH ROLL ###
dieOne = Image.open('dieOne.jpeg')
dieTwo = Image.open('dieTwo.jpeg')
dieThree = Image.open('dieThree.jpeg')
dieFour = Image.open('dieFour.jpeg')
dieFive = Image.open('dieFive.jpeg')
dieSix = Image.open('dieSix.jpeg')
faceOne = None
faceTwo = None
if d1 == 1:
faceOne = dieOne.show()
if d1 == 2:
faceOne = dieTwo.show()
if d1 == 3:
faceOne = dieThree.show()
if d1 == 4:
faceOne = dieFour.show()
if d1 == 5:
faceOne = dieFive.show()
if d1 == 6:
faceOne = dieSix.show()
if d2 == 1:
faceTwo = dieOne.show()
if d2 == 2:
faceTwo = dieTwo.show()
if d2 == 3:
faceTwo = dieThree.show()
if d2 == 4:
faceTwo = dieFour.show()
if d2 == 5:
faceTwo = dieFive.show()
if d2 == 6:
faceTwo = dieSix.show()
return faceOne,faceTwo
def roll_dice():
wins = 0
losses = 0
roll = []
d1 = randint(1, 6)
roll.append(d1)
d2 = randint(1, 6)
roll.append(d2)
rollResults = d1 + d2
getRollFaces(d1,d2)
print("Your roll is: {}".format(rollResults))
if rollResults == 2 or rollResults == 3 or rollResults == 12:
losses = losses + 1
loss = input("We are sorry for your loss. :( Play again? Y or N ")
if loss == "Y" or loss == "y":
roll_dice()
elif loss == "N" or loss == "n":
print("Total wins: {}. Total losses: {}. Thanks for playing!".format(wins,losses))
return 0
elif rollResults == 7 or rollResults == 11:
wins += 1
win = input("Congrats on your win! :) Play again? Y or N ")
if win == "Y" or win == "y":
roll_dice()
elif win == "N" or win == "n":
print("Total wins: {}. Total losses: {}. Thanks for playing!".format(wins,losses))
return 1
else:
roll_dice()
roll_dice()
As mentioned in the title, my images are not displaying on my console as part of my output. My wins/losses accumulator is also not working properly.
PIL documentation was consulted prior to posting.
Please advise!

Creating the war(card) game using OOP in Python

I am trying to create the war card game where 2 players draw a card each on the table, and the player whose card has max value gets both the cards, if the card values are equal(called war condition) each player draws 5 cards, and the value of the last card among these 5 cards are compared and works similarly as above. A player wins when either the other player runs out of cards or if in war condition the other player has less than 5 cards.
My questions:
When I am running the game logic sometimes it runs but sometimes it gets stuck in an infinite loop. Why?
I can notice that when the total number of cards for both players at all times should be 52, but here it is decreasing. Why? (I can see that the cards are getting lost every time the game goes into war condition, but I am not able to understand why that is happening, since I am adding all the 10 cards to the player whose card has a greater value.)
I have tried another method where I assume that players are always at war and then approach it, which works. But I want to understand why, if I break it into steps which I am trying to do here, is it not working?
Code:
import random
suits = ['Hearts','Clubs','Spades','Diamonds']
ranks = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
values = {'Two': 2, 'Three': 3, 'Four': 4, 'Five': 5, 'Six' : 6 , 'Seven' :7, 'Eight': 8,'Nine':9,
'Ten':10,'Jack':11, 'Queen': 12,'King': 13,'Ace':14 }
classes:
class Card():
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
self.value = values[rank]
#string method
def __str__(self):
return self.rank + ' of ' + self.suit
class Deck():
def __init__(self):
self.all_cards = [] #list of objects
for suit in suits:
for rank in ranks:
#create card object
created_card = Card(suit,rank)
self.all_cards.append(created_card)
def shuffle(self): #method to shuffle the card
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop() #we want the last card from deck
class Player():
def __init__(self,name):
self.name = name
self.all_cards = []
def remove_one(self):
return self.all_cards.pop(0) #to remove card from beginning of the list
def add_cards(self,new_cards):
if type(new_cards) == type([]):
self.all_cards.extend(new_cards)
else:
self.all_cards.append(new_cards)
def __str__(self):
return f'Player {self.name} has {len(self.all_cards)} cards.'
And below is the final game logic:
#create 2 new instances of the player class
player1_name = input('Enter the name of Player1: ')
player2_name = input('Enter the name of Player2: ')
player1 = Player(player1_name)
player2 = Player(player2_name)
newdeck = Deck()
newdeck.shuffle()
#splitting the deck among the two players - alternate card from deck goes to each player respectively
for i in range(0,len(newdeck.all_cards)-1,2):
player1.add_cards(newdeck.all_cards[i])
player2.add_cards(newdeck.all_cards[i+1])
#for x in range(26):
# player1.add_cards(newdeck.deal_one())
#player2.add_cards(newdeck.deal_one())
print(player1)
print(player2)
game_status = True
round_num = 0
while game_status == True:
round_num +=1
print(f"Round {round_num}")
if len(player1.all_cards) == 0:
print('Player 1 out of cards'+ player2.name + 'Wins!')
game_status = False
break
if len(player2.all_cards) == 0:
print('Player 2 out of cards' + player1.name + 'Wins!')
game_status = False
break
else:
player_cards = []
player1_card = player1.remove_one()
player2_card = player2.remove_one()
player_cards.append(player1_card)
player_cards.append(player2_card)
print('player1_card_value: ',player1_card.value)
print('')
print('player2_card_value: ',player2_card.value)
print('')
print(player1)
print('')
print(player2)
at_war = True
if player1_card.value == player2_card.value:
while at_war == True:
player1_list = []
player2_list = []
card_list = []
if len(player1.all_cards) < 5:
print('Player 2 won')
game_status = False
at_war = False
break
elif len(player2.all_cards) <5:
print('Player 1 won')
game_status = False
at_war = False
break
if len(player1.all_cards) >= 5 and len(player2.all_cards) >= 5:
for i in range(5):
player1_list.append(player1.remove_one())
player2_list.append(player2.remove_one())
card_list.extend(player1_list)
card_list.extend(player2_list)
print("CARD LIST LEN", len(card_list))
if player1_list[0].value > player2_list[0].value:
player1.add_cards(card_list)
at_war = False
break
elif player1_list[0].value < player2_list[0].value:
player2.add_cards(card_list)
#player2.add_cards(player1_list)
at_war = False
break
else:
at_war = True
elif player1_card.value > player2_card.value:
player1.add_cards(player_cards)
#player1.add_cards(player2_cards)
#print('p1>p2', player1)
elif player2_card.value > player1_card.value:
player2.add_cards(player_cards)
print(player1)
print(player2)
if len(player1.all_cards) == 0:
print('Player 2 won')
elif len(player2.all_cards) == 0:
print('Player 1 won')
Output: When it was stuck in an infinite loop:(You can see the total number of cards is now 34 instead of 52.)

Python - LOGIC ERROR - on racquetball simulation

I just started to learn python(self-taught) and I'm trying to do a simulation of racquetball game.
I can run the simulation with: a==15 or b==15, but when I add the extra condition: abs(a-b)>=2 IT GOES CRAZY(the simOneGame turns to an infinite loop). Here is what I tried so far:
return a == 15 or b == 15 ------> this one works perfectly
return a == 15 or b == 15 and abs(a-b) >= 2 --> this doesn't freeze but the logic is wrong(I think)
return (a == 15 or b == 15) and abs(a-b) >= 2 --> freezing
return (a == 15 or b == 15) and (abs(a-b) >= 2) --> freezing
return ((a == 15 or b == 15) and (abs(a-b) >= 2)) --> freezing
Thanks a lot and sorry if this seems too long(maybe I should've typed just the function gameOver()?...)
Here is my code so far:
from random import random
def main():
printIntro()
n, probA, probB = getInputs()
winsA, winsB = simNGames(n, probA, probB)
displayResults(winsA, winsB)
def printIntro():
print("\nVOLLEYBALL SIMULATION\n")
print("The inputs will be the number of simulations(n),")
print(" the probability player A wins his serve(probA)")
print(" and the probability player B wins his serve(probB).")
print("The program will display how many games won player A(winsA),")
print(" how many games won player B(winsB),")
print(" and the percentages of winnings for both players.\n")
def getInputs():
n = int(input("Enter the number of simulations: "))
probA = float(input("Enter the probability player A wins his serve: "))
probB = float(input("Enter the probability player B wins his serve: "))
return n, probA, probB
def simNGames(n, probA, probB):
winsA, winsB = 0, 0
for i in range(n):
# player A serves on odd games
if i % 2 == 0:
serving = "A"
# player B serves on even games
else:
serving = "B"
scoreA, scoreB = simOneGame(probA, probB, serving)
if scoreA > scoreB:
winsA = winsA + 1
else:
winsB = winsB + 1
return winsA, winsB
def simOneGame(probA, probB, serving):
scoreA, scoreB = 0, 0
while not gameOver(scoreA, scoreB):
if serving == "A":
if random() < probA:
scoreA = scoreA + 1
else:
serving = "B"
else:
if random() < probB:
scoreB = scoreB + 1
else:
serving = "A"
return scoreA, scoreB
def gameOver(a, b):
# the game is over if a player gets to 15 AND the difference is at least 2.
# this shoud work... BUT IT DOESN'T... simOneGame turns to an infinete loop with a large number of simulations...
return (a == 15 or b == 15) and abs(a-b) >= 2
def displayResults(winsA, winsB):
print("Player A won {0} games({1:1.0%})".format(winsA, winsA/(winsA+winsB)))
print("Player B won {0} games({1:0.0%})".format(winsB, winsB/(winsA+winsB)))
if __name__ == "__main__":
main()

How do I carry over the final player score to be used as the starting score for the next round?

In my programming class we are creating a dice poker game. Once a round is complete and the player receives their score, that score is supposed to be used as the new starting point for the next round. In the code you can see me trying to make "newPlayPoints" become "playingPoint", however I am unsure if that is the correct way to go about this. I'm sure the coding is a little messy due to my beginner status, but the main sections to look at would be under the function "updatePlayPoints" and the comment that reads "#Attempting to get playingPoint to become new "newPlayPoints". Thank you for the help!
from random import randint
def rollFiveDie():
allDie = []
for x in range(5):
allDie.append(randint(1,6))
return allDie
def outputUpdate(P, F):
print(P)
print(F)
def rollSelect():
rollSelected = input("Which die would you like to re-roll? (Choose 1, 2, 3, 4 and/or 5 from the list) ")
print(" ")
selectList = rollSelected.split()
return selectList
def rollPicked(toRollList, diceList):
for i in toRollList:
diceList[int(i) - 1] = randint(1,6)
def scoring(dList):
counts = [0] * 7
for value in dList:
counts[value] = counts[value] + 1
if 5 in counts:
score = "Five of a Kind", 30
elif 4 in counts:
score = "Four of a Kind", 25
elif (3 in counts) and (2 in counts):
score = "Full House", 15
elif 3 in counts:
score = "Three of a Kind", 10
elif not (2 in counts) and (counts[1] == 0 or counts[6] == 0):
score = "Straight", 20
elif counts.count(2) == 2:
score = "Two Pair", 5
else:
score = "Lose", 0
return score
def numScore(diList):
counts = [0] * 7
for v in diList:
counts[v] = counts[v] + 1
if 5 in counts:
finScore = 30
elif 4 in counts:
finScore = 25
elif (3 in counts) and (2 in counts):
finScore = 15
elif 3 in counts:
finScore = 10
elif not (2 in counts) and (counts[1] == 0 or counts[6] == 0):
finScore = 20
elif counts.count(2) == 2:
finScore = 5
else:
finScore = 0
return finScore
def printScore(fscore):
print(fscore)
print(" ")
def trackScore(score1, score2):
comScore = (score1) + (score2)
return comScore
#Starting Points
playPoints = 100
print("New round! Your points are: ", playPoints)
newPlayPoints = 100 - 10
def updatePlayPoints(nPP, PP):
nPP = PP
return nPP
def diceGame():
contPlaying = True
while contPlaying:
playing = input("It takes 10 points to play. Would you like to play the Dice Game? (Answer 'y' or 'n'): ")
print(' ')
if playing == 'y':
#First Roll
fiveDie = rollFiveDie()
outputUpdate("Your roll is...", fiveDie)
#Choosing Second Roll/Second Roll execution
pickDie = input("Which die would you like to re-roll? (Choose 1, 2, 3, 4 and/or 5 from the list) ")
print(" ")
pickDie = pickDie.split()
rollPicked(pickDie, fiveDie)
outputUpdate("Your next roll is...", fiveDie)
#Choosing Last Roll
pickDie = rollSelect()
rollPicked(pickDie, fiveDie)
outputUpdate("Your final roll is...", fiveDie)
#Scoring output
finalScore = numScore(fiveDie)
print(scoring(fiveDie))
fiveDieScore = numScore(fiveDie)
finalPoints = newPlayPoints + finalScore
print(finalPoints)
#Attempting to get playingPoint to become new "newPlayPoints"
playingPoint = trackScore(fiveDieScore, newPlayPoints)
if playingPoint > 10:
playingPoint - 10
else:
print("No more points to spend. Game Over.")
contPlaying = False
updatePlayPoints(newPlayPoints, playingPoint)
else:
contPlaying = False
def main():
diceGame()
main()
You are returning the newPlayPoints but you aren't setting them to anything. You are just calling updatePlayPoints and doing nothing with the return value. You don't need trackscore, updatePlayPoints or newPlayPoints. Instead add fiveDieScore to PlayingPoint. Also, the way it is set up now the player can start the game with no points. I am assuming that there should be an initial number of points the person starts with, I set it to 10. So now every turn you check if the player has enough points to even play and if they do immediately subtract out those points. Think about it as if it were an arcade game. You have to have a quarter to play and the first thing you do is pay to play. The way you subtract out the points does nothing. PlayingPoint - 10 is a valid line but you set it to nothing so it does nothing.
def diceGame():
contPlaying = True
PlayingPoints = 10 #Initial points
while contPlaying:
playing = input("It takes 10 points to play. Would you like to play the Dice Game? (Answer 'y' or 'n'): ")
print(' ')
if playing == 'y' and PlayingPoint >= 10:
#Subtract the points used for the turn
PlayingPoint -= 10
#First Roll
fiveDie = rollFiveDie()
outputUpdate("Your roll is...", fiveDie)
#Choosing Second Roll/Second Roll execution
pickDie = input("Which die would you like to re-roll? (Choose 1, 2, 3, 4 and/or 5 from the list) ")
print(" ")
pickDie = pickDie.split()
rollPicked(pickDie, fiveDie)
outputUpdate("Your next roll is...", fiveDie)
#Choosing Last Roll
pickDie = rollSelect()
rollPicked(pickDie, fiveDie)
outputUpdate("Your final roll is...", fiveDie)
#Scoring output
finalScore = numScore(fiveDie)
print(scoring(fiveDie))
fiveDieScore = numScore(fiveDie)
finalPoints = PlayingPoint + finalScore
print(finalPoints)
playingPoint += fiveDieScore
else:
contPlaying = False
To sum up the changes I removed TrackScore, UpdatePlayPoints, and newPlayPoints. Added the point check to the beginning rather than the end

Simulate several rounds of rock, paper and scissors

I am trying to implement a function that takes an integer n and simulates n rounds of Rock, Paper, Scissors between players Player 1 and Player 2. The player who wins the most rounds wins the n-round game, with ties possible. The function should print the result of the game as shown.
>>> simul(1)
Player 1
>>> simul(1)
Tie
>>>simul(100)
Player 2
I think I need to approach this in a modular fashion. In other words, I need to combine at least 2 functions, my problem is that I can't seem to figure out how to do that. How can I activate the result from an embedded function when calling the simul() function?
So I have created a function that simulates the game Rock, Paper, Scissors by execution the function rps(p1, p2). The code is the following:
def rps(p1,p2):
#tie
if (p1==p2):
return 0
# player 1 wins
elif p1+p2 in ['PR','RS','SP']:
return -1
else:
return 1
# player 2 wins
This is where I'm a bit stuck. I need to activate this function when executing the simul() function—how can I do that? What I have so far is the following:
def rps(p1,p2):
#tie
if (p1==p2):
return 0
# player 1 wins
elif p1+p2 in ['PR','RS','SP']:
return -1
else:
return 1
# player 2 wins
def choose_rps():
import random
random.choice('RPS')
def simul(n):
p1_wins, p2_wins = 0, 0
for i in range(n):
p1 = choose_rps()
p2 = choose_rps()
result = rps(p1, p2)
if result == -1:
p1_wins += 1
elif result == 1:
p2_wins += 1
if p1_wins > p2_wins:
return 'Player 1'
elif p1_wins == p2_wins:
return 'Tie'
else:
return 'Player 2'
To "activate" a function, you just call it. For example:
def simul(n):
score = 0
for i in range(n):
p1 = choose_rps()
p2 = choose_rps()
result = rps(p1, p2)
score += result
if score < 0:
print('Player 1')
elif score == 0:
print('Tie')
else:
print('Player 2')
Of course you need to write the choose_rps function (which randomly chooses and returns one of R, P, or S)—but, as you can see, you just call it the same way as the rps function.
To put it all together into a script:
def rps(p1, p2):
# ... your code here
def choose_rps():
# implement this here
def simul(n):
# code from above
And then you'll probably want something to drive it, such as this:
if __name__ == '__main__':
import sys
n = int(sys.argv[1]) if len(sys.argv) > 1 else 5
simul(n)
… or…
while True:
n = int(input('How many trials?')) # raw_input for Python 2.x
simul(n)
If you want, you can simplify this further. For example, you can turn the whole loop into a sum call with a generator expression:
def simul(n):
score = sum(rps(choose_rps(), choose_rps()) for _ in range(n))
Here is an equivalent function without the RPS narrative:
import random
def simul(n):
score = sum([random.choice([-1, 0, 1]) for i in xrange(n)])
winner_idx = 0 if score > 0 \
else 1 if score < 0 \
else 2
print ['Player 1', 'Player 2', 'Tie'][winner_idx]
Here is one that follows the story and is expanded to Rock, Paper, Scissors, Lizard, Spock:
import random
def rand_RPSLK():
while True:
yield random.choice('PSKLR')
def simul(n):
p1 = rand_RPSLK()
p2 = rand_RPSLK()
choice = lambda px: 'PSKLR'.index(next(px))
score = sum([[0,1,-1,1,-1][choice(p1)-choice(p2)] for i in xrange(n)])
winner_idx = 0 if score > 0 \
else 1 if score < 0 \
else 2
print ['Player 1', 'Player 2', 'Tie'][winner_idx]

Categories