I'm just getting started with Python and was hoping for some feedback on a simple Tic-Tac-Toe game I wrote. Specifically, is there a simpler way to check the win conditions for the game, and to break the loops at the end without repeating the code twice, and just generally how to shorten this to achieve a similar effect?
print("Player 1 is 'X' and Player 2 is 'O'.\nEnter a number (0-8) to choose a \
space on the board.\nTake turns entering values until someone wins.\n\n[0, 1, 2] \
\n[3, 4, 5]\n[6, 7, 8]")
class Player:
def __init__(self,num,XO):
self.num = num
self.XO = XO
p1 = Player(1,'X') #odd
p2 = Player(2,'O') #even
plist = [p1,p2]
b = [['0','1','2'], ['3','4','5'], ['6','7','8']]
i = 0
while True:
for plyr in plist:
while True:
try:
p = int(input(f'Player {plyr.num}, enter a number: '))
row = int(p/3)
cel = p%3
if b[row][cel] is not 'X' and b[row][cel] is not 'O':
b[row][cel] = plyr.XO
break
else:
print(f"Space already taken by {b[row][cel]}")
except ValueError:
print("That's not a valid number. Try again and choose 0-8.")
bf = f"{b[0]}\n{b[1]}\n{b[2]}"
print(bf)
i+=1
def CheckWin(b):
if b[0][0]==b[0][1]==b[0][2]==plyr.XO or b[0][0]==b[1][0]==b[2][0]==plyr.XO or \
b[0][0]==b[1][1]==b[2][2]==plyr.XO or b[0][1]==b[1][1]==b[2][1]==plyr.XO or \
b[1][0]==b[1][1]==b[1][2]==plyr.XO or b[2][0]==b[2][1]==b[2][2]==plyr.XO or \
b[0][2]==b[1][2]==b[2][2]==plyr.XO:
print(f"Player {plyr.num} ('{plyr.XO}') wins!")
return 1
else:
pass
win = CheckWin(b)
if not win and i<9:
pass
elif not win and i==9:
print('The match is a tie.')
break
else:
break
if not win and i<9:
pass
elif not win and i==9:
break
else:
break
1 Answer 1
First off, I see no reason to define p1 and p2, then put them into the playerlist, it would be more concise to simply define them inside plist's definition.
eg.
plist = [Player(1,'X'), Player(2, 'O')]
As for the repetition of the if statements, you could set a global variable "gameOver" that gets set true upon a game ending event.
eg.
#Before loops
gameOver = False
...
#In for loop
if not win and i<9:
pass
elif not win and i==9:
gameOver = True
print('The match is a tie.')
break
else:
gameOver = True
break
#In first while loop
if gameOver:
break
else:
pass
This last part is just personal opinion, but I feel like asking the user for row and column would be more intuitive than cell number.
Edit: I just realized you could just do while not gameOver
, no need for the if else.