I'm asking the user if they want to go first or not and use input validation so that only "y" "Y" "n" or "N" are accepted as a valid response. my code seems to crash when i run it.
choice = raw_input("Would you like to go first or not? (y/Y or n/N): ")
print ""
try:
valid_choice = False
while not valid_choice:
if choice == "y" or choice == "Y":
users_turn = True
valid_choice = True
elif choice == "n" or choice == "N":
users_turn = False
valid_choice = True
break
else:
print "Invalid Choice."
except NameError:
print "You can only enter y/Y or n/N"
3 Answers 3
Ahm, the flow in your code has a bit too many possible paths. You could simplify it with something like:
question = "Would you like to go first or not? (y/Y or n/N): "
choice = raw_input(question)
while choice not in ['y', 'Y', 'n', 'N']:
print 'Invalid choice'
choice = raw_input(question)
users_turn = choice in ['y', 'Y']
Having said that, I should say that it is a common pattern for a console application to use (Y/n) to indicate that it accepts the letters y or n as responses (in both lower and upper cases), but the upper case indicates the default option.
So, if you can trust the user to make a decision the first time you ask for an input to the question, you can set a default response and code it like this:
choice = raw_input('Would you like to go first? (Y/n)')
users_turn = choice.lower() not in ['n', 'no']
3 Comments
'yes', 'no' and initials to support other languages.'Yn' in 'yYnN' gives True. sorry ;PJust as an alternative to elias' answer, I'd like to present the following:
while True:
choice = raw_input("Would you like to go first or not? (y/Y or n/N): ")
if choice in ["y", "Y", "n", "N"]:
break
print "Invalid choice"
users_turn = choice in ["y", "Y"]
It's better in that it doesn't duplicate the ask line, but worse in that the while True/break syntax is a bit ugly (it would be nice if Python had do...while like C, but alas). Choose for yourself which you like the most. :)
Also, just to point out some of the several errors you have in your own code:
- The
try...except NameErrorblock is completely redundant, since nothing in your code will throwNameError, and especially not to signal an actual user error. - You have your
elseline at the wrong indentation. As it stands, it matches thewhileblock rather thanif/elifblock, causing behavior you most likely do not intend. - The
breakin theelifblock is redundant, since thewhileloop will exit anyway when you've setvalid_choicetoTrue. - Most important of all, you don't reask the user when he types an invalid answer, causing your code to loop forever. Perhaps this is the unspecified crash you speak of?
Comments
def get_one_of(prompt, options, default=None):
options = set(options)
while True:
val = raw_input(prompt)
if val == '' and default is not None:
return default
elif val in options:
return val
response = get_one_of('Do you want to go first? [Yn] ', 'yYnN', 'y')
users_turn = response in 'yY'
breakin if clause