Reputation: 21
Using VS2015
Python 3.4
Having some issues with this while
counter. It is slowly driving me insane as I'm sure it 'should' work but isn't updating the counter. I've ran stepping debug and can see the counter resetting to 3 before the while condition line. It is annoying me to say the least.
import random
import getpass
print ('Welcome to Rock, Paper or Sissors\nEnter an option.')
user_obj = getpass.getpass('Rock, Paper or Sissors: ').lower()
ai_obj = input('Rock, Paper or Sissors: ').lower()
rps = ('rock', 'paper', 'sissors')
#ai_rps = ['rock', 'paper', 'sissors']
#ai_obj = random.choice(ai_rps)
counter = 3
def rps_game(user_obj, ai_obj):
print('Player selected %s ' % user_obj)
print('Computer selected %s ' % ai_obj)
condition = user_obj in rps and ai_obj in rps
while condition == True and counter >= 0:
if user_obj == ai_obj:
print('Its a draw!')
elif user_obj == 'rock':
if ai_obj == 'paper':
print('You lose!')
break
else:
print('You win!')
elif user_obj == 'paper':
if ai_obj == 'sissors':
print('You lose!')
break
else:
print('You win!')
elif user_obj == 'sissors':
if ai_obj == 'rock':
print('You lose!')
else:
print('You win!')
break
else:
counter += 1
print('Invalid input, please select Rock, Paper or Sissors')
rps_game(user_obj, ai_obj)
rps_game(user_obj, ai_obj)
Upvotes: 2
Views: 4495
Reputation: 12749
The else
containing the counter update is indented so that it hangs off of the while. That means that it executes only when the while loop terminates because the condition is false (not when you break out). In this case, the condition is false when either the user or ai input is not in the list of valid inputs or the counter is negative. The counter can never be negative because it starts at 3 and is only ever incremented. If the user input is invalid, the error message is printed, the counter is incremented, and then you use recursion to call the function with the same arguments. Since the arguments haven't changed, the function should do the same thing it just did, unless it depends on global data (counter). However, if counter is local (initialized inside the function), each invocation of the function gets a fresh copy. If counter is global (initialized outside the function, but declared global inside the function), it still won't work because you need to decrement it. And even then, because none of the other inputs have changed, it will just print the error message over and over.
Your loop bound appears to expect counter to count down from 3 since it keeps going as long as counter
is positive. Incidentally, using >=
as the conditional will make the loop execute 4 times (3, 2, 1, and 0). You might want to change the conditional to strictly greater than, and change the counter increment to a counter decrement.
Next, you are using recursion (the function calls itself), but this should be unnecessary since the loop gets you back to where you need to be.
Next, the lose cases break out of the loop, but the win cases do not. If you win, the code will loop, not modifying the counter or any of the other inputs, so it will not terminate.
Finally, the user input is read from outside the function, so it never changes inside the loop. If the user enters an illegal value, the loop will just keep testing the same value. You probably want to read the user input inside the loop.
Upvotes: 0
Reputation: 1512
counter
resets to its original value because it is a global variable. Global variables in Python behave differently than in other languages. Try this snippet :
counter = 3
def f():
counter = 2 # Shadows global 'counter' by a newly defined one
f()
print (counter) # Prints 3 !
You could expect the printed value to be 2, but is 3 instead. Global variables are immutable by default, and attempt to modify it in a local scope without global
keyword will shadow by local definition instead. See this discussion to use global variable although it would be preferable to rework your program to use local variables.
EDIT: There is also a mistake, counter is initialized to 3 and only incremented, so the condition >= 0 will always be satisfied (thus creating an infinite loop). You can try:
[...]
def rps_game(user_obj, ai_obj, counter):
if counter <= 0:
return
print('Player selected %s ' % user_obj)
print('Computer selected %s ' % ai_obj)
while user_obj in rps and ai_obj in rps :
[...]
else:
print('Invalid input, please select Rock, Paper or Sissors')
rps_game(user_obj, ai_obj, counter-1)
rps_game(user_obj, ai_obj, 3)
Upvotes: 1