[Tutor] programming tic tac toe

Lie Ryan lie.1296 at gmail.com
Thu Aug 21 19:42:23 CEST 2008


> Message: 1
> Date: Thu, 21 Aug 2008 06:53:50 +0100
> From: "Alan Gauld" <alan.gauld at btinternet.com>
> Subject: Re: [Tutor] programming tic tac toe
> To: tutor at python.org
> Message-ID: <g8ivti$rj6$1 at ger.gmane.org>
> Content-Type: text/plain; format=flowed; charset="iso-8859-1";
>         reply-type=original
> 
> "Ark" <cloudneozero at gmail.com> wrote
> 
> > I used a list (with lists inside) to represent the board.  And to 
> > identify a
> > winning line I used many if's, like this one:
> > def line(board):
> >    if board[0][0] == board[1][1] == board[2][2]:
> >        return True
> 
> > I did not like using all those if's, and I would like to hear 
> > suggestions to
> > find a line in the board, maybe a more  intelligent approach.
> 
> Given that there are always 3x3 cells on an oxo board and
> therefore only 8 possible winning lines hard coding is probably
> a reasonable approach. You could make it into a single boolean
> condition which would be slightly less typing and slightly faster
> but otherwise what you have is fine I think:
> 
> def line(board):
>     return  board[0][0] == board[0][1] == board[0][2] or
>               board[1][0] == board[1][1] == board[1][2] or
>               ...
>               board[2][0] == board[1][1] == board[[0][2]
> 
> But I'm not sure its that much nicer! :-)
> 
> For the more general case of an NxN board then you
> should probably consider using a loop and relative
> indexing but for 3x3 hard coded is better IMHO.

For a generic NxM board, which wouldn't require any change of code for
any board size, you might do something like this:

The board class:
Instead of using string as the representation of X and Y, you use +1 and
-1 for X and O, and 0 for unfilled square.

The check:
For each rows and columns sum the line. If the sum equals to the width
(for row) or height (for column), then we've got a winner (we've got a
line that stretch from one end to another). Check the main diagonals'
sum too.

i.e.:
[[0, 0, -1 ],
 [1, 0, -1],
 [1, 1, -1 ],] 

Sum for:
Row 1: 0 + 0 + -1 = -1
Row 2: 1 + 0 + -1 = 0
Row 3: 1 + 1 + -1 = 1
Col 1: 0 + 1 + 1  = 2
Col 2: 0 + 0 + 1  = 1
Col 3: -1 + -1 + -1 = -3 # We've got a winner
Diag 1: 0 + 0 + -1 = -1
Diag 2: 1 + 0 + -1 = 0

in code: (untested)
class Board(object):
    ...
    def iter_row(self):
        for row in self.board:
            yield row
    def iter_col(self):
        for col_num in range(len(self.board[0])):
            ret = []
            for row in self.board:
                ret.append(row[col_num])
            return ret

    def diagonals(self):
        ret = []
        for n in range(len(self.board)):
            ret.append(self.board[n][n])
        yield ret
        ret = []
        for n in range(len(self.board)):
            ret.append(self.board[-n - 1][-n - 1])
        yield ret
    ...
    def check(self):
        for row in self.iter_row:
            if sum(row) >= 3: print 'Winner X'
            if sum(row) <= -3: print 'Winner O'
        for col in self.iter_col:
            if sum(col) >= 3: print 'Winner X'
            if sum(col) <= -3: print 'Winner O'
        for diag in self.diagonals:
            if sum(diag) >= 3: print 'Winner X'
            if sum(diag) <= -3: print 'Winner O'
    ....

It wouldn't be hard to make it a bit more shorter, like using this for 
import itertools
def check(self):
    for line in itertools.chain(self.iter_row, self.iter_col,
self.diagonals):
        if sum(line) >= 3: print 'Winner X'
        if sum(line) <= -3: print 'Winner O'

But personally, I think it'd be hard to read and understand.

After all these talks, if your Tic Tac Toe's board size is hard coded,
yes, it'd be much better just to use plain long if-elifs.



More information about the Tutor mailing list