This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 6 years ago.
Currently I'm working in Python to try and simulate a set in a match of tennis based on player probabilities. There's a while loop that's never ending in my "ftsix" (firsttosixpoints) function, but I can't figure out what the bug is because my logic isn't sound. I've been working on the problem for a few hours but I can't seem to find the solution.
P.S - please play nice
#One set in tennis = 1st to 6 games
#One game = 1st to four points
#Serve switches after each game.
def main():
printIntro()
probA, probB = getInputs()
gamesA, gamesB = ftsix(probA, probB)
if gamesA > gamesB:
print"Player A has won with", gamesA, "to player B's", gamesB, "."
else:
print "Player B has won with", gamesB,"to player A's", gamesA, "."
def printIntro():
print "This is a simulation of 1 tennis set based on player probabilities!"
def getInputs():
probA = input("What is the probability that player A will win?: ")
probB = input("What is the probability that player B will win?: ")
return probA, probB
def ftsix(probA, probB):
#First one to six games = one set
x = 0
gamesA = 0
gamesB = 0
while gamesA or gamesB != 6:
if x % 2 == 0 or x == 0:
serving = "A"
else:
serving = "B"
#This is one game, not in a seperate function because I couldn't figure out how to change serve inside the function!
pointsA = 0
pointsB = 0
while pointsA or pointsB != 4:
if serving == "A":
if probA >= random():
pointsA = pointsA + 1
else:
pointsB = pointsB + 1
if serving == "B":
if probB >= random():
pointsB = pointsB + 1
else:
pointsA = pointsA + 1
if pointsA > pointsB:
gamesA = gamesA + 1
else:
gamesB = gamesB + 1
x = x + 1
return gamesA, gamesB
I think your syntax in the while loops is incorrect. You need a full conditional on each side of the or, for example:
while gamesA != 6 and gamesB != 6:
You need to change your loop to terminate when either gamesA or gamesB reaches 6:
while gamesA != 6 and games != 6:
Related
I am making this kind of a game but it isn't really a game so basically I want this to run every time I hit space but it doesn't work no matter what I try so I would be really thankful if somebody could have helped me out on this.
import random
import keyboard
food = 5
x = 0
y = 0
if keyboard.is_pressed('space'):
bobsDecision = random.randint(0,1)
if bobsDecision == 1:
print ('bob ate')
food = 5
else:
xoy = random.randint(1,4)
if xoy == 1:
x = x + 1
elif xoy == 2:
x = x - 1
elif xoy == 3:
y = y + 1
elif xoy == 4:
y = y - 1
food = food - 1
print ('the cords are ', x, " ", y)
print ('The food supply is ', food)
Your code runs once and immediately skips over keyboard.is_pressed("space"), and then exits.
What you want to do instead is to loop forever, and use the keyboard module's read_key functionality to make it wait for a keypress.
An example of this is this - I also added support for exiting the loop/game with esc.
import random
import keyboard
food = 5
x = 0
y = 0
while True:
keyboard.read_key()
if keyboard.is_pressed("esc"):
print("Stopping play...")
break
elif keyboard.is_pressed("space"):
bobsDecision = random.randint(0,1)
if bobsDecision == 1:
print ('bob ate')
food = 5
else:
xoy = random.randint(1,4)
if xoy == 1:
x = x + 1
elif xoy == 2:
x = x - 1
elif xoy == 3:
y = y + 1
elif xoy == 4:
y = y - 1
food = food - 1
print ('the cords are ', x, " ", y)
print ('The food supply is ', food)
You need to put the if statement in a while loop. But ALSO be sure to have some kind of exit code. Below, I used the keypress esc to stop the while loop:
import random
import keyboard
food = 5
x = 0
y = 0
while True:
keyboard.read_key() # an important inclusion thanks to #wkl
if keyboard.is_pressed('esc'):
break
elif keyboard.is_pressed('space'):
bobsDecision = random.randint(0,1)
if bobsDecision == 1:
print ('bob ate')
food = 5
else:
xoy = random.randint(1,4)
if xoy == 1:
x = x + 1
elif xoy == 2:
x = x - 1
elif xoy == 3:
y = y + 1
elif xoy == 4:
y = y - 1
food = food - 1
print ('the cords are ', x, " ", y)
print ('The food supply is ', food)
I am a beginner in Python and I think I need some help with my program. Any kind of help or advice would be appreciated:)
You can see the program below, when I run it it gets stuck on the part of comparing the random ticket with the winning ticket(win_combination).
from random import choice
#Winning ticket
win_combination = input("Enter the winning combination of 4 numbers(1-digit-numbers): ")
while len(win_combination) != 4:
if len(win_combination) > 4:
win_combination = input("Reenter a shorter combination(4 one-digit-numbers): ")
elif len(win_combination) < 4:
win_combination = input("Reenter a longer combination(4 one-digit-numbers): ")
print(f"Winning combination is {win_combination}.")
#Specifying range of numbers to choose from
range = range(0, 10)
#Making a fake comparison-ticket to start of the loop
random_ticket = [0, 0]
random_ticket_string = f"{random_ticket[0]}{random_ticket[1]}{random_ticket[2]}{random_ticket[3]}"
#Params for the loop
n_tries = 0
n_guesses = 1
while random_ticket_string != win_combination:
while n_tries > 4:
random_ticket.clear()
number = choice(range)
random_ticket.append(number)
n_tries += 1
n_guesses += 1
random_ticket_string = f"{random_ticket[0]}{random_ticket[1]}"
if random_ticket_string == win_combination:
chance_to_win = f"{(1 / n_guesses) * 100}%"
print("Estimated percent to win is " + chance_to_win + ", it took " + f"{n_guesses} to match the winning combination.")
else:
n_tries = 0
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()
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
I edited my previous question because I came up with the code I think is correct.
The logic behind this should be:
while the set is not over and it's not a tie 10:10: player A starts serving and does it twice regardless he wins points or not, then player B takes serve and does it twice also. It continues until the set is over, except there is a tie 10:10 when servers change each point scored.
Can anyone check if the code is flawless? thank you.
def simOneSet(probA, probB):
serving = "A"
scoreA = scoreB = 0
while not setOver(scoreA, scoreB):
if scoreA != 10 and scoreB != 10:
if serving == "A":
for i in range(2):
if random() < probA:
scoreA += 1
else:
scoreB += 1
serving = "B"
else:
for i in range(2):
if random() < probB:
scoreB +=1
else:
scoreA += 1
serving = "A"
# when there is a tie 10:10
else:
if serving == "A":
if random() < probA:
scoreA += 1
serving = "B"
else:
scoreB += 1
serving = "B"
else:
if random() < probB:
scoreB += 1
serving = "B"
else:
scoreA += 1
serving = "A"
return scoreA, scoreB
I would use a dict to "switch" between players:
other = {'A':'B', 'B':'A'}
Then, if serving equals 'A', then other[serving] would equal 'B', and if serving equals 'B', then other[serving] would equal 'A'.
You could also use a collections.Counter to keep track of the score:
In [1]: import collections
In [2]: score = collections.Counter()
In [3]: score['A'] += 1
In [4]: score['A'] += 1
In [5]: score['B'] += 1
In [6]: score
Out[6]: Counter({'A': 2, 'B': 1})
Also notice how in this piece of code
if serving == "A":
for i in range(2):
if random() < probA:
scoreA += 1
else:
scoreB += 1
else:
for i in range(2):
if random() < probB:
scoreB +=1
else:
scoreA += 1
there are two blocks which are basically the same idea repeated twice. That's a sign that the code can be tightened-up by using a function. For example, we could define a function serve which when given a probability prob and a player (A or B) returns the player who wins:
def serve(prob, player):
if random.random() < prob:
return player
else:
return other[player]
then the above code would become
for i in range(2):
winner = serve(prob[serving], serving)
score[winner] += 1
Thus, you can compactify your code quite a bit this way:
import random
import collections
other = {'A':'B', 'B':'A'}
def serve(prob, player):
if random.random() < prob:
return player
else:
return other[player]
def simOneSet(probA, probB):
prob = {'A':probA, 'B':probB}
score = collections.Counter()
serving = "A"
while not setOver(score['A'], score['B']):
for i in range(2):
winner = serve(prob[serving], serving)
score[winner] += 1
if score['A'] == 10 and score['B'] == 10:
winner = serve(prob[serving], serving)
score[winner] += 1
serving = winner
return score['A'], score['B']
def setOver(scoreA, scoreB):
return max(scoreA, scoreB) >= 21
print(simOneSet(0.5,0.5))
Here is a hint:
If you have the roundnumber in the set and know which player started serving, you have everything you need to know who is serving.
Then a simple if statement at the start or end of your loop should be enough.
If this is too complicated, try starting by simulating a game where the server starts every round.
Something that might help is the syntax
var = 1 if var == 2 else 2
Which will make var be 1 if var is 2, and var be 2 if var is 1. I feel as though this is a school problem, so I don't want to totally give away the answer :)
Hint: You're on the right track with your thinking.
from random import *
P1=P2=0
while 1 :
p1=p2=0
while 2 :
if random() < 0.5 : p1 +=1
else : p2 +=1
if(p1 >=11 or p2 >=11) and abs(p1-p2) > 1: break
P1 += p1 > p2; P2 += p2 > p1
print "%2d : %2d (%d : %d)" % (p1, p2, P1, P2)
if P1 == 4 or P2 == 4 : break
i hope this helps, it worked for me