Python program to know who wins a tic-tac-toe game Given an input where we have two players: "X" and "O", and empty cells marked with a "." like:

check_winner([
        "X.O",
        "XX.",
        "XOO"])

the program outputs if there are three "X" or "O" in horizontal, vertical or diagonal. If there is a draw it outputs "D".



def check_winner(game_result: List[str]) -&gt; str:

    for i, row in enumerate(game_result):
        if game_result[i][0] == game_result[i][1] == game_result[i][2]:
            if game_result[i][0] != ".":
                return game_result[i][0]
        if game_result[0][i] == game_result[1][i] == game_result[2][i]:
            if game_result[0][i] != ".":
                return game_result[0][i]

    if game_result[0][0] == game_result[1][1] == game_result[2][2]:
        if game_result[1][1] != ".":
            return game_result[1][1]

    if game_result[0][2] == game_result[1][1] == game_result[2][0]:
        if game_result[1][1] != ".":
            return game_result[1][1]

    return "D"


How could we improve this code?
To avoid repetitious code, look for commonality. Here, there's a repeated task of checking whether a group of 3 characters are all the same (and not .). This could be done more generally using a set. Sets don't carry duplicates, so if the set of a group has length 1, that means all characters were the same.

The example below shows this idea, by first extracting the different groups and then iterating over them all. This probably means it's less efficient than it could be - it would be faster to create as few groups as possible - but I think the code is somewhat legible at least.

def check_winner(lst):

    # collect "triplets": rows, columns and diagonals
    rows = lst[:]
    cols = list(zip(*lst))
    diag1 = [row[i] for i, row in enumerate(rows)]
    diag2 = [row[2 - i] for i, row in enumerate(rows)]
    triplets = rows + cols + [diag1, diag2]

    # if all characters in a triplet are the same, and that character
    # is not ".", then that character marks the winner
    for triplet in triplets:
        if len(set(triplet)) == 1 and triplet[0] != '.':
            return triplet[0]
    return 'D'

print(check_winner([ "X.O", "XX.", "XOO"]))