Python - Determine Tic-Tac-Toe Winner

29,968

Solution 1

You can just make a set of each row, and check its length. If it contains only one element, then the game has been won.

def returnWinner(board):
    for row in board:
        if len(set(row)) == 1:
            return row[0]
    return -1

This will return "O" if there is a full line of "O", "X" if there is a line of "X", and -1 otherwise.

Below is the code of a full Tic-Tac-Toe checker, it should not be hard to understand, but do not hesitate to ask:

import numpy as np

def checkRows(board):
    for row in board:
        if len(set(row)) == 1:
            return row[0]
    return 0

def checkDiagonals(board):
    if len(set([board[i][i] for i in range(len(board))])) == 1:
        return board[0][0]
    if len(set([board[i][len(board)-i-1] for i in range(len(board))])) == 1:
        return board[0][len(board)-1]
    return 0

def checkWin(board):
    #transposition to check rows, then columns
    for newBoard in [board, np.transpose(board)]:
        result = checkRows(newBoard)
        if result:
            return result
    return checkDiagonals(board)


a = [['X', 'A', 'X'],
     ['A', 'X', 'A'],
     ['A', 'X', 'A']]

print(checkWin(a))

Note that this works regardless of the symbols you choose to put in your tic-tac-toe ("O" & "X" is as fine as "bloop" & "!"), and for any size of grid, as long as it is a square.

Solution 2

One way to do this would be to create a set (a generator function would be even better) of all the possible index combinations to check for the win. Then loop through those index combinations and check if they all contain the same value, if so, then it's a win.

def win_indexes(n):
    # Rows
    for r in range(n):
        yield [(r, c) for c in range(n)]
    # Columns
    for c in range(n):
        yield [(r, c) for r in range(n)]
    # Diagonal top left to bottom right
    yield [(i, i) for i in range(n)]
    # Diagonal top right to bottom left
    yield [(i, n - 1 - i) for i in range(n)


def is_winner(board, decorator):
    n = len(board)
    for indexes in win_indexes(n):
        if all(board[r][c] == decorator for r, c in indexes):
            return True
    return False

Solution 3

def check_winner(board,mark):
    return((board[1]==mark and board[2]== mark and board[3]==mark )or #for row1 

            (board[4]==mark and board[5]==mark and board[6]==mark )or #for row2

            (board[7]==mark and board[8]==mark and board[9]==mark )or #for row3

            (board[1]==mark and board[4]==mark and board[7]== mark )or#for Colm1 

            (board[2]==mark and board[5]==mark and board[8]==mark )or #for Colm 2

            (board[3]==mark and board[6]==mark and board[9]==mark )or #for colm 3

            (board[1]==mark and board[5]==mark and board[9]==mark )or #daignole 1

            (board[3]==mark and board[5]==mark and board[7]==mark )) #daignole 2

Solution 4

I just came up with this little piece of code:

def eval_w(board):
possible = []

#rows
for i in range(3):
    possible.append( board[i][0] + board[i][1] + board[i][2] )

#columns
for i in range(3):
    possible.append( board[0][i] + board[1][i] + board[2][i] )

#diagonals
possible.append( board[0][0] + board[1][1] + board[2][2] )
possible.append( board[0][2] + board[1][1] + board[2][0] )

if 3 in possible:
    ended = True
    return 1
elif -3 in possible:
    ended = True
    return -1
else:
    return 0

I haven't seen anything similar here, so I might as well post it.

Share:
29,968
Saadat
Author by

Saadat

System.out.println("Sta Awesome!);

Updated on November 26, 2021

Comments

  • Saadat
    Saadat over 2 years

    I am trying to write a code that determines the winner of a tic-tac-toe game. (This is for a college assignment)

    I have written the following function to do so:

    This code only checks for horizontal lines, I haven't added the rest. I feel that this is something that needs a bit of hardcoding.

    def iswinner(board, decorator):
        win = True
        for row in range(len(board)):
            for col in range(len(board)):
                if board[row][col] == decorator:
                    win = True
                else:
                    win = False
                    break
    

    Where "board" is a 2D array of size n^2 and "decorator" is the "X" or "O" value

    What I hope to accomplish is that the function loops through the 2D array's rows. Then loops through the values in each row. If that element matches the "decorator" then it continues and checks the next but if it doesn't, then it breaks from the first loop and goes to the next row. It does this until it finds n elements in the same row. Then it would give a bool value of True otherwise False.

    The code doesn't seem to do that and even when I checked with the following "board" it gave me an output of "True"

    check_list = [['O', 'X', 'X'],
                  ['O', 'X', 'O'],
                  ['O', 'X', 'X']]
    

    Thank you so much!

    Best, Seyed