IntroGrammer IntroGrammer - 7 months ago 9
Python Question

What is causing one block of code to loop and the other not?

So as a learning assignment in working with python I am to create a basic tic-tac-toe program.

My question is between these two blocks of code:

letter = ''
while (letter != 'X' or letter != 'O'):
letter = raw_input("Player 1 select your letter (X or O)")
letter = letter.upper()
if letter == 'X':
return ['X','O']
else:
return ['O','X']


and

letter = ''
while not (letter == 'X' or letter == 'O'):
letter = raw_input("Player 1 select your letter (X or O)")
letter = letter.upper()
if letter == 'X':
return ['X','O']
else:
return ['O','X']


As you can see there is only one difference between the blocks of code, specifically the second line of each block.

The first block of code regardless of what the user inputs, gets stuck in the loop and continuously asks the user what letter they want.

The second block of code works as intended.

Can you please explain why this is the case as to my understanding the line in the first code reads the same as the second.

Thank you.

Answer

This is fundamental logic, which you will get better at with practice.

letter != 'X' or letter != 'O'

Imagine a letter - any letter. Let's first pick 'X'. It does not satisfy the first expression of letter != 'X', but it does satisfy the second expression of letter != 'O'. Now let's try 'O'. That satisfies the first expression but not the second. Now try it with any character other than 'X' or 'O', like 'N'. That satisfies both expression. No matter what you pick, the condition will be satisfied and the loop will always execute.

letter == 'X' or letter == 'O'

Here, only 'X' will satisfy the first expression, and only 'O' will satisfy the second. No other value will satisfy the condition. This means that the loop will only execute if letter is 'X' or 'O'.

The first code block could be repaired as follows:

letter != 'X' and letter != 'O'

This means that if the letter isn't 'X' and the letter isn't 'O', the loop will execute. 'X' or 'O' will stop execution.

You could also use this condition:

letter not in 'XO'

If letter is not a member of that string, the loop will execute. Note that this would break if letter is literally 'XO' - if you don't trust the user, you should make an adjustment:

letter not in {'X', 'O'}

It's a little larger, but also safer if you expect the possibility of multiple-character inputs.