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.

Asked By: Twissted

||

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

Answered By: lyxal

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.

Answered By: paxdiablo
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.