Добринка обнови решението на 15.04.2013 01:03 (преди над 11 години)
+import re
+
+
+class TicTacToeBoard:
+ ALPHA_KEYS = {"A": 0, "B": 1, "C": 2}
+ NUM_KEYS = {"3": 2, "2": 1, "1": 0}
+ PLAYER_X = 'X'
+ PLAYER_O = 'O'
+
+ def __init__(self):
+ self.board = [[" " for i in range(0, 3)] for i in range(0, 3)]
+ self.next_player = None
+
+ def __str__(self):
+ result = ""
+ devider = "\n -------------\n"
+ result += devider
+ for i in reversed(range(0, 3)):
+ result += str(i+1) + " "
+ for j in range(0, 3):
+ result += "| " + self.board[i][j] + " "
+
+ result += "|"
+ result += devider
+
+ result += " A B C \n"
+ return result
+
+ def __setitem__(self, key, value):
+ if not self._check_valid_key(key):
+ raise InvalidKey("Invalid key!")
+
+ if not self._check_valid_value(value):
+ raise InvalidValue("Invalid value!")
+
+ indexes = self._calculate_indexes(key)
+ if self.board[indexes[0]][indexes[1]] != " ":
+ raise InvalidMove("Invalid move!")
+
+ if not self._check_your_turn(value):
+ raise NotYourTurn
+
+ self.board[indexes[0]][indexes[1]] = value
+
+ def __getitem__(self, key):
+ if not self._check_valid_key(key):
+ raise InvalidKey("Invalid key!")
+
+ indexes = self._calculate_indexes(key)
+ return self.board[indexes[0]][indexes[1]]
+
+ def _calculate_indexes(self, key):
+ i = self.ALPHA_KEYS[key[0]]
+ j = self.NUM_KEYS[key[1]]
+ return (j, i)
+
+ def game_status(self):
+ if self._check_win(self.PLAYER_X):
+ return "X wins!"
+ if self._check_win(self.PLAYER_O):
+ return "O wins!"
+ if self._check_draw():
+ return "Draw!"
+ return "Game in progress."
+
+ def _check_draw(self):
+ for i in range(0, 3):
+ for j in range(0, 3):
+ if self.board[i][j] == " ":
+ return False
+
+ return True
+
+ def _check_win(self, player):
+ return (self._check_win_rows(player) or
+ self._check_win_cols(player) or
+ self._check_win_diag(player) or
+ self._check_win_antidiag(player))
+
+ def _check_win_rows(self, player):
+ win = True
+ for i in range(0, 3):
+ for j in range(0, 3):
+ if self.board[i][j] != player:
+ win = False
+ break
+ if win:
+ return win
+ return win
+
+ def _check_win_cols(self, player):
+ win = True
+ for i in range(0, 3):
+ for j in range(0, 3):
+ if self.board[j][i] != player:
+ win = False
+ break
+ if win:
+ return win
+ return win
+
+ def _check_win_diag(self, player):
+ win = True
+ for i in range(0, 3):
+ if self.board[i][i] != player:
+ win = False
+ break
+ return win
+
+ def _check_win_antidiag(self, player):
+ win = True
+ for i in range(0, 3):
+ if self.board[i][2-i] != player:
+ win = False
+ break
+ return win
+
+ def _check_valid_key(self, key):
+ return re.match(r'(^([ABC][123])$)', key)
+
+ def _check_valid_value(self, value):
+ return re.match(r'(^[XO]$)', value)
+
+ def _check_your_turn(self, player):
+ if self.next_player is None or self.next_player == player:
+ if player == self.PLAYER_X:
+ self.next_player = self.PLAYER_O
+ else:
+ self.next_player = self.PLAYER_X
+ return True
+
+ return False
+
+
+class InvalidKey(Exception):
+ pass
+
+
+class InvalidValue(Exception):
+ pass
+
+
+class InvalidMove(Exception):
+ pass
+
+
+class NotYourTurn(Exception):
+ pass
Дай по-подходящи имена на променливите: i
, j
Влагането е зло. Опитвай да решаваш задачи с по-малко нива на влагане.
Всичките ти _check_win_...
методи изглеждат ужасяващо подобни. Можеш да направиш един вместо четири абстрахирайки се от проверяваните полета.
__str__
методът ти може да се възползва от форматиране на низове за четимост и пригледност.