Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 53 additions & 25 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,62 @@
from typing import List, Tuple, Optional, Dict


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


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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This violates CheckList item #4: "Remove unused attributes. Check that all the attributes you define in the __init__ method are used." You assign self.start here but that attribute is never used elsewhere; either use it (e.g., for validation/representation) or remove it.

self.end = end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This violates CheckList item #4: "Remove unused attributes. Check that all the attributes you define in the __init__ method are used." You assign self.end here but that attribute is never used elsewhere; either use it (e.g., for validation/representation) or remove it.

self.is_drowned = is_drowned
self.decks: List[Deck] = []

row_start, row_end = min(start[0], end[0]), max(start[0], end[0])
col_start, col_end = min(start[1], end[1]), max(start[1], end[1])

def get_deck(self, row, column):
# Find the corresponding deck in the list
pass
for r in range(row_start, row_end + 1):
for c in range(col_start, col_end + 1):
self.decks.append(Deck(r, c))

def fire(self, row, column):
# Change the `is_alive` status of the deck
# And update the `is_drowned` value if it's needed
pass
def get_deck(self, row: int, column: int) -> Optional[Deck]:
for deck in self.decks:
if deck.row == row and deck.column == column:
return deck
return None

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This violates checklist item #2: "Don't use a redundant return statement if it doesn't do anything." The final return None in Ship.get_deck is redundant — remove it and let the function implicitly return None when no deck is found.


def fire(self, row: int, column: int) -> None:
target_deck = self.get_deck(row, column)
if target_deck is not None:
target_deck.is_alive = False
self.is_drowned = all(not deck.is_alive for deck in self.decks)


class Battleship:
def __init__(self, ships):
# 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

def fire(self, location: tuple):
# 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
def __init__(self, ships: List[Tuple[Tuple[int, int], Tuple[int, int]]]) -> None:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task requires a protected _validate_field method that should be called after creating the field in __init__. I don't see _validate_field implemented or invoked — please implement _validate_field and call it at the end of Battleship.init to enforce the required checks (total ships, counts by size, and no neighboring ships) as described in the task.

self.field: Dict[Tuple[int, int], Ship] = {}

for start, end in ships:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before inserting ship decks into self.field, validate input coordinates are within the 10x10 bounds (rows and columns must be in 0..9). The description defines the field as a 10x10 matrix; add range checks and raise an error for out-of-range coordinates.

new_ship = Ship(start, end)
for deck in new_ship.decks:
self.field[(deck.row, deck.column)] = new_ship

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When assigning self.field[(deck.row, deck.column)] = new_ship you should check for existing entries at that coordinate. If a deck coordinate is already present, the input describes overlapping ships which should be considered invalid — detect and raise an error (this also helps when implementing _validate_field).


def fire(self, location: Tuple[int, int]) -> str:
if location not in self.field:
return "Miss!"

ship = self.field[location]
ship.fire(location[0], location[1])

if ship.is_drowned:
return "Sunk!"

return "Hit!"
Loading