Reputation: 185
I have this code that is made for a game similar like (Rock, Paper, Scissors). When the code starts running, sometimes it gives error in not running the actual loop and conditions correctly. For example when the code starts running, at the first time the loop runs normally:
Foot, Nuke or Cockroach? (Quit ends): Foot
You chose: Foot
Computer chose: Foot
It is a tie!
Foot, Nuke or Cockroach? (Quit ends):
But if I re-run the code again, the while-loop
does not get executed as in the following example:
Foot, Nuke or Cockroach? (Quit ends): Cockroach
Foot, Nuke or Cockroach? (Quit ends):
Or it gives me elif
condition that the input is incorrect even though the input is from the correct selection.
Here is the full code:
import random
def main():
rounds = 0
win = 0
tie = 0
choices = ["Foot", "Nuke", "Cockroach"]
cpu = random.choice(choices)
while True:
inpt = input("Foot, Nuke or Cockroach? (Quit ends): ")
if inpt == "Foot" and cpu == "Nuke" or inpt == "Cockroach" and \
cpu == "Foot":
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("You LOSE!")
rounds += 1
elif inpt == "Nuke" and cpu == "Foot" or inpt == "Foot" and \
cpu == "Cockroach":
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("You WIN!")
rounds += 1
win += 1
elif inpt == "Foot" and cpu == "Foot" or inpt == "Cockroach" and \
cpu == "Cockroach" or inpt == "Nuke" and cpu == "Nuke":
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("It is a tie!")
rounds += 1
tie += 1
elif inpt == "Quit":
print(f"You played {rounds} rounds, and won {win} rounds, "
f"playing tie in {tie} rounds.")
break
elif inpt != "Foot" and inpt != "Cockroach" and inpt != "Nuke":
print("Incorrect selection.")
if __name__ == "__main__":
main()
Upvotes: 1
Views: 296
Reputation: 8270
To avoid multiple if-else
statements you can use list
to store all possible combinations:
import random
ACTIONS = ['foot', 'nuke', 'cockroach']
MAP = [['=', '<', '>'],
['>', '=', '<'],
['<', '>', '=']]
SCORE = {'=': ['Tied Game!', 0, 0],
'>': ['You WIN!', 1, 0],
'<': ['You LOOSE!', 0, 1]}
rounds = 0
score_user = 0
score_comp = 0
while True:
action = input(f'Foot, Nuke or Cockroach? (Quit ends): ').lower()
if action == 'quit':
break
user = ACTIONS.index(action)
comp = random.randint(0, 2)
print(f'You chose {ACTIONS[user]}, computer chose {ACTIONS[comp]}.')
res = MAP[user][comp]
score_user += SCORE[res][1]
score_comp += SCORE[res][2]
print(f'{ACTIONS[user].title()} {res} {ACTIONS[comp].title()}. {SCORE[res][0]} Your score: {score_user}. Comp score: {score_comp}')
rounds += 1
print(f'You played {rounds} rounds, and won {score_user} rounds, playing tie in {rounds-score_user-score_comp} rounds.')
Output:
Foot, Nuke or Cockroach? (Quit ends): foot
You chose foot, computer chose nuke.
Foot < Nuke. You LOOSE! Your score: 0. Comp score: 1
Foot, Nuke or Cockroach? (Quit ends): nuke
You chose nuke, computer chose foot.
Nuke > Foot. You WIN! Your score: 1. Comp score: 1
Foot, Nuke or Cockroach? (Quit ends): quit
You played 2 rounds, and won 1 rounds, playing tie in 0 rounds.
Upvotes: 0
Reputation: 345
Two things make this break, and there's a few thing to improve.
The reason for breaks is that you've done the tie condition wrong. When running multiple conditions like that in a row you need parentheses. Otherwise it reads it "incorrect". So the if condition should be:
elif (inpt == "Foot" and cpu == "Foot") or (inpt == "Cockroach" and cpu == "Cockroach") or (inpt == "Nuke" and cpu == "Nuke"):
The same thing might be happening for the other conditions too, I didn't run the loop that many times.
Secondary thing that doesn't break the loop itself but renders the game useless is that you have the cpu pick their value outside of the loop. That means that the CPU's pick stays the same during all loops. It's an easy fix to move this inside the while loop (ofc before the if statements)
In addition you should probably make a stop condition flag instead of using break. So set the while loop to run when flag
(or whatever name you want) is True
.
Then if you need the game to end set the variable to False.
Also doing all the checks for win state in the if statements make mistake easy and reduce readability. You should instead check for each state (win, loss, tie) first, and set a variable to match that, and then run the point adding if statements against that variable.
Also making the game a class, and adding functions inside help it run smoother and increase readability. So you can run i.e the game state checker in it's own function.
EDIT:
Also any time you take input you should sanitize it. Here the input is simple so casting input.lower()
is all you need. That way no matter what the user capitalizes the input will always be all lowercase. So an input of nUkE
becomes just nuke
Upvotes: 4
Reputation: 1645
Not sure, but you have not treated the case that you input "Nuke" and cpu is "Cockroach" if i am not mistaken. You will have to implement that. However, a few suggestions:
The following code works for me except when i enter Nuke and cpu is on Cockroach, because there is no condition for that:
import random
def main():
rounds = 0
win = 0
tie = 0
choices = ["Foot", "Nuke", "Cockroach"]
cpu = random.choice(choices)
while True:
inpt = input("Foot, Nuke or Cockroach? (Quit ends): ")
if inpt == "Quit":
print(f"You played {rounds} rounds, and won {win} rounds, "
f"playing tie in {tie} rounds.")
break
if inpt not in choices:
print("Incorrect selection.")
continue
if inpt == "Foot" and cpu == "Nuke" or inpt == "Cockroach" and cpu == "Foot":
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("You LOSE!")
rounds += 1
if inpt == "Nuke" and cpu == "Foot" or inpt == "Foot" and cpu == "Cockroach":
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("You WIN!")
rounds += 1
win += 1
if inpt == cpu:
print(f"You chose: {inpt}")
print(f"Computer chose: {cpu}")
print("It is a tie!")
rounds += 1
tie += 1
if __name__ == "__main__":
main()
Upvotes: 2
Reputation: 186
I don't about your game but if it's like rock paper scissors, shouldn't you have more conditions? You never test cockroach vs nuke.
Also, it may be best to change cpu
within the while
loop (otherwise in at most 3 tries the player can guess its value and always win).
I don't see any obvious error that would prevent your input to be valid, so make sure you have entered the capitalized letters as in your program (or maybe better, use inpt.lower() to always consider lower case strings)
Upvotes: 0
Reputation: 577
If I input Nuke
and the cpu picks Foot
, nothing happens. This is because you have not programmed that specific condition.
I also recommend moving cpu = random.choice(choices)
inside the while loop, so the cpu can change its choice during the game.
Upvotes: 0