Решение на Морски шах от Орлин Христов

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

Към профила на Орлин Христов

Резултати

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

Код

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
winning_combinations = (('A1', 'A2', 'A3'),
('B1', 'B2', 'B3'),
('C1', 'C2', 'C3'),
('A1', 'B1', 'C1'),
('A2', 'B2', 'C2'),
('A3', 'B3', 'C3'),
('A1', 'B2', 'C3'),
('A3', 'B2', 'C1'))
rank = 3
players = ('X', 'O')
empty = ' '
board_representation = '''
-------------
3 | {A3} | {B3} | {C3} |
-------------
2 | {A2} | {B2} | {C2} |
-------------
1 | {A1} | {B1} | {C1} |
-------------
A B C
'''
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.board = {''.join(coordinates): self.empty
for coordinates in product(*self.dimensions)}
self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
return
elif index not in board:
raise InvalidKey()
elif board[index] != self.empty:
raise InvalidMove()
elif item not in self.players:
raise InvalidValue()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
return self.board_representation.format(**self.board)
def game_status(self, players=None):
for player in players if players is not None else self.players:
if self._winner_is(player):
return '{} wins!'.format(player)
empty = self.empty
return 'Game in progress.' if empty in self.board.values() else 'Draw!'
def _winner_is(self, player):
positions = tuple([position for position, owner in self.board.items()
if owner == player])
return any(all(position in positions for position in winning_fields)
for winning_fields in self.winning_combinations)

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

........
----------------------------------------------------------------------
Ran 8 tests in 0.084s

OK

История (6 версии и 7 коментара)

Орлин обнови решението на 08.04.2013 18:36 (преди около 11 години)

+from itertools import product
+
+
+class InvalidMove(Exception):
+ pass
+
+
+class InvalidValue(Exception):
+ pass
+
+
+class InvalidKey(Exception):
+ pass
+
+
+class NotYourTurn(Exception):
+ pass
+
+
+class GameIsOver(Exception):
+ pass
+
+
+class TicTacToeBoard(object):
+ def __init__(self):
+ self.board = {''.join(coordinates): ' ' for coordinates in
+ product(('A', 'B', 'C'), ('1', '2', '3'))}
+ self.last_player = ' '
+ self.game_is_on = True
+
+ def __getitem__(self, index):
+ return self.board[index]
+
+ def __setitem__(self, index, item):
+ board = self.board
+
+ if not self.game_is_on:
+ raise GameIsOver()
+ elif board[index] != ' ':
+ raise InvalidMove()
+ elif item not in ('X', 'O'):
+ raise InvalidValue()
+ elif index not in board:
+ raise InvalidKey()
+ elif self.last_player == item:
+ raise NotYourTurn()
+ board[index] = item
+ self.last_player = item
+ if self.game_status((item,)) != 'Game in progress.':
+ self.game_is_on = False
+
+ def __str__(self):
+ return '''\
+ -------------
+3 | {A3} | {B3} | {C3} |
+ -------------
+2 | {A2} | {B2} | {C2} |
+ -------------
+1 | {A1} | {B1} | {C1} |
+ -------------
+ A B C'''.format(**self.board)
+
+ def game_status(self, players=('X', 'O')):
+ for player in players:
+ if self._is_winner(player):
+ return '{} wins!'.format(player)
+ return 'Game in progress.' if ' ' in self.board.values() else 'Draw!'
+
+
+ def _is_winner(self, player):
+ positions = ''.join([position for position, owner in self.board.items()
+ if owner == player])
+ streight_win = 3 == max(positions.count(coordinate)
+ for coordinate in 'ABC123')
+
+ diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
+ diagonal_win = any(all(position in positions for position in diagonal)
+ for diagonal in diagonals)
+ return streight_win or diagonal_win

Орлин обнови решението на 09.04.2013 16:31 (преди около 11 години)

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
+ dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
+ diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
+ rank = 3
+ players = ('X', 'O')
+ empty = ' '
+ board_representation = '''
+ -------------
+3 | {A3} | {B3} | {C3} |
+ -------------
+2 | {A2} | {B2} | {C2} |
+ -------------
+1 | {A1} | {B1} | {C1} |
+ -------------
+ A B C
+'''
+
def __init__(self):
- self.board = {''.join(coordinates): ' ' for coordinates in
- product(('A', 'B', 'C'), ('1', '2', '3'))}
- self.last_player = ' '
+ self.board = {''.join(coordinates): self.empty
+ for coordinates in product(*self.dimensions)}
+ self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
raise GameIsOver()
- elif board[index] != ' ':
+ elif board[index] != self.empty:
raise InvalidMove()
- elif item not in ('X', 'O'):
+ elif item not in self.players:
raise InvalidValue()
elif index not in board:
raise InvalidKey()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
- return '''\
- -------------
-3 | {A3} | {B3} | {C3} |
- -------------
-2 | {A2} | {B2} | {C2} |
- -------------
-1 | {A1} | {B1} | {C1} |
- -------------
- A B C'''.format(**self.board)
+ return self.board_representation.format(**self.board)
- def game_status(self, players=('X', 'O')):
- for player in players:
+ def game_status(self, players=None):
+ for player in players if players is not None else self.players:
if self._is_winner(player):
return '{} wins!'.format(player)
- return 'Game in progress.' if ' ' in self.board.values() else 'Draw!'
+ empty = self.empty
+ return 'Game in progress.' if empty in self.board.values() else 'Draw!'
def _is_winner(self, player):
positions = ''.join([position for position, owner in self.board.items()
if owner == player])
- streight_win = 3 == max(positions.count(coordinate)
- for coordinate in 'ABC123')
- diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
+ dimensions = self.dimensions
+ max_dimensional_presence = max(positions.count(coordinate)
+ for coordinate in sum(dimensions, ()))
+ mono_dimensional_win = self.rank == max_dimensional_presence
+
diagonal_win = any(all(position in positions for position in diagonal)
- for diagonal in diagonals)
- return streight_win or diagonal_win
+ for diagonal in self.diagonals)
+
+ return mono_dimensional_win or diagonal_win

Орлин обнови решението на 09.04.2013 16:36 (преди около 11 години)

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
rank = 3
players = ('X', 'O')
empty = ' '
board_representation = '''
-------------
3 | {A3} | {B3} | {C3} |
-------------
2 | {A2} | {B2} | {C2} |
-------------
1 | {A1} | {B1} | {C1} |
-------------
A B C
'''
- def __init__(self):
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
self.board = {''.join(coordinates): self.empty
for coordinates in product(*self.dimensions)}
self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
raise GameIsOver()
elif board[index] != self.empty:
raise InvalidMove()
elif item not in self.players:
raise InvalidValue()
elif index not in board:
raise InvalidKey()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
return self.board_representation.format(**self.board)
def game_status(self, players=None):
for player in players if players is not None else self.players:
if self._is_winner(player):
return '{} wins!'.format(player)
empty = self.empty
return 'Game in progress.' if empty in self.board.values() else 'Draw!'
def _is_winner(self, player):
positions = ''.join([position for position, owner in self.board.items()
if owner == player])
dimensions = self.dimensions
max_dimensional_presence = max(positions.count(coordinate)
for coordinate in sum(dimensions, ()))
mono_dimensional_win = self.rank == max_dimensional_presence
diagonal_win = any(all(position in positions for position in diagonal)
for diagonal in self.diagonals)
return mono_dimensional_win or diagonal_win

Може малко да съм прекалил, но сега човек с малко желание може да модифицира презентацията на дъската, имената на играчите, символа за незаето поле и дори измеренията и размерността на играта без да има нужда от друг клас и това да не чупи стандартната игра.

Орлин обнови решението на 09.04.2013 16:52 (преди около 11 години)

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
rank = 3
players = ('X', 'O')
empty = ' '
board_representation = '''
-------------
3 | {A3} | {B3} | {C3} |
-------------
2 | {A2} | {B2} | {C2} |
-------------
1 | {A1} | {B1} | {C1} |
-------------
A B C
'''
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.board = {''.join(coordinates): self.empty
for coordinates in product(*self.dimensions)}
self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
raise GameIsOver()
elif board[index] != self.empty:
raise InvalidMove()
elif item not in self.players:
raise InvalidValue()
elif index not in board:
raise InvalidKey()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
return self.board_representation.format(**self.board)
def game_status(self, players=None):
for player in players if players is not None else self.players:
if self._is_winner(player):
return '{} wins!'.format(player)
empty = self.empty
return 'Game in progress.' if empty in self.board.values() else 'Draw!'
def _is_winner(self, player):
- positions = ''.join([position for position, owner in self.board.items()
- if owner == player])
+ positions = tuple([position for position, owner in self.board.items()
+ if owner == player])
dimensions = self.dimensions
max_dimensional_presence = max(positions.count(coordinate)
for coordinate in sum(dimensions, ()))
mono_dimensional_win = self.rank == max_dimensional_presence
diagonal_win = any(all(position in positions for position in diagonal)
for diagonal in self.diagonals)
return mono_dimensional_win or diagonal_win

Орлин обнови решението на 15.04.2013 16:54 (преди около 11 години)

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
- diagonals = (('A1', 'B2', 'C3'), ('A3', 'B2', 'C1'))
+ winning_combinations = (('A1', 'A2', 'A3'),
+ ('B1', 'B2', 'B3'),
+ ('C1', 'C2', 'C3'),
+ ('A1', 'B1', 'C1'),
+ ('A2', 'B2', 'C2'),
+ ('A3', 'B3', 'C3'),
+ ('A1', 'B2', 'C3'),
+ ('A3', 'B2', 'C1'))
rank = 3
players = ('X', 'O')
empty = ' '
board_representation = '''
-------------
3 | {A3} | {B3} | {C3} |
-------------
2 | {A2} | {B2} | {C2} |
-------------
1 | {A1} | {B1} | {C1} |
-------------
A B C
'''
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.board = {''.join(coordinates): self.empty
for coordinates in product(*self.dimensions)}
self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
- raise GameIsOver()
+ return
+ elif index not in board:
+ raise InvalidKey()
elif board[index] != self.empty:
raise InvalidMove()
elif item not in self.players:
raise InvalidValue()
- elif index not in board:
- raise InvalidKey()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
return self.board_representation.format(**self.board)
def game_status(self, players=None):
for player in players if players is not None else self.players:
if self._is_winner(player):
return '{} wins!'.format(player)
empty = self.empty
return 'Game in progress.' if empty in self.board.values() else 'Draw!'
-
-
+
def _is_winner(self, player):
positions = tuple([position for position, owner in self.board.items()
if owner == player])
- dimensions = self.dimensions
- max_dimensional_presence = max(positions.count(coordinate)
+ return any(all(position in positions for position in winning_fields)
- for coordinate in sum(dimensions, ()))
+ for winning_fields in self.winning_combinations)
- mono_dimensional_win = self.rank == max_dimensional_presence
-
- diagonal_win = any(all(position in positions for position in diagonal)
- for diagonal in self.diagonals)
-
- return mono_dimensional_win or diagonal_win

Орлин обнови решението на 15.04.2013 16:58 (преди около 11 години)

from itertools import product
class InvalidMove(Exception):
pass
class InvalidValue(Exception):
pass
class InvalidKey(Exception):
pass
class NotYourTurn(Exception):
pass
class GameIsOver(Exception):
pass
class TicTacToeBoard(object):
dimensions = (('A', 'B', 'C'), ('1', '2', '3'))
winning_combinations = (('A1', 'A2', 'A3'),
('B1', 'B2', 'B3'),
('C1', 'C2', 'C3'),
('A1', 'B1', 'C1'),
('A2', 'B2', 'C2'),
('A3', 'B3', 'C3'),
('A1', 'B2', 'C3'),
('A3', 'B2', 'C1'))
rank = 3
players = ('X', 'O')
empty = ' '
board_representation = '''
-------------
3 | {A3} | {B3} | {C3} |
-------------
2 | {A2} | {B2} | {C2} |
-------------
1 | {A1} | {B1} | {C1} |
-------------
A B C
'''
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.board = {''.join(coordinates): self.empty
for coordinates in product(*self.dimensions)}
self.last_player = self.empty
self.game_is_on = True
def __getitem__(self, index):
return self.board[index]
def __setitem__(self, index, item):
board = self.board
if not self.game_is_on:
return
elif index not in board:
raise InvalidKey()
elif board[index] != self.empty:
raise InvalidMove()
elif item not in self.players:
raise InvalidValue()
elif self.last_player == item:
raise NotYourTurn()
board[index] = item
self.last_player = item
if self.game_status((item,)) != 'Game in progress.':
self.game_is_on = False
def __str__(self):
return self.board_representation.format(**self.board)
def game_status(self, players=None):
for player in players if players is not None else self.players:
- if self._is_winner(player):
+ if self._winner_is(player):
return '{} wins!'.format(player)
empty = self.empty
return 'Game in progress.' if empty in self.board.values() else 'Draw!'
- def _is_winner(self, player):
+ def _winner_is(self, player):
positions = tuple([position for position, owner in self.board.items()
if owner == player])
return any(all(position in positions for position in winning_fields)
for winning_fields in self.winning_combinations)

Искаше ми се да може да изчислява по подадени списък от n измерения(представени като списъци, всеки от които с еднаква дължина) да може да изчислява всички n-мерни диагонали и рекурсивно всички n-1-мерни(с фиксирано кое да е от n-те измерения) и по-малки такива, което, ако не греша, би трябвало да са всички победни n-торки полета в хиперкубичен морски шах...

Но и това ще се наложи да се приеме за читаво подобно решение :D