Vývoj knihovny logiky hry Lodě v Pythonu: architektura a typické chyby
Knihovna implementuje logiku klasické hry Lodě s důrazem na matematicky optimální algoritmy. Hlavní třídy jsou Field pro reprezentaci herního pole a Ship pro správu lodí. Pole je uloženo jako matice 10x10 se seznamy seznamů, kde symboly označují stavy: mezera — prázdné políčko, '1' — živá část lodi, '.' — minutí, 'X' — zničené políčko.
Třída Field zodpovídá za vytvoření hrací desky, validaci souřadnic, umístění lodí a zpracování výstřelů. Souřadnice se zadávají ve formátu 'a1', kde písmena A-J odpovídají řádkům, čísla 1-10 — sloupcům. Pravidla jsou pevná: 1 loď 4-políčková, 2 třípolíčkové, 3 dvoupolíčkové, 4 jednopolíčkové; lodě se nedotýkají ani rohy.
Implementace třídy Field
Inicializace vytvoří prázdnou mřížku:
class Field:
def __init__(self):
height = 10
width = 10
self.grid = [[' ' for i in range(width)] for i in range(height)]
Metoda display() vypíše pole do konzole se souřadnicemi. První verze obsahovala chybu — metoda line.insert(0, letter) mutovala původní grid, přidávala písmena při opakovaných voláních. Oprava: tisk písmena zvlášť bez změny struktury.
def display(self):
print(' 1 2 3 4 5 6 7 8 9 10')
letters = 'ABCDEFGHIJ'
count_letters = 0
for line in self.grid:
print(letters[count_letters], *line)
count_letters += 1
Validace souřadnic je vyčleněna do privátní metody _validation_coordinate(). Kontroluje délku řetězce (2-3 znaky), přítomnost písmena v A-J a čísla v 1-10. Metoda find_coordinate() určuje stav políčka: clear, hitted, destroyed, not_damaged, was_beaten.
Slovníky pro převod souřadnic jsou uloženy jako atributy self.rows a self.columns:
- rows: {'a': 0, 'b': 1, ..., 'j': 9}
- columns: {'1': 0, '2': 1, ..., '10': 9}
Třída Ship a umístění lodí
Třída Ship ukládá parametry ve slovníku:
class Ship:
def __init__(self):
self.parameters = {
'alive coordinates': [],
'hitted coordinates': [],
'alive': True
}
self.field = None
def set_field(self, field):
self.field = field
Metoda add_ship(ship, coordinate_line, length) v Field umístí loď podle řetězce typu 'a1-a2-a3'. Nejprve validace linie _ship_line_validation(): rozklad na souřadnice, kontrola linearity (horizontální/vertikální), shoda délky. Poté pro každou souřadnici volání ship.set_coordinate_in_ship(coordinate), nastavení '1' v grid.
def add_ship(self, ship, coordinate_line, length):
ship.set_field(self)
if not self._ship_line_validation(coordinate_line):
return False
coordinates = coordinate_line.split('-')
if length != len(coordinates):
return False
for coordinate in coordinates:
result = ship.set_coordinate_in_ship(coordinate)
if result:
rows = self.rows[coordinate[0]]
columns = self.columns[coordinate[1:]]
self.grid[rows][columns] = '1'
return True
Vazba Field-Ship je obousměrná: Field volá ship.set_field(self), Ship používá self.field pro validaci. To porušuje princip zapouzdření základních vrstev, ale zjednodušuje API.
Závěry k refaktoringu
Projekt odhalil klíčové problémy začátečníků:
- Přetížení metod: find_coordinate() kombinoval validaci, hledání a výstup — rozdělit na _validation_coordinate() a get_cell_state().
- Mutace dat: Vyhnout se insert() v display(), pracovat s kopiemi.
- Pevně zakódované slovníky: Vyčlenit do třídních konstant nebo použít ord() pro převody.
- Návratové hodnoty: Sjednotit: True/False pro úspěch, řetězce pro chyby.
Pro optimální hru integrovat algoritmy pravděpodobnostního hledání: při zásahu skenovat sousední políčka, při zničení — vyloučit paluby z pravděpodobností.
Co je důležité
- Field jako matice seznamů se symboly pro stavy; validace souřadnic přes slovníky self.rows/self.columns.
- Ship ukládá alive/hitted coordinates; obousměrná vazba s Field přes set_field().
- Umístění podle coordinate_line ('a1-a2'); kontrola linearity a nárazníkových zón.
- Vyhnout se mutaci grid v display(); vyčleňovat společné kontroly do privátních metod.
- Pro pokročilé algoritmy: ukládat pravděpodobnostní mapu výstřelů odděleně od grid.
— Editorial Team
Zatím žádné komentáře.