Мартин обнови решението на 11.04.2013 11:24 (преди над 12 години)
+class TicTacToeBoard():
+
+    def __init__(self):
+        self.FIELDS = ('A3', 'B3', 'C3',
+                       'A2', 'B2', 'C2', 'A1', 'B1', 'C1')
+        self.MARKS = ('X', 'O')
+        self.board = dict.fromkeys(self.FIELDS, ' ')
+        self.last_mark = ''
+        self._status = 'Game in progress.'
+
+    def __str__(self):
+        template = ('\n  -------------\n'
+                    '3 | {0} | {1} | {2} |\n'
+                    '  -------------\n'
+                    '2 | {3} | {4} | {5} |\n'
+                    '  -------------\n'
+                    '1 | {6} | {7} | {8} |\n'
+                    '  -------------\n'
+                    '    A   B   C  \n')
+        return template.format(*([self.board[field] for field in self.FIELDS]))
+
+    def __getitem__(self, field):
+        if field not in self.FIELDS:
+            raise NameError("wtf")
+        return self.board[field]
+
+    def __setitem__(self, field, mark):
+        if field not in self.FIELDS:
+            raise InvalidKey
+        if mark not in self.MARKS:
+            raise InvalidValue
+        if self.board[field] in self.MARKS:
+            raise InvalidMove
+        if self.last_mark == mark:
+            raise NotYourTurn
+
+        self.board[field] = self.last_mark = mark
+
+        if self.game_status() == 'Game in progress.':
+            winner = self.x_or_y_win()
+            if winner:
+                self._status = '{0} wins!'.format(winner)
+            if self.isBoardFull():
+                self._status = 'Draw!'
+
+    def game_status(self):
+        return self._status
+
+    def isBoardFull(self):
+        for value in self.board.values():
+            if value == ' ':
+                return False
+        return True
+
+    def x_or_y_win(self):
+        for line in ('1', '2', '3'):
+            horizontal = self['A'+line] + self['B'+line] + self['C'+line]
+            if horizontal == 'XXX' or horizontal == 'OOO':
+                return(self['A'+line])
+
+        for row in ('A', 'B', 'C'):
+            vertical = self[row+'1'] + self[row+'2'] + self[row+'3']
+            if vertical == 'XXX' or vertical == 'OOO':
+                return(self[row+'1'])
+
+        diagonal_1 = self['A1'] + self['B2'] + self['C3']
+        if diagonal_1 == 'XXX' or diagonal_1 == 'YYY':
+            return self['A1']
+
+        diagonal_2 = self['C1'] + self['B2'] + self['A3']
+        if diagonal_2 == 'XXX' or diagonal_2 == 'YYY':
+            return self['A1']
+
+
+class InvalidKey(Exception):
+    pass
+
+
+class InvalidValue(Exception):
+    pass
+
+
+class InvalidMove(Exception):
+    pass
+
+
+class NotYourTurn(Exception):
+    pass
