> 5.6_01 WIP checkpoint
This commit is contained in:
parent
48f083afaf
commit
8c5cd8e3e9
@ -36,9 +36,9 @@ length - длина корабля (число палуб: целое значе
|
|||||||
tp - ориентация корабля (1 - горизонтальная; 2 - вертикальная).
|
tp - ориентация корабля (1 - горизонтальная; 2 - вертикальная).
|
||||||
|
|
||||||
Объекты класса Ship должны создаваться командами:
|
Объекты класса Ship должны создаваться командами:
|
||||||
ship = Ship(length)
|
>>> ship = Ship(length := 1)
|
||||||
ship = Ship(length, tp)
|
>>> ship = Ship(length := 1, tp := 2)
|
||||||
ship = Ship(length, tp, x, y)
|
>>> ship = Ship(length := 1, tp := 2, x := 1, y := 1)
|
||||||
|
|
||||||
По умолчанию (если не указывается) параметр tp = 1, а координаты x, y равны None.
|
По умолчанию (если не указывается) параметр tp = 1, а координаты x, y равны None.
|
||||||
|
|
||||||
@ -49,6 +49,52 @@ _tp - ориентация корабля;
|
|||||||
_is_move - возможно ли перемещение корабля (изначально равно True);
|
_is_move - возможно ли перемещение корабля (изначально равно True);
|
||||||
_cells - изначально список длиной length, состоящий из единиц (например, при length=3, _cells = [1, 1, 1]).
|
_cells - изначально список длиной length, состоящий из единиц (например, при length=3, _cells = [1, 1, 1]).
|
||||||
|
|
||||||
|
# доп проверки кораблей ---
|
||||||
|
>>> [*map(len, (Ship(1),Ship(2),Ship(3),Ship(4)))] == [*range(1, 5)]
|
||||||
|
True
|
||||||
|
>>> Ship(5)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: 5 is not a valid Ship.ShipSize
|
||||||
|
>>> Ship(1, 1)._tp, Ship(1, 2)._tp
|
||||||
|
(1, 2)
|
||||||
|
>>> Ship(1, 3)._tp
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: 3 is not a valid Ship.ShipOrientation
|
||||||
|
>>> s = Ship(1)
|
||||||
|
>>> {s[0] == 1, len(s) == 1}
|
||||||
|
{True}
|
||||||
|
>>> s[0] = 2
|
||||||
|
>>> s[0]
|
||||||
|
2
|
||||||
|
>>> s[0] = 4
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: 4 is not a valid Ship.DeckStatus
|
||||||
|
>>> s2 = Ship(2)
|
||||||
|
>>> s2._cells = [1, 2]
|
||||||
|
>>> s2._cells
|
||||||
|
[1, 2]
|
||||||
|
>>> s._cells = [1, 2]
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: _cells_ must be 1 elements long
|
||||||
|
>>> s[0] = 1
|
||||||
|
>>> s._is_move
|
||||||
|
True
|
||||||
|
>>> s[0] = 2
|
||||||
|
>>> s._is_move
|
||||||
|
False
|
||||||
|
>>> s.get_start_coords()
|
||||||
|
(None, None)
|
||||||
|
>>> s.set_start_coords(2, 3)
|
||||||
|
>>> s.get_start_coords()
|
||||||
|
(2, 3)
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
|
|
||||||
Список _cells будет сигнализировать о попадании соперником в какую-либо палубу корабля. Если стоит 1, то попадания не было, а если стоит значение 2, то произошло попадание в соответствующую палубу.
|
Список _cells будет сигнализировать о попадании соперником в какую-либо палубу корабля. Если стоит 1, то попадания не было, а если стоит значение 2, то произошло попадание в соответствующую палубу.
|
||||||
|
|
||||||
При попадании в корабль (хотя бы одну его палубу), флаг _is_move устанавливается в False и перемещение корабля по игровому полю прекращается.
|
При попадании в корабль (хотя бы одну его палубу), флаг _is_move устанавливается в False и перемещение корабля по игровому полю прекращается.
|
||||||
@ -66,7 +112,9 @@ ship[indx] = value # запись нового значения в коллек
|
|||||||
Класс GamePole
|
Класс GamePole
|
||||||
Следующий класс GamePole должен обеспечивать работу с игровым полем. Объекты этого класса создаются командой:
|
Следующий класс GamePole должен обеспечивать работу с игровым полем. Объекты этого класса создаются командой:
|
||||||
|
|
||||||
pole = GamePole(size)
|
>>> pole = GamePole(10)
|
||||||
|
>>> pole = GamePole()
|
||||||
|
|
||||||
где size - размеры игрового поля (обычно, size = 10).
|
где size - размеры игрового поля (обычно, size = 10).
|
||||||
|
|
||||||
В каждом объекте этого класса должны формироваться локальные атрибуты:
|
В каждом объекте этого класса должны формироваться локальные атрибуты:
|
||||||
@ -119,6 +167,121 @@ P.S. Для самых преданных поклонников програм
|
|||||||
Сыграйте в эту игру и выиграйте у компьютера.
|
Сыграйте в эту игру и выиграйте у компьютера.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
from enum import Enum
|
||||||
|
from functools import total_ordering
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
|
class EnumOrdering(Enum):
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, self.__class__):
|
||||||
|
return self.value == other.value
|
||||||
|
return self.value == other
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if isinstance(other, self.__class__):
|
||||||
|
return self.value < other.value
|
||||||
|
return self.value < other
|
||||||
|
|
||||||
|
class IntEnumField:
|
||||||
|
def __init__(self, enum_cls: Enum):
|
||||||
|
self.enum_cls = enum_cls
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
self.name_orig = name
|
||||||
|
self.name = name + "_"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name_orig
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
if instance is None:
|
||||||
|
return self
|
||||||
|
return getattr(instance, self.name).value
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
setattr(instance, self.name, self.enum_cls(value))
|
||||||
|
|
||||||
|
|
||||||
|
class ListEnumField:
|
||||||
|
def __init__(self, enum_cls: Enum, length_key):
|
||||||
|
self.enum_cls = enum_cls
|
||||||
|
self.length_key = length_key
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
self.name = name + "_"
|
||||||
|
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
if instance is None:
|
||||||
|
return self
|
||||||
|
return [x.value for x in getattr(instance, self.name)]
|
||||||
|
|
||||||
|
def get_item(self, instance, index):
|
||||||
|
return getattr(instance, self.name)[index]
|
||||||
|
|
||||||
|
def set_item(self, instance, index, value):
|
||||||
|
getattr(instance, self.name)[index] = self.enum_cls(value)
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
length = getattr(instance, str(self.length_key))
|
||||||
|
new_value = list(map(self.enum_cls, value))
|
||||||
|
if len(new_value) != length:
|
||||||
|
raise ValueError(f"{self.name} must be {length} elements long")
|
||||||
|
setattr(instance, self.name, new_value)
|
||||||
|
|
||||||
|
class Ship:
|
||||||
|
class ShipSize(EnumOrdering):
|
||||||
|
ONE_DECK = 1
|
||||||
|
TWO_DECKS = 2
|
||||||
|
THREE_DECKS = 3
|
||||||
|
FOUR_DECKS = 4
|
||||||
|
|
||||||
|
class ShipOrientation(EnumOrdering):
|
||||||
|
HORIZONTAL = 1
|
||||||
|
VERTICAL = 2
|
||||||
|
|
||||||
|
class DeckStatus(EnumOrdering):
|
||||||
|
OK = 1
|
||||||
|
DAMAGED = 2
|
||||||
|
|
||||||
|
pole_size: int = 10
|
||||||
|
|
||||||
|
_length = IntEnumField(ShipSize)
|
||||||
|
_tp = IntEnumField(ShipOrientation)
|
||||||
|
_cells = ListEnumField(DeckStatus, _length)
|
||||||
|
|
||||||
|
def __init__(self, length: int, tp: int = 1, x: Optional[int] = None, y: Optional[int] = None, cells: Optional[list[DeckStatus]] = None):
|
||||||
|
self._length, self._tp, self._x, self._y = length, tp, x, y
|
||||||
|
self._cells = cells or [self.DeckStatus.OK] * self._length
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"{self.__class__.__name__}{(self._length, self._tp, self._x, self._y, self._cells)!r}"
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self._length
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.__class__._cells.get_item(self, key).value
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
return self.__class__._cells.set_item(self, key, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _is_move(self) -> bool:
|
||||||
|
return all(cell == self.DeckStatus.OK for cell in self)
|
||||||
|
|
||||||
|
def set_start_coords(self, x: int, y: int):
|
||||||
|
self._x, self._y = x, y
|
||||||
|
|
||||||
|
def get_start_coords(self):
|
||||||
|
return self._x, self._y
|
||||||
|
|
||||||
|
|
||||||
|
class GamePole:
|
||||||
|
def __init__(self, size: int = 10):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def tests():
|
def tests():
|
||||||
code = (
|
code = (
|
||||||
@ -169,4 +332,7 @@ if __name__ == "__main__":
|
|||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
##############################################################################################################################
|
||||||
|
exit(0)
|
||||||
|
##############################################################################################################################
|
||||||
tests()
|
tests()
|
||||||
|
Loading…
Reference in New Issue
Block a user