Search code examples
pythontic-tac-toe

How to improve a code for Tic Tac Toe-Check Victory in Python


I am writing a python code for making a tic tac toe game. I need to write a function that takes in three inputs, board, x, and y. Board being the current display of the board and then x and y being values of 0, 1, or 2. The game is set up to ask the user for coordinates.

def CheckVictory(board, x, y):

    #check if previous move was on vertical line and caused a win
    if board[0][y] == ('X') and board[1][y] == ('X') and board [2][y] == ('X'):
        return True
    if board[0][y] == ('O') and board[1][y] == ('O') and board [2][y] == ('O'):
        return True

    #check if previous move was on horizontal line and caused a win
    if board[x][0] == ('X') and board[x][1] == ('X') and board [x][2] == ('X'):
        return True
    if board[x][0] == ('O') and board[x][1] == ('O') and board [x][2] == ('O'):
        return True

    #check if previous move was on the main diagonal and caused a win
    if board[0][0] == ('X') and board[1][1] == ('X') and board [2][2] == ('X'):
        return True
    if board[0][0] == ('O') and board[1][1] == ('O') and board [2][2] == ('O'):
        return True
    #check if previous move was on the secondary diagonal and caused a win
    if board[0][2] == ('X') and board[1][1] == ('X') and board [2][0] == ('X'):
        return True
    if board[0][2] == ('O') and board[1][1] == ('O') and board [2][0] == ('O'):
        return True

    return False 
#end of CheckVictory function

the function is called in the game loop like so

p_x, p_y = playerTurn(board)    #let player take turn
displayBoard(board)             #show board after move has been made
if CheckVictory(board, p_x, p_y):   #see if user has won
    print("CONGRATULATIONS, you win!")
    newGame(board)  #game over start new one
    continue

and it's similar for the computer turn

I feel like there is a better way to write this function. I feel like I should be using x and y more or there is a better way to check rather than writing all the possibilities. So what's a better way to write this? To make it short and concise.


Solution

  • I can't see why you need x and y parameters, you're supposed to check if there are three X letters or three O letters in a row, you don't need coordinates for that. Instead edit the board first so it updates the coordinates player entered, then check if the victory happened.

    Here's how I would do it, but if you want to use your method - feel free to. You can still learn something from my version.

    def check_victory(board):
        combinations = [
            # horizontal
            ((0,0), (1,0), (2,0)),
            ((0,1), (1,1), (2,1)),
            ((0,2), (1,2), (2,2)),
            # vertical
            ((0,0), (0,1), (0,2)),
            ((1,0), (1,1), (1,2)),
            ((2,0), (2,1), (2,2)),
            # crossed
            ((0,0), (1,1), (2,2)),
            ((2,0), (1,1), (0,2))
        ]
    
        for coordinates in combinations:
            letters = [board[y][x] for x,y in coordinates]
            if len(set(letters)) == 1:
                return letters[0] # returns corresponding letter for winner (X/O)
    
        return False
    

    Notice that it uses list comprehension and sets. If you're not familiar with those, I recommend to learn them before using this solution.