diff --git a/mod_oop/5.6_01_sea_battle.py b/mod_oop/5.6_01_sea_battle.py index ede99e1..b6bede3 100644 --- a/mod_oop/5.6_01_sea_battle.py +++ b/mod_oop/5.6_01_sea_battle.py @@ -114,6 +114,57 @@ False True >>> Ship(3, 2, 1, 8).is_out_pole(10) True +>>> s = Ship(4, 2) +>>> s.try_move(1, 6, [Ship(1, 1, 3, 1)]) +True +>>> s.get_start_coords() +(0, 1) +>>> s.try_move(1, 6, [Ship(1, 1, 3, 1)]) +False +>>> s.get_start_coords() +(0, 1) +>>> s.try_move(1, 6, [Ship(1, 1, 2, 1)]) +False +>>> s.get_start_coords() +(0, 1) +>>> s[0] = 2 +>>> s.try_move(1, 10, [Ship(1, 1, 3, 1)]) +False +>>> s.get_start_coords() +(0, 1) +>>> s[0] = 1; s.computer_move(10, [Ship(1, 1, 3, 1)]) +>>> _, y = s.get_start_coords(); 0 <= y <= 2 +True + +>>> s = Ship(4, 2) +>>> s.hit(1, 1) +False +>>> s._is_move +True +>>> s.hit(0, 4) +False +>>> s._is_move +True +>>> s.hit(0, 3) +True +>>> s._is_move +False +>>> s.is_alive +True +>>> {s.hit(0, x) for x in range(3)} ; s.is_alive +{True} +False + +>>> sz = 5; pole = [[0 for _ in range(sz)] for _ in range(sz)] +>>> s1, s2 = Ship(2, 1), Ship(2, 2, 3, 1) +>>> s1.place_to_pole(pole) +True +>>> pole +[[1, 1, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] +>>> s2.place_to_pole(pole) +True +>>> pole +[[1, 1, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] # --- @@ -195,6 +246,7 @@ from typing import List, Optional from enum import Enum from functools import total_ordering from collections import namedtuple +import random @total_ordering @@ -325,7 +377,7 @@ class Ship: @property def _is_move(self) -> bool: return all(cell == self.DeckStatus.OK for cell in self) - + @property def is_alive(self) -> bool: return any(cell == self.DeckStatus.OK for cell in self) @@ -336,9 +388,13 @@ class Ship: def get_start_coords(self): return self._x, self._y + @property + def is_horizontal(self): + return self._tp == self.ShipOrientation.HORIZONTAL + def move(self, go: int): if self._is_move: - if self._tp == self.ShipOrientation.HORIZONTAL: + if self.is_horizontal: self._x += go else: self._y += go @@ -346,7 +402,7 @@ class Ship: @property def rect(self): x, y = self.get_start_coords() - if self._tp == self.ShipOrientation.HORIZONTAL: + if self.is_horizontal: return self.Rect(x, y, x + self._length, y + 1) else: return self.Rect(x, y, x + 1, y + self._length) @@ -358,7 +414,7 @@ class Ship: and self.rect.top <= other.rect.bottom and self.rect.bottom >= other.rect.top or any( - abs(getattr(a.rect, x) - getattr(b.rect, y)) == 0 + not (getattr(a.rect, x) - getattr(b.rect, y)) for a, b in ((self, other), (other, self)) for x, y in (("left", "right"), ("top", "bottom")) ) @@ -372,6 +428,40 @@ class Ship: or self.rect.bottom > size ) + def try_move(self, go: int, pole_size: int, other_ships: List["Ship"]) -> bool: + if not self._is_move: + return False + backup = self.get_start_coords() + self.move(go) + if not ( + self.is_out_pole(pole_size) + or any(self.is_collide(ship) for ship in other_ships) + ): + return True + self.set_start_coords(*backup) + return False + + def computer_move(self, pole_size: int, other_ships: List["Ship"]): + self.try_move(random.randint(-1, 1), pole_size, other_ships) + + def hit(self, x: int, y: int) -> bool: + left, top, right, bottom = self.rect + if left <= x < right and top <= y < bottom: + a, b = ((y, top), (x, left))[self.is_horizontal] + self[a - b] = self.DeckStatus.DAMAGED + return True + return False + + def place_to_pole(self, pole: List[List[int]]) -> bool: + if self.is_out_pole(len(pole)): + return False + rect = self.rect + for i in range(rect.top, rect.bottom): + for j in range(rect.left, rect.right): + a, b = ((i, rect.top), (j, rect.left))[self.is_horizontal] + pole[i][j] = self[a - b] + return True + class GamePole: def __init__(self, size: int = 10):