Tic Tac Toe checkWin Validator with Lists
Question:
I am attempting to make a checkWin module for my Tic Tac Toe game. I have done things differently than most other Tic Tac Toe examples but have hit a final snag in the game.
row1 = [" "," "," "]
row2 = [" "," "," "]
row3 = [" "," "," "]
def gameBoard ():
print ( row1[0], row1[1], row1[2] )
print ( row2[0], row2[1], row2[2] )
print ( row3[0], row3[1], row3[2] )
def checkPosition ( playerRow, playerColumn ):
if playerRow == 1:
return row1 [playerColumn - 1] == " "
elif playerRow == 2:
return row2 [playerColumn - 1] == " "
elif playerRow == 3:
return row3 [playerColumn - 1] == " "
#I feel as though this cannot be the only way to accomplish validation
def checkWin ( gameBoard ):
if row1[0] == "X" and row1[1] == "X" and row1[2] == "X":
while True:
playerRow = int ( input ( "Select a row: " ) )
playerColumn = int ( input ( "Select a column: " ) )
if checkPosition ( playerRow, playerColumn ) == True:
if turn % 2 == 0:
if playerColumn >= 1 and playerColumn <= 3:
if playerRow == 1:
row1[playerColumn - 1] = "X"
if playerRow == 2:
row2[playerColumn - 1] = "X"
if playerRow == 3:
row3[playerColumn - 1] = "X"
else:
if playerRow == 1:
row1[playerColumn - 1] = "O"
if playerRow == 2:
row2[playerColumn - 1] = "O"
if playerRow == 3:
row3[playerColumn - 1] = "O"
turn = turn + 1
else:
print ( "Position", playerRow, ",", playerColumn, "is already marked. Please try again." )
gameBoard ()
I am not the best with Python and am still learning. The only way my mind can validate the winner is if I go possible win outcome at a time with both X and O. I feel as there must be a much simpler way. Any suggestions would be much appreciated.
P.S. Yes I have left out a few lines for input and such due to the main issue is irrelevant to those lines.
P.P.S. Upvote if this was helpful.
Answers:
Instead of using three separate lists, you can use a 2D list for your checkWin()
function:
#2D List
board = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
#rest of code here
def checkWin ( gameBoard ):
for row in board: #check all rows first
if row[0] == row[1] == row[2]: #If all the items in row are the same
#code here
for i in range(3): #check all columns now
if gameBoard[0][i] == gameBoard[1][i] == gameBoard [2][i]:
#If the ith piece in each row is the same
#code here
Here’s the updated program:
def gameBoard ():
print (gameBoard[0][0], gameBoard[0][1], gameBoard[0][2])
print (gameBoard[1][0], gameBoard[1][1], gameBoard[1][2])
print (gameBoard[2][0], gameBoard[2][1], gameBoard[2][2])
def checkPosition ( playerRow, playerColumn ):
return board[playerRow][playerColumn - 1] == " "
def checkWin ( gameBoard ):
for row in gameBoard: #check all rows first
if row[0] == row[1] == row[2]: #If all the items in row are the same
return row[0]
for i in range(3): #check all columns now
if gameBoard[0][i] == gameBoard[1][i] == gameBoard [2][i]:
#If the ith piece in each row is the same
return gameBoard[0][i]
while True:
playerRow = int ( input ( "Select a row: " ) )
playerColumn = int ( input ( "Select a column: " ) )
if checkPosition ( playerRow, playerColumn ):
if turn % 2 == 0:
if playerColumn >= 1 and playerColumn <= 3:
board[playerRow][playerColumn - 1] = "X"
else:
board[playerRow] [playerColumn - 1] = "O"
turn = turn + 1
else:
print ( "Position", playerRow, ",", playerColumn, "is already marked. Please try again." )
gameBoard ()
I recommend reading about 2D lists here
For something as simple as Tic-Tac-Toe, it doesn’t really matter if your checking code is not a perfect example of minimalist code, since the naive code to do it is already very simple. I’d simply use something like:
# Function to check for win based on cell contents. Game board is:
# row1[n], n = : 0 | 1 | 2
# ---+---+---
# row2[n], n = : 0 | 1 | 2
# ---+---+---
# row3[n], n = : 0 | 1 | 2
#
# Cells are ' ' if unpopulated.
def checkWin(row1, row2, row3):
# Check rows (top, middle, bottom).
if row1[0] != ' ' and row1[0] == row1[1] and row1[0] == row1[2]: return row1[0]
if row2[0] != ' ' and row2[0] == row2[1] and row2[0] == row2[2]: return row2[0]
if row3[0] != ' ' and row3[0] == row3[1] and row3[0] == row3[2]: return row3[0]
# Check columns (left, middle, right).
if row1[0] != ' ' and row1[0] == row2[0] and row1[0] == row3[0]: return row1[0]
if row1[1] != ' ' and row1[1] == row2[1] and row1[1] == row3[1]: return row1[1]
if row1[2] != ' ' and row1[2] == row2[2] and row1[2] == row3[2]: return row1[2]
# Check diagonals (top-left-to-bottom-right, bottom-left-to-top-right).
if row1[0] != ' ' and row1[0] == row2[1] and row1[0] == row3[2]: return row1[0]
if row3[0] != ' ' and row3[0] == row2[1] and row3[0] == row1[0]: return row3[0]
# No winner.
return ' '
Now you could try to make that code shorter by use of loops and such but I’d seriously doubt that it would become more readable than what’s presented.
By way of example, the column checking code could be changed into:
# Check columns (left, middle, right).
for col in range(3):
if row1[col] != ' ' and row1[col] == row2[col] and row1[col] == row3[col]:
return row1[col]
But, in my opinion, that’s not really that much more readable that it warrants the “mind shift” that’s needed to distinguish it from the row and diagonal checking. But, of course, if you think differently, by all means use it.
I am attempting to make a checkWin module for my Tic Tac Toe game. I have done things differently than most other Tic Tac Toe examples but have hit a final snag in the game.
row1 = [" "," "," "]
row2 = [" "," "," "]
row3 = [" "," "," "]
def gameBoard ():
print ( row1[0], row1[1], row1[2] )
print ( row2[0], row2[1], row2[2] )
print ( row3[0], row3[1], row3[2] )
def checkPosition ( playerRow, playerColumn ):
if playerRow == 1:
return row1 [playerColumn - 1] == " "
elif playerRow == 2:
return row2 [playerColumn - 1] == " "
elif playerRow == 3:
return row3 [playerColumn - 1] == " "
#I feel as though this cannot be the only way to accomplish validation
def checkWin ( gameBoard ):
if row1[0] == "X" and row1[1] == "X" and row1[2] == "X":
while True:
playerRow = int ( input ( "Select a row: " ) )
playerColumn = int ( input ( "Select a column: " ) )
if checkPosition ( playerRow, playerColumn ) == True:
if turn % 2 == 0:
if playerColumn >= 1 and playerColumn <= 3:
if playerRow == 1:
row1[playerColumn - 1] = "X"
if playerRow == 2:
row2[playerColumn - 1] = "X"
if playerRow == 3:
row3[playerColumn - 1] = "X"
else:
if playerRow == 1:
row1[playerColumn - 1] = "O"
if playerRow == 2:
row2[playerColumn - 1] = "O"
if playerRow == 3:
row3[playerColumn - 1] = "O"
turn = turn + 1
else:
print ( "Position", playerRow, ",", playerColumn, "is already marked. Please try again." )
gameBoard ()
I am not the best with Python and am still learning. The only way my mind can validate the winner is if I go possible win outcome at a time with both X and O. I feel as there must be a much simpler way. Any suggestions would be much appreciated.
P.S. Yes I have left out a few lines for input and such due to the main issue is irrelevant to those lines.
P.P.S. Upvote if this was helpful.
Instead of using three separate lists, you can use a 2D list for your checkWin()
function:
#2D List
board = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
#rest of code here
def checkWin ( gameBoard ):
for row in board: #check all rows first
if row[0] == row[1] == row[2]: #If all the items in row are the same
#code here
for i in range(3): #check all columns now
if gameBoard[0][i] == gameBoard[1][i] == gameBoard [2][i]:
#If the ith piece in each row is the same
#code here
Here’s the updated program:
def gameBoard ():
print (gameBoard[0][0], gameBoard[0][1], gameBoard[0][2])
print (gameBoard[1][0], gameBoard[1][1], gameBoard[1][2])
print (gameBoard[2][0], gameBoard[2][1], gameBoard[2][2])
def checkPosition ( playerRow, playerColumn ):
return board[playerRow][playerColumn - 1] == " "
def checkWin ( gameBoard ):
for row in gameBoard: #check all rows first
if row[0] == row[1] == row[2]: #If all the items in row are the same
return row[0]
for i in range(3): #check all columns now
if gameBoard[0][i] == gameBoard[1][i] == gameBoard [2][i]:
#If the ith piece in each row is the same
return gameBoard[0][i]
while True:
playerRow = int ( input ( "Select a row: " ) )
playerColumn = int ( input ( "Select a column: " ) )
if checkPosition ( playerRow, playerColumn ):
if turn % 2 == 0:
if playerColumn >= 1 and playerColumn <= 3:
board[playerRow][playerColumn - 1] = "X"
else:
board[playerRow] [playerColumn - 1] = "O"
turn = turn + 1
else:
print ( "Position", playerRow, ",", playerColumn, "is already marked. Please try again." )
gameBoard ()
I recommend reading about 2D lists here
For something as simple as Tic-Tac-Toe, it doesn’t really matter if your checking code is not a perfect example of minimalist code, since the naive code to do it is already very simple. I’d simply use something like:
# Function to check for win based on cell contents. Game board is:
# row1[n], n = : 0 | 1 | 2
# ---+---+---
# row2[n], n = : 0 | 1 | 2
# ---+---+---
# row3[n], n = : 0 | 1 | 2
#
# Cells are ' ' if unpopulated.
def checkWin(row1, row2, row3):
# Check rows (top, middle, bottom).
if row1[0] != ' ' and row1[0] == row1[1] and row1[0] == row1[2]: return row1[0]
if row2[0] != ' ' and row2[0] == row2[1] and row2[0] == row2[2]: return row2[0]
if row3[0] != ' ' and row3[0] == row3[1] and row3[0] == row3[2]: return row3[0]
# Check columns (left, middle, right).
if row1[0] != ' ' and row1[0] == row2[0] and row1[0] == row3[0]: return row1[0]
if row1[1] != ' ' and row1[1] == row2[1] and row1[1] == row3[1]: return row1[1]
if row1[2] != ' ' and row1[2] == row2[2] and row1[2] == row3[2]: return row1[2]
# Check diagonals (top-left-to-bottom-right, bottom-left-to-top-right).
if row1[0] != ' ' and row1[0] == row2[1] and row1[0] == row3[2]: return row1[0]
if row3[0] != ' ' and row3[0] == row2[1] and row3[0] == row1[0]: return row3[0]
# No winner.
return ' '
Now you could try to make that code shorter by use of loops and such but I’d seriously doubt that it would become more readable than what’s presented.
By way of example, the column checking code could be changed into:
# Check columns (left, middle, right).
for col in range(3):
if row1[col] != ' ' and row1[col] == row2[col] and row1[col] == row3[col]:
return row1[col]
But, in my opinion, that’s not really that much more readable that it warrants the “mind shift” that’s needed to distinguish it from the row and diagonal checking. But, of course, if you think differently, by all means use it.