I have the task of writing a function to determine the outcome of a game of tictactoe, i at first thought use a couple of for loops but that proved pointless, and then the only way i could think of was to write an if...elif...else statement for each row, column and diagonal. which isnt very impressive, so can anyone show me, or hint at a way to do this?
below is exactly what it says on the site.

In the pencil-and-paper game, Tic-tac-toe, 2 players take turns to mark 'X' and 'O' on a board of 3x3 squares. The player who succeeds in marking 3 successive 'X' or 'O' in vertical, horizontal or diagonal stripe wins the game. Write a function that determines the outcome of a tic-tac-toe game.

Examples

    >>> tictactoe([('X', ' ', 'O'), 
                   (' ', 'O', 'O'), 
                   ('X', 'X', 'X') ])
    "'X' wins (horizontal)."
    >>> tictactoe([('X', 'O', 'X'), 
    ...            ('O', 'X', 'O'), 
    ...            ('O', 'X', 'O') ])
    'Draw.'
    >>> tictactoe([('X', 'O', 'O'), 
    ...            ('X', 'O', ' '), 
    ...            ('O', 'X', ' ') ])
    "'O' wins (diagonal)."
    >>> tictactoe([('X', 'O', 'X'), 
    ...            ('O', 'O', 'X'), 
    ...            ('O', 'X', 'X') ])
    "'X' wins (vertical)."

Help much appreciated.

Dani AI

Generated

: A compact, readable way is to build the eight candidate lines (three rows, three columns, two diagonals) from the 3x3 tuple and test each for three identical non-space marks. This keeps the logic local and avoids a long cascade of if/elif. It also complements 's set-based idea (which is great when squares are numbered): the following works directly with the tuple-of-rows representation shown in the question.

def tictactoe(board):
    # board: sequence of 3 sequences of length 3 containing 'X', 'O' or ' '
    if len(board) != 3 or any(len(row) != 3 for row in board):
        raise ValueError("board must be 3x3")

    lines = []
    for row in board:
        lines.append(('horizontal', tuple(row)))
    for col in zip(*board):
        lines.append(('vertical', tuple(col)))
    lines.append(('diagonal', (board[0][0], board[1][1], board[2][2])))
    lines.append(('diagonal', (board[0][2], board[1][1], board[2][0])))

    winners = []
    for kind, line in lines:
        a, b, c = line
        if a == b == c and a != ' ':
            winners.append((a, kind))

    if not winners:
        if any(cell == ' ' for row in board for cell in row):
            return 'No winner yet.'
        return 'Draw.'

    players = {w for w, _ in winners}
    if len(players) > 1:
        return 'Invalid board: both players have winning lines.'
    player, kind = winners[0]
    return "'{}' wins ({}).".format(player, kind)

Notes: the function returns the same human-readable phrases used in the examples. It flags impossible states where both players appear to win; for stricter validation add a check on counts (e.g. abs(x_count - o_count) in (0,1)) to detect illegal move sequences. The algorithm is O(1) here because the board size is fixed; it is simple, easy to test, and easier to extend (to report which row/column/diagonal) if desired.

Sets are the way to go

# assumes each square is numbered 1 thorugh 9, not 0 through 8
##             rows, columns, & diagonals
winner_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], \
               [1, 4, 7], [2, 5, 8], [3, 6, 9], \
               [1, 5, 9], [3, 5, 7]]

""" use something like
for winner in winner_list:
    if set(winner).issubset(player_set):

so
tictactoe([('X', ' ', 'O'), 
           (' ', 'O', 'O'), 
           ('X', 'X', 'X') ])
becomes [1, 7, 8, 9] for X
and [3, 5, 6] for O

A tie = all squares filled and no winner
""" 
X=[1, 7, 8, 9]
for winner in winner_list:
    if set(winner).issubset(set(X)):
        print "Is a winner", winner
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.