1

I'm trying to make input validation with limits to only allow 'y/Y' or 'n/N'

I can't get the while loop to close when performing two checks like this. (i.e. the loop continues even if you enter "Y/y' or 'N/n'.)

print('Would you like to play a game?')
play_a_game = input()
while play_a_game.lower() != 'y' or play_a_game.lower() != 'n':
    print(play_a_game)
    print('Invalid input')
    print('Would you like to play a game?')
    play_a_game = input()

But if I limit the while statement to one check, the loop exits fine. (i.e. the loop closes if you enter 'Y/y'.

print('Would you like to play a game?')
play_a_game = input()
while play_a_game.lower() != 'y':
    print(play_a_game)
    print('Invalid input')
    print('Would you like to play a game?')
    play_a_game = input()
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
inlakechalakin
  • 43
  • 1
  • 1
  • 4
  • 1
    Consider: Which input is not unequal to ``'y'`` or ``'n'``? – MisterMiyagi Apr 14 '21 at 15:26
  • 1
    Use `and` instead of `or`. The input is invalid if it's not y and not n (neither y nor n). – AcK Apr 14 '21 at 15:28
  • That does appear to work, I must need to go review how and/or work. I thought it would have to be both with and, which is why I used or. Guess I was wrong. – inlakechalakin Apr 14 '21 at 15:31
  • 1
    Does this answer your question? [Asking the user for input until they give a valid response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) – SiHa Apr 14 '21 at 15:57

2 Answers2

2

The problem is the or operation. Let's make a truth table.

play_a_game.lower() != 'y' (A) != 'n' (B) A or B
'y' False True True
'n' True False True
'x' (anything else, invalid input) True True True

See why it happens now?

What you actually need:

while play_a_game.lower() != 'y' and play_a_game.lower() != 'n'
play_a_game.lower() != 'y' (A) != 'n' (B) A and B
'y' False True False
'n' True False False
'x' (anything else, invalid input) True True True

which is equivalent to

while play_a_game.lower() not in ('y', 'n')
play_a_game.lower() in ('y', 'n') (A) not in ('y', 'n') (not A)
'y' True False
'n' True False
'x' (anything else, invalid input) False True
Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
  • 1
    That makes perfect sense now. For some reason I was thinking the != would work similar to 'while not', but I see now how it keeps the while loop running because one of them is always true. – inlakechalakin Apr 14 '21 at 15:35
  • 1
    It does! Except in this case, you need to think about what you actually want: You want to loop when `play_a_game` is neither `y` nor `n`. So you need `not ('y' or 'n')`, which by [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) becomes `not 'y' and not 'n'` – Pranav Hosangadi Apr 14 '21 at 15:38
1

As stated in the above, the truth table will always evaluate to True and keep you in the loop. Consider limiting the response to 'N' or 'n' when asking the user if he/she wishes to keep playing the game?

i.e., while ((keep_playing != 'N') and (keep_playing != 'n')):

fjm
  • 21
  • 1