Python - Determine Tic-Tac-Toe Winner

我的未来我决定 提交于 2020-07-06 20:42:37

问题


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


回答1:


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



回答2:


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.




回答3:


You can do it by creating a generator, lines() that yields all 8 lines (3 rows, 3 columns and 2 diagonals) and then checking if any of the lines is made up of only one element and that element isn't None

Once you've got something like

board = [
    [ 'o', 'x', None], 
    [None, 'x', None], 
    [None, 'x',  'o']
]

Do this:

def _lines(board):
    yield from board  # the rows
    yield [board[i][i] for i in range(len(board))]  # one of the diagonals

def lines(board):
    yield from _lines(board)
    # rotate the board 90 degrees to get the columns and the other diagonal
    yield from _lines(list(zip(*reversed(board))))

def who_won(board):
    for line in lines(board):
        if len(set(line)) == 1 and line[0] is not None:
            return line[0]
    return None  # if we got this far, there's no winner

For the board I gave above, list(lines(board)) will return

[['o', 'x', None], 
 [None, 'x', None], 
 [None, 'x', 'o'], 
 ['o', 'x', 'o'], 
 (None, None, 'o'), 
 ('x', 'x', 'x'), 
 ('o', None, None), 
 [None, 'x', None]]

3 of those elements are tuples instead of lists because zip returns tuples. You can convert them using a list comprehension, see this question for how to do that and more details about what zip(*reversed(some_list)) does.

Then it's just a matter of checking each one to see if it has only one unique element by converting to a set and that that unique element is not None.

This works unmodified for any sized tic-tac-toe board, not just 3×3.




回答4:


There are a total of 3 states that a cell can have

  1. 0 if it is not yet filled ( There is a possibility that the game gets over in 5 moves)
  2. 1 if it is filled with 'X'
  3. -1 if it is filled with 'O'

I will expand on @EfferLagan answer

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

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

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)

randomInput=[
    [0,0,1],
    [-1,-1,1],
    [0,0,0]
]

You have 3 outputs 1, -1, and 999 ( which means neither won ) checkWin(randomInput)



来源:https://stackoverflow.com/questions/39922967/python-determine-tic-tac-toe-winner

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!