Skip to content

Commit

Permalink
'Solution_v1.00'
Browse files Browse the repository at this point in the history
  • Loading branch information
DmytroPieskov committed Dec 7, 2024
1 parent a91a4c5 commit b1a6822
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ ignore = E203, E266, W503, ANN002, ANN003, ANN101, ANN102, ANN401, N807, N818
max-line-length = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9,ANN,Q0,N8,VNE
exclude = venv, tests
exclude = venv, tests, mainishe.py
116 changes: 104 additions & 12 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,126 @@
from typing import List


class Deck:
def __init__(self, row, column, is_alive=True):
pass
def __init__(self, row: int, column: int, is_alive: bool = True) -> None:
self.row = row
self.column = column
self.is_alive = is_alive

def fire(self) -> bool:
self.is_alive = False
return self.is_alive

def __repr__(self) -> str:
return "□" if self.is_alive else "x"


class Ship:
def __init__(self, start, end, is_drowned=False):
def __init__(self,
start: tuple,
end: tuple,
is_drowned: bool = False
) -> None:
# Create decks and save them to a list `self.decks`
pass
self.is_drowned = is_drowned
self.decks = self.create_decks(start, end)

@staticmethod
def create_decks(start: tuple, end: tuple) -> List[Deck]:
decks = []
if start[0] == end[0]: # Horizontal ship
for col in range(start[1], end[1] + 1):
decks.append(Deck(start[0], col))
elif start[1] == end[1]: # Vertical ship
for row in range(start[0], end[0] + 1):
decks.append(Deck(row, start[1]))
return decks

def get_deck(self, row, column):
@staticmethod
def get_deck(row: int, column: int) -> Deck:
# Find the corresponding deck in the list
pass
return Deck(row, column)

def fire(self, row, column):
def fire(self, row: int, column: int) -> str:
# Change the `is_alive` status of the deck
# And update the `is_drowned` value if it's needed
pass
for deck in self.decks:
if deck.row == row and deck.column == column:
deck.fire()
if all(not deck.is_alive for deck in self.decks):
self.is_drowned = True
return "Sunk!"
return "Hit!"
return "Miss!"

def __repr__(self) -> str:
return "".join(str(deck) for deck in self.decks)


class Battleship:
def __init__(self, ships):
def __init__(self, ships: list[Ship]) -> None:
# Create a dict `self.field`.
# Its keys are tuples - the coordinates of the non-empty cells,
# A value for each cell is a reference to the ship
# which is located in it
pass
self.field = [["~" for _ in range(10)] for _ in range(10)]
self.ships = [Ship(start, end) for start, end in ships]
self.place_ships()
self._validate_field()

def place_ships(self) -> None:
for ship in self.ships:
for deck in ship.decks:
row, col = deck.row, deck.column
self.field[row][col] = "□"

def fire(self, location: tuple):
def fire(self, location: tuple) -> str:
# This function should check whether the location
# is a key in the `self.field`
# If it is, then it should check if this cell is the last alive
# in the ship or not.
pass
row, col = location
for ship in self.ships:
result = ship.fire(*location)
if result != "Miss!":
self.field[row][col] = "*" if result == "Hit!" else "x"
return result
self.field[row][col] = "o"
return "Miss!"

def print_field(self) -> None:
for row in self.field:
print(" ".join(row))

def _validate_field(self) -> None:
ship_lengths = [len(ship.decks) for ship in self.ships]
if len(self.ships) != 10:
raise ValueError("There should be exactly 10 ships.")
if ship_lengths.count(1) != 4:
raise ValueError("There should be exactly 4 single-deck ships.")
if ship_lengths.count(2) != 3:
raise ValueError("There should be exactly 3 double-deck ships.")
if ship_lengths.count(3) != 2:
raise ValueError("There should be exactly 2 three-deck ships.")
if ship_lengths.count(4) != 1:
raise ValueError("There should be exactly 1 four-deck ship.")
if not self._check_no_neighbors():
raise ValueError("Ships should not be located "
"in neighboring cells.")

def _check_no_neighbors(self) -> bool:
directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1),
(0, 1), (1, -1), (1, 0), (1, 1)
]
for ship in self.ships:
for deck in ship.decks:
row, col = deck.row, deck.column
for dr, dc in directions:
nr, nc = row + dr, col + dc
if (0 <= nr < 10
and 0 <= nc < 10
and self.field[nr][nc] == "□"
and (nr, nc)
not in [(d.row, d.column) for d in ship.decks]):
return False
return True

0 comments on commit b1a6822

Please sign in to comment.