Решение на Морски шах от Йордан Джамбазов

Обратно към всички решения

Към профила на Йордан Джамбазов

Резултати

  • 6 точки от тестове
  • 1 бонус точка
  • 7 точки общо
  • 8 успешни тест(а)
  • 0 неуспешни тест(а)

Код

import re
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class TicTacToeBoard(dict):
def __init__(self, players=None, columns=None, rows=None):
self.players = players or ('X', 'O')
self.columns = columns or ('A', 'B', 'C')
self.rows = rows or range(1, 4)
self.moves = []
self.cells_count = len(self.columns) * len(self.rows)
def __str__(self):
row_separator = '\n ' + '-' * int(4 * len(self.columns) + 1) + '\n'
board_string = row_separator
for row in reversed(self.rows):
board_string += '%d |' % row
for column in self.columns:
board_string += ' %s |' % dict(
self.moves).get('%s%d' % (column, row), ' ')
board_string += row_separator
board_string += ' ' + ' '.join(
[' %s ' % column for column in self.columns]) + ' \n'
return board_string
def game_status(self):
cols = self.columns
rows = self.rows
win = [['%s%d' % (col, row) for col in cols] for row in rows] +\
[['%s%d' % (col, row) for row in rows] for col in cols] +\
[['%s%d' % (col, dep+1) for dep, col in enumerate(cols)]] +\
[['%s%d' % (col, dep+1)
for dep, col in enumerate(reversed(cols))]]
for player in self.players:
if any([all([dict(self.moves).get(pattern_item) == player
for pattern_item in pattern]) for pattern in win]):
return '%s wins!' % player
if len(self.moves) == self.cells_count:
return 'Draw!'
else:
return 'Game in progress.'
def __setitem__(self, key, value):
if key in self.keys():
raise InvalidMove()
if value not in self.players:
raise InvalidValue()
if not re.match('^[%s-%s][%d-%d]$' % (self.columns[0],
self.columns[-1],
self.rows[0],
self.rows[-1]), key):
raise InvalidKey()
if self.moves and self.moves[-1][1] == value:
raise NotYourTurn()
self.moves.append((key, value))
return dict.__setitem__(self, key, value)

Лог от изпълнението

........
----------------------------------------------------------------------
Ran 8 tests in 0.011s

OK

История (3 версии и 4 коментара)

Йордан обнови решението на 09.04.2013 18:37 (преди над 11 години)

+import re
+
+
+class InvalidMove(Exception):
+ pass
+
+
+class InvalidValue(Exception):
+ pass
+
+
+class InvalidKey(Exception):
+ pass
+
+
+class NotYourTurn(Exception):
+ pass
+
+
+class TicTacToeBoard(dict):
+
+ def __init__(self, players=None, columns=None, rows=None):
+ self.players = ('X', 'O') if players is None else players
+ self.columns = ('A', 'B', 'C') if columns is None else columns
+ self.rows = range(1, 4) if rows is None else rows
+ self.moves = []
+ self.cells_count = len(self.columns) * len(self.rows)
+
+ def __str__(self):
+ row_separator = '\n ' + '-' * 13 + '\n'
+ board_string = row_separator
+ for row in reversed(self.rows):
+ board_string += '%d |' % row
+ for column in self.columns:
+ board_string += ' %s |' % dict(
+ self.moves).get('%s%d' % (column, row), ' ')
+ board_string += row_separator
+ board_string += ' ' + ' '.join(
+ [' %s ' % column for column in self.columns]) + ' \n'
+ return board_string
+
+ def game_status(self):
+ cols = self.columns
+ rows = self.rows
+ win = [['%s%d' % (col, row) for col in cols] for row in rows] +\
+ [['%s%d' % (col, row) for row in rows] for col in cols] +\
+ [['%s%d' % (col, dep+1) for dep, col in enumerate(cols)]] +\
+ [['%s%d' % (col, dep+1)
+ for dep, col in enumerate(reversed(cols))]]
+ for player in self.players:
+ if any([all([dict(self.moves).get(pattern_item) == player
+ for pattern_item in pattern]) for pattern in win]):
+ return '%s wins!' % player
+ if len(self.moves) == self.cells_count:
+ return 'Draw!'
+ else:
+ return 'Game in progress.'
+
+ def __setitem__(self, key, value):
+ if key in self.keys():
+ raise InvalidMove()
+ if value not in self.players:
+ raise InvalidValue()
+ if not re.match('^[%s-%s][1-3]$' % (self.columns[0],
+ self.columns[-1]), key):
+ raise InvalidKey()
+ if self.moves and self.moves[-1][1] == value:
+ raise NotYourTurn()
+
+ self.moves.append((key, value))
+ return dict.__setitem__(self, key, value)

Един от feature-те на моят код е, че може да работи с променлива бройка редове/колони :)

In [6]: board = TicTacToeBoard(columns=('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'), rows=range(1,9))

In [7]: print(board)

  ---------------------------------
8 |   |   |   |   |   |   |   |   |
  ---------------------------------
7 |   |   |   |   |   |   |   |   |
  ---------------------------------
6 |   |   |   |   |   |   |   |   |
  ---------------------------------
5 |   |   |   |   |   |   |   |   |
  ---------------------------------
4 |   |   |   |   |   |   |   |   |
  ---------------------------------
3 |   |   |   |   |   |   |   |   |
  ---------------------------------
2 |   |   |   |   |   |   |   |   |
  ---------------------------------
1 |   |   |   |   |   |   |   |   |
  ---------------------------------
    A   B   C   D   E   F   G   H  

Йордан обнови решението на 09.04.2013 18:45 (преди над 11 години)

import re
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class TicTacToeBoard(dict):
def __init__(self, players=None, columns=None, rows=None):
self.players = ('X', 'O') if players is None else players
self.columns = ('A', 'B', 'C') if columns is None else columns
self.rows = range(1, 4) if rows is None else rows
self.moves = []
self.cells_count = len(self.columns) * len(self.rows)
def __str__(self):
- row_separator = '\n ' + '-' * 13 + '\n'
+ row_separator = '\n ' + '-' * int(4 * len(self.columns) + 1) + '\n'
board_string = row_separator
for row in reversed(self.rows):
board_string += '%d |' % row
for column in self.columns:
board_string += ' %s |' % dict(
self.moves).get('%s%d' % (column, row), ' ')
board_string += row_separator
board_string += ' ' + ' '.join(
[' %s ' % column for column in self.columns]) + ' \n'
return board_string
def game_status(self):
cols = self.columns
rows = self.rows
win = [['%s%d' % (col, row) for col in cols] for row in rows] +\
[['%s%d' % (col, row) for row in rows] for col in cols] +\
[['%s%d' % (col, dep+1) for dep, col in enumerate(cols)]] +\
[['%s%d' % (col, dep+1)
for dep, col in enumerate(reversed(cols))]]
for player in self.players:
if any([all([dict(self.moves).get(pattern_item) == player
for pattern_item in pattern]) for pattern in win]):
return '%s wins!' % player
if len(self.moves) == self.cells_count:
return 'Draw!'
else:
return 'Game in progress.'
def __setitem__(self, key, value):
if key in self.keys():
raise InvalidMove()
if value not in self.players:
raise InvalidValue()
if not re.match('^[%s-%s][1-3]$' % (self.columns[0],
self.columns[-1]), key):
raise InvalidKey()
if self.moves and self.moves[-1][1] == value:
raise NotYourTurn()
self.moves.append((key, value))
return dict.__setitem__(self, key, value)

Като цяло избягвам да слагам каквито и да било структури като default аргументи (след това на човека който чете кога му се налага да се сеща дали са mutable/immutable)

>>> def a(b=[1,2], c=(1,2)):
...   b.append(3)
...   c += (3,)
...   print(b, c)
... 
>>> a()
[1, 2, 3] (1, 2, 3)
>>> a()
[1, 2, 3, 3] (1, 2, 3)

Йордан обнови решението на 11.04.2013 23:58 (преди над 11 години)

import re
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class TicTacToeBoard(dict):
def __init__(self, players=None, columns=None, rows=None):
- self.players = ('X', 'O') if players is None else players
- self.columns = ('A', 'B', 'C') if columns is None else columns
- self.rows = range(1, 4) if rows is None else rows
+ self.players = players or ('X', 'O')
+ self.columns = columns or ('A', 'B', 'C')
+ self.rows = rows or range(1, 4)
self.moves = []
self.cells_count = len(self.columns) * len(self.rows)
def __str__(self):
row_separator = '\n ' + '-' * int(4 * len(self.columns) + 1) + '\n'
board_string = row_separator
for row in reversed(self.rows):
board_string += '%d |' % row
for column in self.columns:
board_string += ' %s |' % dict(
self.moves).get('%s%d' % (column, row), ' ')
board_string += row_separator
board_string += ' ' + ' '.join(
[' %s ' % column for column in self.columns]) + ' \n'
return board_string
def game_status(self):
cols = self.columns
rows = self.rows
win = [['%s%d' % (col, row) for col in cols] for row in rows] +\
[['%s%d' % (col, row) for row in rows] for col in cols] +\
[['%s%d' % (col, dep+1) for dep, col in enumerate(cols)]] +\
[['%s%d' % (col, dep+1)
for dep, col in enumerate(reversed(cols))]]
for player in self.players:
if any([all([dict(self.moves).get(pattern_item) == player
for pattern_item in pattern]) for pattern in win]):
return '%s wins!' % player
if len(self.moves) == self.cells_count:
return 'Draw!'
else:
return 'Game in progress.'
def __setitem__(self, key, value):
if key in self.keys():
raise InvalidMove()
if value not in self.players:
raise InvalidValue()
- if not re.match('^[%s-%s][1-3]$' % (self.columns[0],
- self.columns[-1]), key):
+ if not re.match('^[%s-%s][%d-%d]$' % (self.columns[0],
+ self.columns[-1],
+ self.rows[0],
+ self.rows[-1]), key):
raise InvalidKey()
if self.moves and self.moves[-1][1] == value:
raise NotYourTurn()
self.moves.append((key, value))
- return dict.__setitem__(self, key, value)
+ return dict.__setitem__(self, key, value)