0

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
  • "my code seems to crash" -- In what way, more precisely? What's the error? Commented Feb 8, 2014 at 3:21
  • you are missing break in if clause Commented Feb 8, 2014 at 3:22
  • If any of these answers helped you, you should select one as a solution. Commented Feb 10, 2014 at 4:49

3 Answers 3

2

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']
Sign up to request clarification or add additional context in comments.

3 Comments

@zhangxaochen I saw your edit to use a string, but I think I still prefer using a list -- that way you can add other possible answers likes 'yes', 'no' and initials to support other languages.
yes and I removed that edit also because 'Yn' in 'yYnN' gives True. sorry ;P
@zhangxaochen oh yeah, there's also that! =)
0

Just 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 NameError block is completely redundant, since nothing in your code will throw NameError, and especially not to signal an actual user error.
  • You have your else line at the wrong indentation. As it stands, it matches the while block rather than if/elif block, causing behavior you most likely do not intend.
  • The break in the elif block is redundant, since the while loop will exit anyway when you've set valid_choice to True.
  • 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

0
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'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.