Reputation: 21
I'm currently coding a little rock, paper, scissors game in Python, however I appear to have stumbled upon a problem. The game works, even though the code is a little rough, but I've tried to make the program inform the player they have made an error, and when I test this out, it randomly informs the player they have made an error, when they have not. Here is the block of code that is my problem, it is not the whole game.
def game(self):
print "This is rock, paper, scissors!"
rps = ('rock', 'paper', 'scissors')
comp1 = raw_input("Rock, paper or scissors?\n> ")
comp2 = random.choice(rps)
if comp1 == 'rock' and comp2 == 'scissors' or comp1 == 'scissors' and comp2 == 'paper' or comp1 == 'paper' and comp2 == 'rock':
print "You won! The computer chose %s" % comp2
return "game"
elif comp1 == 'rock' and comp2 == 'rock':
print "In a stalemate, there are no winners, only losers :)\nThe computer also chose %s" % comp2
return "game"
elif comp1 == 'scissors' and comp2 == 'scissors':
print "In a stalemate, there are no winners, only losers :)\nThe computer also chose %s" % comp2
return "game"
elif comp1 == 'paper' and comp2 == 'paper':
print "In a stalemate, there are no winners, only losers :)\nThe computer also chose %s" % comp2
return "game"
elif comp1 != 'rock' or 'scissors' or 'paper':
print "Try choosing between rock, paper and scissors next time. It might help.
return "game"
else:
print "The computer %s. You have failed. Problem?" % comp2
return "game"
Upvotes: 0
Views: 1330
Reputation: 295
I think that this is a little more cleaned up version, although not the best implementation. I also added an option to keep playing, and changed it so the user input was case insensitive.
def game():
import random
import string
print "This is rock, paper, scissors!"
rps = ('rock', 'paper', 'scissors')
comp1 = raw_input("Rock, paper or scissors? ")
comp1 = comp1.lower()
comp2 = random.choice(rps)
if comp1 == 'rock' and comp2 == 'scissors' or comp1 == 'scissors' and comp2 == 'paper' or comp1 == 'paper' and comp2 == 'rock':
print "You won! The computer chose %s" % comp2
elif comp1 == comp2:
print "In a stalemate, there are no winners, only losers :)\nThe computer also chose %s" % comp2
elif comp1 not in rps:
print "Try choosing between rock, paper and scissors next time. It might help."
else:
print "The computer chose %s. You have failed. Problem?" % comp2
new_game = raw_input('Would you like to play again? ')
new_game = new_game.lower()
if new_game == 'yes':
game()
Upvotes: 0
Reputation: 34153
The problem is with your logic here elif comp1 != 'rock' or 'scissors' or 'paper':
. The strings 'scissors' and 'paper' are being evaluated to a boolean value, which is true because they are not null.
What you want is elif comp1 != 'rock' and comp1 != 'scissors' and comp1 != 'paper':
or since you already have it in the rps
tuple, you can do elif comp1 not in rps:
Upvotes: 1
Reputation: 5760
Change
elif comp1 != 'rock' or 'scissors' or 'paper':
to
elif comp1 not in rps:
What you were doing before was equivalent to:
elif (comp1 != 'rock') or 'scissors' or 'paper':
So why was the condition always met?
Have a close look at the or 'scissors' or 'paper'
part.
1) In Python, non-empty strings are treated as True, and empty strings are treated as False. Have a look at this interactive session:
>>> bool('')
False
>>> bool('a')
True
2) Also in Python, if
statements without a comparison (e.g. if var1:
) are inexplicity checking if the expression is True. So,
if var1:
is the same as
if var1 == True:
If you combine these two ideas together:
if 'rock':
# Always executed
if '':
# Never executed
Back to your original if statement:
elif comp1 != 'rock' or 'scissors' or 'paper':
Both 'scissors' and 'paper' will always return True, so the contained statements will always be evaluated.
So what is the "in" operator?
The in
operator in elif comp1 not in rps:
will see if the contents of comp1
is an item in the tuple rps
(which is equal to ('rock', 'paper', 'scissors')
). The not
in front of it will negate it, checking if the contents of comp1
is an item in the tuple rps
. Therefore, the contained statements will only be executed if the user input stored in comp1
is invalid.
Upvotes: 9
Reputation: 96366
It should be
comp1 not in ['rock', 'scissors', 'paper']
'scissors' and 'paper' always evaluate to true (or in case of or
to themselves)
comp1 != 'rock' or 'scissors' or 'paper'
Also, use comp1 == comp2
, it's much more simple.
Upvotes: 2