From feb25bb48f80a121bd085e60960128471d2f3812 Mon Sep 17 00:00:00 2001 From: ehermakov Date: Sun, 21 Jul 2024 20:40:04 +0300 Subject: [PATCH] add kill check & kill marker --- .DS_Store | Bin 6148 -> 6148 bytes HNS/.DS_Store | Bin 6148 -> 6148 bytes HNS/Excercises/.DS_Store | Bin 8196 -> 8196 bytes HNS/Excercises/ShipCraft/.DS_Store | Bin 6148 -> 10244 bytes HNS/Excercises/ShipCraft/Переделка/Files.py | 60 +- .../ShipCraft/Переделка/GameMode.py | 32 +- .../ShipCraft/Переделка/ShipDirection.py | 30 +- .../ShipCraft/Переделка/ShipField.py | 711 ++++++++++-------- .../ShipCraft/Переделка/ShipMode.py | 34 +- .../ShipCraft/Переделка/ShipView.py | 24 +- .../ShipCraft/Переделка/ShootResult.py | 16 +- HNS/Excercises/ShipCraft/Переделка/Test.py | 156 ++-- .../__pycache__/GameMode.cpython-312.pyc | Bin 0 -> 883 bytes .../__pycache__/ShipDirection.cpython-312.pyc | Bin 0 -> 893 bytes .../__pycache__/ShipField.cpython-312.pyc | Bin 0 -> 18778 bytes .../__pycache__/ShipMode.cpython-312.pyc | Bin 0 -> 868 bytes .../__pycache__/ShipView.cpython-312.pyc | Bin 0 -> 789 bytes .../__pycache__/ShootResult.cpython-312.pyc | Bin 0 -> 529 bytes HNS/Excercises/ShipCraft/Переделка/main.py | 576 +++++++------- .../ShipCraft/Переделка/test_ShipField.py | 560 +++++++------- 20 files changed, 1125 insertions(+), 1074 deletions(-) create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/GameMode.cpython-312.pyc create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipDirection.cpython-312.pyc create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipField.cpython-312.pyc create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipMode.cpython-312.pyc create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipView.cpython-312.pyc create mode 100644 HNS/Excercises/ShipCraft/Переделка/__pycache__/ShootResult.cpython-312.pyc diff --git a/.DS_Store b/.DS_Store index 1b232ba1ce8684e55cc83bb24e559993172ccb65..a29a714ac10f1e1873e22cc77f60e36dc7d7e3cf 100644 GIT binary patch delta 14 VcmZoMXffDe%f@K3*^cd)AOIqe1YZCE delta 14 VcmZoMXffDe%f@K9*^cd)AOIqM1Y7_B diff --git a/HNS/.DS_Store b/HNS/.DS_Store index 3175dc3aeb0b3499e1be061384f99ab96257d42b..0ebef95ec74f308c6f0bd23e1a0f6dbe9d0c2e39 100644 GIT binary patch delta 14 VcmZoMXffCz%FJl8S&aFe2mm0u1T+8u delta 14 VcmZoMXffCz%FJlES&aFe2mm0c1Tg>r diff --git a/HNS/Excercises/.DS_Store b/HNS/Excercises/.DS_Store index 979d852e716a927af022a7ad7719aa6119bde246..892a14b1c254fe2d64eab7be83ac7e1b04aa6d16 100644 GIT binary patch delta 21 ZcmZp1XmQw}E5>NDSx@XgJD9r02mnlf2C)DD delta 21 ZcmZp1XmQw}E5>NJSx@XgJD9r02mnk*2CD!7 diff --git a/HNS/Excercises/ShipCraft/.DS_Store b/HNS/Excercises/ShipCraft/.DS_Store index 07bf8be3734be06c89af2324023ac31890cf6465..7cc5cb1642cf5d9e6df4a7d94380312cb9862df3 100644 GIT binary patch literal 10244 zcmeHMTWl0n7(V}Wp)(AZX>Ga5uq!K2p}h*kyf#*oT?TIscq< z{_mXqzy1E%J!c6a(4N!R6A~eWh*+pqW@A<1qT{sOaS49UEVO`lLQLY36u#Dy(L20@ zj(~xHfq;R4fq;R4f$6{ierMB5l(`M+fPsL4fPpCn=<^|hh1$4pC%I*h4y@P~0Bs1n z*@gGG4`7&xZ{xn5WGUl zcLH&4gF0X!VBk&$=-ypsdv=r9CHwcWF3ZWJEhmj0G^yIKto?^wcvnP?k};AY8kS*V z(0R&G=gLskWCXqGTJ(&dYz_Fc%zHLT;=Cq$K903PETUJ!2}jFtHKZ54T|AA5OwEuW zSzP%D_ElJ!MR(@5=%i3Mv@sON(u}1wv^f+jjSSSXH7g*}1$WeE@M3z@GF>kgy9z>8 zXvWNHv09YHgUMm1kn}V!=eBFv{j}BVI99rNuch~yMj@rtB^=w+OxwsZfTXr{hNXFC z-ssRg!%ZpkTnw};WuduOtaW$kuc(=#1= zaKJN8cyx?TR5CO$j-01lNmwuq9V_gPxnu>7vgt=P4rKhGofJL|WK(m=); z8Npy&-lrxyL{a(T5M8)ibG==ohCTI`65B*^$Q{L8t}P1g+_gI>IFQLUO(`$Xk3VieQPn<#kv47l#aXgv7|lUp>tipws_4Izx< zXgtQ-b;WMq(w__}iIH})ogAVM6LN~YOx`3PlJn#OxkSDuSIKqq6Zx6^LVhJT$zKqH zSx^T{U^%RW26zaXU;{Km3nZW$dSE9EK?Za%;3!y-gFF;q44#5#;8}PMPQgp?8oUmt z;S9V5=iohfA3lap;WM}dpTkx79Ce8n@iK|zPkGP3nI%` zt!sYdv9>8Oa_tu7dV3l$<(K3OQ$ABixoTNH%1gt2m>R~3TM5Y%w3wDkHBDjh3iWLT(5vGcj>^b9H!4SP?K^c{3Jnl9ejVMu}lJhS$gnh`g~$Zk3e~<|S`# zk(bH}k$9s$+!0o2mWlUD?_ZM3jF zdf_0X;4q|7@fO(Nz;VdJI8314C*f&03D3g|@FKhducGQt!yBmix8WUl7e0XVZ~-pD zM@;=+!8dRXek{{-PpO{ax5|3XC$qNY*!0W0mFc2^hFc2^hFmTrysNyq5 z==p!=fB*k~*Vhdu3>XL)m_7_Zs3Y0Yj_>EceudMs_6U~4Sm;IlCb?x0tk`ipT6P?d u4SF2kfQ9<{`*(I9_xmQfWpMOiaJ2k1|DOLD5bXc|pF_7`|37W^|NjC9f%)VB delta 168 zcmZn(XfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~50$jG@dU^g=(=Vl&($Bc}IlRpRs zO>URqH|1rKXE9}Q0Adp$wq~(nF<{VRC}K!tDDuq7Pfp6oPlA}l*bSuh{)55B!bZl$ r>>M0|%s??95a0$9t{}@c7Jg@*%&+1JvYLSj;tY_>7&gcA%wYxqDg7aj diff --git a/HNS/Excercises/ShipCraft/Переделка/Files.py b/HNS/Excercises/ShipCraft/Переделка/Files.py index 5a541a6..1f44ee6 100644 --- a/HNS/Excercises/ShipCraft/Переделка/Files.py +++ b/HNS/Excercises/ShipCraft/Переделка/Files.py @@ -1,30 +1,30 @@ -import os - - -def list_levels(): - files = os.listdir(path=".") - result = [] - for file in files: - if file.lower().endswith('.txt'): - result.append(file) - - return result - - -def load(file): - # 1 загрузить весь файл в строку - f = open(file, "r") - s = f.read() - - # 2 заменить все пробелы и переводы строки на ничего - s = s.replace(" ", "") - s = s.replace('\n', "") - - # 3 из полученной строки создать массив используя разделитель "," - a = s.split(",") - - # а - массив строк, в которых хранятся числа - b = [] - - f.close() - return a +import os + + +def list_levels(): + files = os.listdir(path=".") + result = [] + for file in files: + if file.lower().endswith('.txt'): + result.append(file) + + return result + + +def load(file): + # 1 загрузить весь файл в строку + f = open(file, "r") + s = f.read() + + # 2 заменить все пробелы и переводы строки на ничего + s = s.replace(" ", "") + s = s.replace('\n', "") + + # 3 из полученной строки создать массив используя разделитель "," + a = s.split(",") + + # а - массив строк, в которых хранятся числа + b = [] + + f.close() + return a diff --git a/HNS/Excercises/ShipCraft/Переделка/GameMode.py b/HNS/Excercises/ShipCraft/Переделка/GameMode.py index 8ae75d1..3b8ac6f 100644 --- a/HNS/Excercises/ShipCraft/Переделка/GameMode.py +++ b/HNS/Excercises/ShipCraft/Переделка/GameMode.py @@ -1,16 +1,16 @@ -from enum import Enum - - -class GameMode(Enum): - MENU = 'MENU' - PLAN = 'PLAN' - BATTLE = 'BATTLE' - END = 'END' - - @staticmethod - def from_string(raw_value): - if raw_value: - value = raw_value.upper() - if value in GameMode.__members__: - return GameMode[value] - return GameMode.MENU +from enum import Enum + + +class GameMode(Enum): + MENU = 'MENU' + PLAN = 'PLAN' + BATTLE = 'BATTLE' + END = 'END' + + @staticmethod + def from_string(raw_value): + if raw_value: + value = raw_value.upper() + if value in GameMode.__members__: + return GameMode[value] + return GameMode.MENU diff --git a/HNS/Excercises/ShipCraft/Переделка/ShipDirection.py b/HNS/Excercises/ShipCraft/Переделка/ShipDirection.py index c794076..78153f0 100644 --- a/HNS/Excercises/ShipCraft/Переделка/ShipDirection.py +++ b/HNS/Excercises/ShipCraft/Переделка/ShipDirection.py @@ -1,15 +1,15 @@ -from enum import Enum - - -class ShipDirection(Enum): - VERTICAL = 'VERTICAL' - HORIZONTAL = 'HORIZONTAL' - UNKNOWN = 'UNKNOWN' - - @staticmethod - def from_string(raw_value): - if raw_value: - value = raw_value.upper() - if value in ShipDirection.__members__: - return ShipDirection[value] - return ShipDirection.UNKNOWN +from enum import Enum + + +class ShipDirection(Enum): + VERTICAL = 'VERTICAL' + HORIZONTAL = 'HORIZONTAL' + UNKNOWN = 'UNKNOWN' + + @staticmethod + def from_string(raw_value): + if raw_value: + value = raw_value.upper() + if value in ShipDirection.__members__: + return ShipDirection[value] + return ShipDirection.UNKNOWN diff --git a/HNS/Excercises/ShipCraft/Переделка/ShipField.py b/HNS/Excercises/ShipCraft/Переделка/ShipField.py index e2a1486..c296e4f 100644 --- a/HNS/Excercises/ShipCraft/Переделка/ShipField.py +++ b/HNS/Excercises/ShipCraft/Переделка/ShipField.py @@ -1,331 +1,380 @@ -import copy - -from ShootResult import ShootResult -from ShipDirection import ShipDirection -from ShipMode import ShipMode - - -class ShipField: - field_size = 10 - - def __init__(self): - self.field = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] - - self.ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1] - self.field_mode = ShipMode.INACTIVE - self.ship_size = 4 - self.ship_direction = ShipDirection.VERTICAL - - def from_json(self, obj): - self.field = obj['field'] - self.ships = obj['ships'] - self.field_mode = ShipMode.from_string(obj['field_mode']) - self.ship_size = obj['ship_size'] - self.ship_direction = ShipDirection.from_string(obj['ship_direction']) - - def __getitem__(self, item): - if item is None: - return None - - if type(item) is not int and item.isnumeric(): - item = int(item) - - if type(item) is int and 0 <= item < len(self.field): - return self.field[item] - - return None - - def check_killed(self, row, col): - if row < 0 or row > ShipField.field_size: - return - if col < 0 or col > ShipField.field_size: - return - - ship_killed = True - ship_direction = ShipDirection.UNKNOWN - - #check vertical - for r in range(row + 1, ShipField.field_size): - if self.check_ship(r, col): - return False - - elif self.check_empty(r, col): - break - - for r in range(row - 1, -1, -1): - if self.check_ship(r, col): - return False - - elif self.check_empty(r, col): - break - - # проверим горизонталь - for c in range(col + 1, ShipField.field_size): - if self.check_ship(row, c): - ship_direction = ShipDirection.HORIZONTAL - else: - break - - for c in range(col + 1, ShipField.field_size): - if self.check_ship(row, c): - return False - - elif self.check_empty(row, c): - break - return True - - def fill_empty_killed(self, row, col): - pass - - def action(self, row, col): - self.clear_marker() - - if self.field_mode == ShipMode.PUT: - if self.check_ship(row, col): - self.get_ship(row, col) - - elif self.ship_size in self.ships and self.check_possible(row, col): - self.set_ship(row, col) - - elif self.field_mode == ShipMode.SHOOT: - shoot_result = self.shoot(row, col) - - if shoot_result == ShootResult.KILLED: - self.fill_empty_killed(row, col) - - return shoot_result == ShootResult.EMPTY - - return False - - def target(self, row, col): - self.clear_marker() - - if self.field_mode == ShipMode.PUT: - if self.check_possible(row, col): - if self.ship_direction == ShipDirection.VERTICAL: - for r in range(row, row + self.ship_size): - if self.ship_size in self.ships: - self.field[r * ShipField.field_size + col] = "p" - else: - self.field[r * ShipField.field_size + col] = "r" - - if self.ship_direction == ShipDirection.HORIZONTAL: - for c in range(col, col + self.ship_size): - if self.ship_size in self.ships: - self.field[row * ShipField.field_size + c] = "p" - else: - self.field[row * ShipField.field_size + c] = "r" - elif self.field_mode == ShipMode.SHOOT: - self.field[row * ShipField.field_size + col] += "+" - - def clear_marker(self): - for i in range(0, len(self.field)): - if self.field[i] == "p" or self.field[i] == "r": - self.field[i] = "" - - if "+" in self.field[i]: - self.field[i] = self.field[i].replace("+", "") - - def set_ship(self, row, col): - if row < 0 or row > ShipField.field_size: - return - if col < 0 or col > ShipField.field_size: - return - index = row * ShipField.field_size + col - if self.ship_direction == ShipDirection.VERTICAL: - if ShipField.field_size - row < self.ship_size: - return - for r in range(row, row + self.ship_size): - index = r * ShipField.field_size + col - self.field[index] = "1" - if self.ship_direction == ShipDirection.HORIZONTAL: - if ShipField.field_size - col < self.ship_size: - return - for c in range(col, col + self.ship_size): - index = row * ShipField.field_size + c - self.field[index] = "1" - - if self.ship_size in self.ships: - self.ships.remove(self.ship_size) - self.print_field() - - if self.ship_size not in self.ships and len(self.ships) > 0: - self.ship_size = max(self.ships) - - def get_ship(self, row, col): - if row < 0 or row > ShipField.field_size: - return - if col < 0 or col > ShipField.field_size: - return - - self.field[row * ShipField.field_size + col] = "" - - ship_size = 1 - ship_direction = ShipDirection.UNKNOWN - - # проверим вертикаль - for r in range(row + 1, ShipField.field_size): - if self.check_ship(r, col): - ship_size += 1 - ship_direction = ShipDirection.VERTICAL - self.field[r * ShipField.field_size + col] = "" - else: - break - - for r in range(row - 1, -1, -1): - if self.check_ship(r, col): - ship_size += 1 - ship_direction = ShipDirection.VERTICAL - self.field[row * ShipField.field_size + col] = "" - else: - break - - if ship_direction == ShipDirection.UNKNOWN: - - # проверим горизонталь - for c in range(col + 1, ShipField.field_size): - if self.check_ship(row, c): - ship_size += 1 - ship_direction = ShipDirection.HORIZONTAL - self.field[row * ShipField.field_size + c] = "" - else: - break - - for c in range(col - 1, -1, -1): - if self.check_ship(row, c): - ship_size += 1 - ship_direction = ShipDirection.HORIZONTAL - self.field[row * ShipField.field_size + c] = "" - else: - break - self.set_ship_direction(ship_direction) - self.set_ship_size(ship_size) - self.ships.append(ship_size) - - def shoot(self, row, col): - if row < 0 or row > ShipField.field_size - 1: - return ShootResult.UNDEFINED - if col < 0 or col > ShipField.field_size - 1: - return ShootResult.UNDEFINED - index = row * ShipField.field_size + col - if (self.field[index]).strip() == "": - self.field[index] = "0" - return ShootResult.EMPTY - elif (self.field[index]).strip() == "1": - self.field[index] = "\\" - if self.check_killed(row, col): - return ShootResult.KILLED - return ShootResult.DAMAGED - else: - return ShootResult.UNDEFINED - - def check_ship(self, row, col): - # функция должна возвражать тру, если в заданной клетке есть корабль - # в противном случае фолс - return self.field[row * ShipField.field_size + col].strip() == "1" - - def check_damaged(self, row, col): - return self.field[row * ShipField.field_size + col].strip() == "\\" - - def check_empty(self, row, col): - cell = self.field[row * ShipField.field_size + col].strip() - return cell == "0" or cell == "" - - def check_end(self): - return "1" not in self.field - - def check_possible(self, row, col): - # Функция должна возвращать True, если можно поставить сюда корабль, - # в противном случае - False - if self.ship_direction == ShipDirection.VERTICAL: - # Здесь мы знаем, что корабль помещается на поле. - if ShipField.field_size - row >= self.ship_size: - # Теперь нужно проверить, не заблокировано ли какое-то из полей, - for r in range(row, row + self.ship_size): - if not self.check_blocked(r, col): - return False - return True - - if self.ship_direction == ShipDirection.HORIZONTAL: - if ShipField.field_size - col >= self.ship_size: - for c in range(col, col + self.ship_size): - if not self.check_blocked(row, c): - return False - return True - - return False - - def check_blocked(self, row, col): - # Функция возвращает True, если все клетки вокруг клетки с координатами row, col - # либо находятся за пределами поля, либо в них нет корабля/они пустые - for r in range(row - 1, row + 2): - for c in range(col - 1, col + 2): - if 0 <= r < ShipField.field_size and 0 <= c < ShipField.field_size: - cell = (self.field[r * ShipField.field_size + c]).strip() - if cell != '' and cell != 'p': - return False - return True - - def set_ship_size(self, value): - if value is None: - return - - if type(value) is str and value.isnumeric(): - value = int(value) - - if type(value) is int and 1 <= value <= 4: - self.ship_size = value - - def set_ship_direction(self, value): - if value is None: - return - - if type(value) is not ShipDirection: - return - - if value != ShipDirection.UNKNOWN: - self.ship_direction = value - - def toggle_ship_direction(self): - if self.ship_direction == ShipDirection.VERTICAL: - self.ship_direction = ShipDirection.HORIZONTAL - else: - self.ship_direction = ShipDirection.VERTICAL - - def set_field_mode(self, value): - if value is None: - return - - if type(value) is not ShipMode: - return - - self.field_mode = value - - def print_field(self): - print(self.ships) - for r in range(0, ShipField.field_size): - blocked_string = "" - ship_string = "" - for c in range(0, ShipField.field_size): - blocked_string += str(self.check_blocked(r, c))[0] + ", " - ship_string += self.field[r * ShipField.field_size + c] + ', ' - print(ship_string[:-2]) - # print(blocked_string[:-2] + ' ' + ship_string[:-2]) - print("********************************************************************") - - @staticmethod - def convert_to_json(obj): - if isinstance(obj, ShipField): - result = copy.deepcopy(obj.__dict__) - result['field_mode'] = obj.field_mode.value - result['ship_direction'] = obj.ship_direction.value - return result +import copy + +from ShootResult import ShootResult +from ShipDirection import ShipDirection +from ShipMode import ShipMode + + +class ShipField: + field_size = 10 + + def __init__(self): + self.field = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] + + self.ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1] + self.field_mode = ShipMode.INACTIVE + self.ship_size = 4 + self.ship_direction = ShipDirection.VERTICAL + + def from_json(self, obj): + self.field = obj['field'] + self.ships = obj['ships'] + self.field_mode = ShipMode.from_string(obj['field_mode']) + self.ship_size = obj['ship_size'] + self.ship_direction = ShipDirection.from_string(obj['ship_direction']) + + def __getitem__(self, item): + if item is None: + return None + + if type(item) is not int and item.isnumeric(): + item = int(item) + + if type(item) is int and 0 <= item < len(self.field): + return self.field[item] + + return None + + + + def mark_killed(self, row, col): + if row < 0 or row > ShipField.field_size: + return + if col < 0 or col > ShipField.field_size: + return + + self.field[row * ShipField.field_size + col] = 'x' + self.fill_empty_killed(row, col) + + + #check vertical + for r in range(row + 1, ShipField.field_size): + if self.check_damaged(r, col): + self.field[r * ShipField.field_size + col] = 'x' + self.fill_empty_killed(r, col) + + else: + break + + for r in range(row - 1, -1, -1): + if self.check_damaged(r, col): + self.field[r * ShipField.field_size + col] = 'x' + self.fill_empty_killed(r, col) + else: + break + + # проверим горизонталь + for c in range(col + 1, ShipField.field_size): + if self.check_damaged(row, c): + self.field[row * ShipField.field_size + c] = 'x' + self.fill_empty_killed(row, c) + else: + break + + for c in range(col - 1, -1, -1): + if self.check_damaged(row, c): + self.field[row * ShipField.field_size + c] = 'x' + self.fill_empty_killed(row, c) + else: + break + + def check_killed(self, row, col): + if row < 0 or row > ShipField.field_size: + return + if col < 0 or col > ShipField.field_size: + return + + ship_killed = True + ship_direction = ShipDirection.UNKNOWN + + #check vertical + for r in range(row + 1, ShipField.field_size): + if self.check_ship(r, col): + return False + + elif self.check_empty(r, col): + break + + for r in range(row - 1, -1, -1): + if self.check_ship(r, col): + return False + + elif self.check_empty(r, col): + break + + # проверим горизонталь + for c in range(col + 1, ShipField.field_size): + if self.check_ship(row, c): + return False + + elif self.check_empty(row, c): + break + + for c in range(col - 1, -1, -1): + if self.check_ship(row, c): + return False + + elif self.check_empty(row, c): + break + + return True + + def fill_empty_killed(self, row, col): + for r in range(row - 1, row + 2): + for c in range(col - 1, col + 2): + if self.check_empty(r, c): + self.field[r * ShipField.field_size + c] = '0' + + def action(self, row, col): + self.clear_marker() + + if self.field_mode == ShipMode.PUT: + if self.check_ship(row, col): + self.get_ship(row, col) + + elif self.ship_size in self.ships and self.check_possible(row, col): + self.set_ship(row, col) + + elif self.field_mode == ShipMode.SHOOT: + shoot_result = self.shoot(row, col) + + if shoot_result == ShootResult.KILLED: + self.mark_killed(row, col) + self.fill_empty_killed(row, col) + + return shoot_result == ShootResult.EMPTY + + return False + + def target(self, row, col): + self.clear_marker() + + if self.field_mode == ShipMode.PUT: + if self.check_possible(row, col): + if self.ship_direction == ShipDirection.VERTICAL: + for r in range(row, row + self.ship_size): + if self.ship_size in self.ships: + self.field[r * ShipField.field_size + col] = "p" + else: + self.field[r * ShipField.field_size + col] = "r" + + if self.ship_direction == ShipDirection.HORIZONTAL: + for c in range(col, col + self.ship_size): + if self.ship_size in self.ships: + self.field[row * ShipField.field_size + c] = "p" + else: + self.field[row * ShipField.field_size + c] = "r" + elif self.field_mode == ShipMode.SHOOT: + self.field[row * ShipField.field_size + col] += "+" + + def clear_marker(self): + for i in range(0, len(self.field)): + if self.field[i] == "p" or self.field[i] == "r": + self.field[i] = "" + + if "+" in self.field[i]: + self.field[i] = self.field[i].replace("+", "") + + def set_ship(self, row, col): + if row < 0 or row > ShipField.field_size: + return + if col < 0 or col > ShipField.field_size: + return + index = row * ShipField.field_size + col + if self.ship_direction == ShipDirection.VERTICAL: + if ShipField.field_size - row < self.ship_size: + return + for r in range(row, row + self.ship_size): + index = r * ShipField.field_size + col + self.field[index] = "1" + if self.ship_direction == ShipDirection.HORIZONTAL: + if ShipField.field_size - col < self.ship_size: + return + for c in range(col, col + self.ship_size): + index = row * ShipField.field_size + c + self.field[index] = "1" + + if self.ship_size in self.ships: + self.ships.remove(self.ship_size) + self.print_field() + + if self.ship_size not in self.ships and len(self.ships) > 0: + self.ship_size = max(self.ships) + + def get_ship(self, row, col): + if row < 0 or row > ShipField.field_size: + return + if col < 0 or col > ShipField.field_size: + return + + self.field[row * ShipField.field_size + col] = "" + + ship_size = 1 + ship_direction = ShipDirection.UNKNOWN + + # проверим вертикаль + for r in range(row + 1, ShipField.field_size): + if self.check_ship(r, col): + ship_size += 1 + ship_direction = ShipDirection.VERTICAL + self.field[r * ShipField.field_size + col] = "" + else: + break + + for r in range(row - 1, -1, -1): + if self.check_ship(r, col): + ship_size += 1 + ship_direction = ShipDirection.VERTICAL + self.field[row * ShipField.field_size + col] = "" + else: + break + + if ship_direction == ShipDirection.UNKNOWN: + + # проверим горизонталь + for c in range(col + 1, ShipField.field_size): + if self.check_ship(row, c): + ship_size += 1 + ship_direction = ShipDirection.HORIZONTAL + self.field[row * ShipField.field_size + c] = "" + else: + break + + for c in range(col - 1, -1, -1): + if self.check_ship(row, c): + ship_size += 1 + ship_direction = ShipDirection.HORIZONTAL + self.field[row * ShipField.field_size + c] = "" + else: + break + self.set_ship_direction(ship_direction) + self.set_ship_size(ship_size) + self.ships.append(ship_size) + + def shoot(self, row, col): + if row < 0 or row > ShipField.field_size - 1: + return ShootResult.UNDEFINED + if col < 0 or col > ShipField.field_size - 1: + return ShootResult.UNDEFINED + index = row * ShipField.field_size + col + if (self.field[index]).strip() == "": + self.field[index] = "0" + return ShootResult.EMPTY + elif (self.field[index]).strip() == "1": + self.field[index] = "\\" + if self.check_killed(row, col): + return ShootResult.KILLED + return ShootResult.DAMAGED + else: + return ShootResult.UNDEFINED + + def check_ship(self, row, col): + # функция должна возвражать тру, если в заданной клетке есть корабль + # в противном случае фолс + return self.field[row * ShipField.field_size + col].strip() == "1" + + def check_damaged(self, row, col): + return self.field[row * ShipField.field_size + col].strip() == "\\" + + def check_empty(self, row, col): + cell = self.field[row * ShipField.field_size + col].strip() + return cell == "0" or cell == "" + + def check_end(self): + return "1" not in self.field + + def check_possible(self, row, col): + # Функция должна возвращать True, если можно поставить сюда корабль, + # в противном случае - False + if self.ship_direction == ShipDirection.VERTICAL: + # Здесь мы знаем, что корабль помещается на поле. + if ShipField.field_size - row >= self.ship_size: + # Теперь нужно проверить, не заблокировано ли какое-то из полей, + for r in range(row, row + self.ship_size): + if not self.check_blocked(r, col): + return False + return True + + if self.ship_direction == ShipDirection.HORIZONTAL: + if ShipField.field_size - col >= self.ship_size: + for c in range(col, col + self.ship_size): + if not self.check_blocked(row, c): + return False + return True + + return False + + def check_blocked(self, row, col): + # Функция возвращает True, если все клетки вокруг клетки с координатами row, col + # либо находятся за пределами поля, либо в них нет корабля/они пустые + for r in range(row - 1, row + 2): + for c in range(col - 1, col + 2): + if 0 <= r < ShipField.field_size and 0 <= c < ShipField.field_size: + cell = (self.field[r * ShipField.field_size + c]).strip() + if cell != '' and cell != 'p': + return False + return True + + def set_ship_size(self, value): + if value is None: + return + + if type(value) is str and value.isnumeric(): + value = int(value) + + if type(value) is int and 1 <= value <= 4: + self.ship_size = value + + def set_ship_direction(self, value): + if value is None: + return + + if type(value) is not ShipDirection: + return + + if value != ShipDirection.UNKNOWN: + self.ship_direction = value + + def toggle_ship_direction(self): + if self.ship_direction == ShipDirection.VERTICAL: + self.ship_direction = ShipDirection.HORIZONTAL + else: + self.ship_direction = ShipDirection.VERTICAL + + def set_field_mode(self, value): + if value is None: + return + + if type(value) is not ShipMode: + return + + self.field_mode = value + + def print_field(self): + print(self.ships) + for r in range(0, ShipField.field_size): + blocked_string = "" + ship_string = "" + for c in range(0, ShipField.field_size): + blocked_string += str(self.check_blocked(r, c))[0] + ", " + ship_string += self.field[r * ShipField.field_size + c] + ', ' + print(ship_string[:-2]) + # print(blocked_string[:-2] + ' ' + ship_string[:-2]) + print("********************************************************************") + + @staticmethod + def convert_to_json(obj): + if isinstance(obj, ShipField): + result = copy.deepcopy(obj.__dict__) + result['field_mode'] = obj.field_mode.value + result['ship_direction'] = obj.ship_direction.value + return result diff --git a/HNS/Excercises/ShipCraft/Переделка/ShipMode.py b/HNS/Excercises/ShipCraft/Переделка/ShipMode.py index dbffd33..6cd65f8 100644 --- a/HNS/Excercises/ShipCraft/Переделка/ShipMode.py +++ b/HNS/Excercises/ShipCraft/Переделка/ShipMode.py @@ -1,17 +1,17 @@ -from enum import Enum - - -class ShipMode(Enum): - PUT = 'PUT' - SHOOT = 'SHOOT' - INACTIVE = 'INACTIVE' - - @staticmethod - def from_string(raw_value): - if raw_value: - value = raw_value.upper() - if value in ShipMode.__members__: - return ShipMode[value] - return ShipMode.INACTIVE - - +from enum import Enum + + +class ShipMode(Enum): + PUT = 'PUT' + SHOOT = 'SHOOT' + INACTIVE = 'INACTIVE' + + @staticmethod + def from_string(raw_value): + if raw_value: + value = raw_value.upper() + if value in ShipMode.__members__: + return ShipMode[value] + return ShipMode.INACTIVE + + diff --git a/HNS/Excercises/ShipCraft/Переделка/ShipView.py b/HNS/Excercises/ShipCraft/Переделка/ShipView.py index b3f1247..cad93d3 100644 --- a/HNS/Excercises/ShipCraft/Переделка/ShipView.py +++ b/HNS/Excercises/ShipCraft/Переделка/ShipView.py @@ -1,12 +1,12 @@ -from ShipField import ShipField -from tkinter import StringVar - - -class ShipView: - - def __init__(self, ship_field, buttons, enemy): - self.ship_field = ship_field - self.buttons = buttons - self.remaining_ship_text = StringVar() - self.enemy = enemy - self.active = False +from ShipField import ShipField +from tkinter import StringVar + + +class ShipView: + + def __init__(self, ship_field, buttons, enemy): + self.ship_field = ship_field + self.buttons = buttons + self.remaining_ship_text = StringVar() + self.enemy = enemy + self.active = False diff --git a/HNS/Excercises/ShipCraft/Переделка/ShootResult.py b/HNS/Excercises/ShipCraft/Переделка/ShootResult.py index b5b13da..b64107a 100644 --- a/HNS/Excercises/ShipCraft/Переделка/ShootResult.py +++ b/HNS/Excercises/ShipCraft/Переделка/ShootResult.py @@ -1,8 +1,8 @@ -from enum import Enum - - -class ShootResult(Enum): - EMPTY = "EMPTY" - DAMAGED = "DAMAGED" - KILLED = "KILLED" - UNDEFINED = "UNDEFINED" +from enum import Enum + + +class ShootResult(Enum): + EMPTY = "EMPTY" + DAMAGED = "DAMAGED" + KILLED = "KILLED" + UNDEFINED = "UNDEFINED" diff --git a/HNS/Excercises/ShipCraft/Переделка/Test.py b/HNS/Excercises/ShipCraft/Переделка/Test.py index b5a15f6..c68eaec 100644 --- a/HNS/Excercises/ShipCraft/Переделка/Test.py +++ b/HNS/Excercises/ShipCraft/Переделка/Test.py @@ -1,78 +1,78 @@ -from ShipField import ShipField - - - -def verify_value(actual, expected): - if actual == expected: - print("OK") - else: - print("ERROR") - - -my_field = ShipField() - -print("set_ship_size()") -my_field.set_ship_size(1) - -verify_value(my_field.ship_size, 1) - -my_field.set_ship_size(0) -my_field.set_ship_size(6) - -verify_value(my_field.ship_size, 1) - -my_field.set_ship_size([]) -my_field.set_ship_size("") -my_field.set_ship_size(None) -my_field.set_ship_size(True) -my_field.set_ship_size(False) -verify_value(my_field.ship_size, 1) - -my_field.set_ship_size("2") -verify_value(my_field.ship_size, 2) -print() - -print("set_ship_direction()") -my_field.set_ship_direction(1) -verify_value(my_field.ship_direction, 1) - -my_field.set_ship_direction(-1) -my_field.set_ship_direction(6) -verify_value(my_field.ship_direction, 1) - -my_field.set_ship_direction([]) -my_field.set_ship_direction("") -my_field.set_ship_direction(None) -my_field.set_ship_direction(True) -my_field.set_ship_direction(False) -verify_value(my_field.ship_direction, 1) - -my_field.set_ship_direction("0") -verify_value(my_field.ship_direction, 0) -print() - -print('toggle_field_mode()') -verify_value(my_field.field_mode, 0) - -my_field.toggle_field_mode() -verify_value(my_field.field_mode, 1) - -my_field.toggle_field_mode() -verify_value(my_field.field_mode, 0) -print() - -print("set_ship()") -verify_value(my_field.field[0], " ") - -my_field.set_ship_size(1,) -my_field.set_ship_direction(0) -my_field.set_ship(0, 0) - -verify_value(my_field.field[0], "1") -print() - -my_field.set_ship_size(4) -my_field.set_ship_direction(0) -my_field.set_ship(5, 5) -my_field.print_field() - +from ShipField import ShipField + + + +def verify_value(actual, expected): + if actual == expected: + print("OK") + else: + print("ERROR") + + +my_field = ShipField() + +print("set_ship_size()") +my_field.set_ship_size(1) + +verify_value(my_field.ship_size, 1) + +my_field.set_ship_size(0) +my_field.set_ship_size(6) + +verify_value(my_field.ship_size, 1) + +my_field.set_ship_size([]) +my_field.set_ship_size("") +my_field.set_ship_size(None) +my_field.set_ship_size(True) +my_field.set_ship_size(False) +verify_value(my_field.ship_size, 1) + +my_field.set_ship_size("2") +verify_value(my_field.ship_size, 2) +print() + +print("set_ship_direction()") +my_field.set_ship_direction(1) +verify_value(my_field.ship_direction, 1) + +my_field.set_ship_direction(-1) +my_field.set_ship_direction(6) +verify_value(my_field.ship_direction, 1) + +my_field.set_ship_direction([]) +my_field.set_ship_direction("") +my_field.set_ship_direction(None) +my_field.set_ship_direction(True) +my_field.set_ship_direction(False) +verify_value(my_field.ship_direction, 1) + +my_field.set_ship_direction("0") +verify_value(my_field.ship_direction, 0) +print() + +print('toggle_field_mode()') +verify_value(my_field.field_mode, 0) + +my_field.toggle_field_mode() +verify_value(my_field.field_mode, 1) + +my_field.toggle_field_mode() +verify_value(my_field.field_mode, 0) +print() + +print("set_ship()") +verify_value(my_field.field[0], " ") + +my_field.set_ship_size(1,) +my_field.set_ship_direction(0) +my_field.set_ship(0, 0) + +verify_value(my_field.field[0], "1") +print() + +my_field.set_ship_size(4) +my_field.set_ship_direction(0) +my_field.set_ship(5, 5) +my_field.print_field() + diff --git a/HNS/Excercises/ShipCraft/Переделка/__pycache__/GameMode.cpython-312.pyc b/HNS/Excercises/ShipCraft/Переделка/__pycache__/GameMode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9eca069cd247aabf2fef833a29d9e028a478e56d GIT binary patch literal 883 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 literal 0 HcmV?d00001 diff --git a/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipMode.cpython-312.pyc b/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipMode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbacaf130a708454dc6e88cecc0608a668b8e1f6 GIT binary patch literal 868 zcmYjP&ubGw6rR~1>9%RzswuSxaf?`7ti5>?L258PG!argEDOuJGqow%B+l+uTOvj+ z*rPq=Qq-&TqF_M$^$&QN#Y4lOpm-85O6|E8y_LZs^`M44WHhoH8#gF30v_(JAH?(EM4-EPwZp06Hwn0DA_x4J~ zJC9N15@hG{MLT=f!^A5EIIxA0^Tb^aZTgJ1xV%MQ^YOrCnKZr`Wl zGhg({J>7_PgK9>HH-fyWG0kx*u8$pujc|LaC@Kp+>NvL}x13an@Rtk;5U#P&Aaui$ z=i_jtiiplrF8~=AI^x59nEL$~Wc DJOtU8 literal 0 HcmV?d00001 diff --git a/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipView.cpython-312.pyc b/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShipView.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8bc68b47502625618b80b3fe1fd091478c1d902 GIT binary patch literal 789 zcmYLHOKa3n6h1e}JUVS{eY8TYI-m;!wYaaiQENBOrqD$QTw-#^29r#^xucyji%|!h zg@U`;6kWKIZWJ64Uw^>O9dI!OyK*IN#6bjCo|~9@Am2TY?|kPz@@aay0%*J6ck3$z z;HwI9GyXZ_3+VL01CIm{f(1nRT0lb0(g*m{14Qil{-`GOv zLz}dLqL*1)!zfn;CI?6#$k+J2lW*nAw5aZMd8?I_Da8W_N_P(DSG}C4 zN@}C$5IQhgINLKG&5Vwp!e#2qnWg6|J>zq^I+|O+L}fI8qGvpw93vNMcw|(KoRCqP zR45G_UNcbs6s5PDPLNgj402xppT&hAQc%o6JwdF7cVTQ43X2&>l~J3k$4g4$mLCbm t(|5=^k7545+Mn{pZ0;pKj|KHV#B&HgbVA5JoZg3%zl$ZZ_!AJ)w!aFl%cuYV literal 0 HcmV?d00001 diff --git a/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShootResult.cpython-312.pyc b/HNS/Excercises/ShipCraft/Переделка/__pycache__/ShootResult.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89dc459ebdc161d8b8395db1485fd20c9c090ab8 GIT binary patch literal 529 zcmX|;ze^lJ6vt=w*PX`m2hmu>!XgM;B!7Vf#9hxL-V(f6WEohNosko6Z_Vs2c!jY3 zfV6hkh^a%G1acro^ADt%?T!VjR3S~^w6V&YTlK+w-uKOWGsC?1t5O+9V5fgiw|n4! z%izKEdof%B(L)qb+(IFCF-8iiBB~rCsxtgVE$UpQtC{*A8JIZN>~<0cMW!IW4~7dM zdWazxQ{*ZXyDC*&jjFCrHP`6srjb8sG^41q$>OBd$#uK__TBruWUbU!s>ru#v6$MGi+MSq)Gx04u%07y|xDw~0znC2?ijyqO4q-PHKgA_!wu6_9CO)TR z-DwbeFJL^_iCIh<&7IvCO)6WlTeDa~tG1XjS&}S}3P+U-vYE&@=>aM(8wBj|Nfl!Vho(23< UF~-+u?#9sY!pVzU1a5TdKbJL@Z2$lO literal 0 HcmV?d00001 diff --git a/HNS/Excercises/ShipCraft/Переделка/main.py b/HNS/Excercises/ShipCraft/Переделка/main.py index dc1f71f..90f35ec 100644 --- a/HNS/Excercises/ShipCraft/Переделка/main.py +++ b/HNS/Excercises/ShipCraft/Переделка/main.py @@ -1,287 +1,289 @@ -import json -import os -import random -import time -from tkinter import * -from tkinter import filedialog -from ShipView import ShipView -from ShipMode import ShipMode -from ShipField import ShipField -from GameMode import GameMode -from ShootResult import ShootResult - - - -def create_view(window, enemy): - field = ShipField() - buttons = [] - view = ShipView(field, buttons, enemy) - for r in range(0, field.field_size): - for c in range(0, field.field_size): - btn = Button(window, text='', width=5, height=2) - btn.bind('', lambda e, x=r, y=c: left_button_click(view, x, y)) - btn.bind('', lambda e: right_button_click(view)) - btn.bind('', lambda e, x=r, y=c: button_enter(view, x, y)) - buttons.append(btn) - - colorize(view) - return view - -def show_view(view, col_offset=0, row_offset=0): - field_size = view.ship_field.field_size - - for r in range(0, field_size): - for c in range(0, field_size): - btn = view.buttons[r * field_size +c] - btn.grid(column=c + col_offset, row=r + row_offset) - -def hide_view(view): - for button in view.buttons: - button.grid_forget() - - -def colorize(view): - field = view.ship_field - for i in range(len(field.field)): - bg = "white" - if field.field[i] == "1" and not view.enemy: - bg = 'pink' - if field.field[i] == "\\": - bg = 'grey' - if field.field[i] == "0": - bg = 'black' - if field.field[i] == "p": - bg = 'blue' - if field.field[i] == "r": - bg = 'red' - if "+" in field.field[i] and view.enemy: - bg = 'orange' - - view.buttons[i].configure(bg=bg) - - refresh_remaining_ships_label(view) - - -def keypress_handler(e): - if e.keysym.isnumeric(): - if my_view.active: - my_view.ship_field.set_ship_size(int(e.keysym)) - elif enemy_view.active: - enemy_view.ship_field.set_ship_size(int(e.keysym)) - - -def left_button_click(view, row, col): - - action_result = view.ship_field.action(row, col) - - if action_result and view.enemy and game_mode == GameMode.BATTLE: - # Ход соперника - enemy_shoot_result = ShootResult.UNDEFINED - - while enemy_shoot_result != ShootResult.EMPTY: - my_row = random.randint(0, ShipField.field_size - 1) - my_col = random.randint(0, ShipField.field_size - 1) - - enemy_shoot_result = my_view.ship_field.shoot(my_row, my_col) - if game_mode == GameMode.BATTLE and my_view.ship_field.check_end(): - next_game_mode() - return - colorize(my_view) - - if game_mode == GameMode.BATTLE and view.ship_field.check_end(): - next_game_mode() - return - - colorize(view) - - -def right_button_click(view): - view.ship_field.toggle_ship_direction() - colorize(view) - - -def button_enter(view, row, col): - if view.enemy: - my_view.ship_field.clear_marker() - enemy_view.ship_field.target(row, col) - - enemy_view.active = True - my_view.active = False - else: - enemy_view.ship_field.clear_marker() - my_view.ship_field.target(row, col) - - enemy_view.active = False - my_view.active = True - - colorize(my_view) - colorize(enemy_view) - - -def savebutton_click(view): - file_path = filedialog.asksaveasfilename(filetypes=[("JSON files", "*.json")]) - if file_path: - with open(file_path, "w") as f: - json.dump({"shipField": view.ship_field}, f, default=ShipField.convert_to_json) - - -def loadbutton_click(view): - file_path = filedialog.askopenfilename(filetypes=[('JSON files', '*.json')]) - - load_field(view, file_path) - - -def load_field(view, file_path): - if os.path.isfile(file_path): - with open(file_path) as lines: - view.ship_field.from_json(json.load(lines)['shipField']) - - colorize(view) - -def refresh_remaining_ships_label(view): - text = '' - for i in range(1, 5): - count = view.ship_field.ships.count(i) - if count > 0: - text += f'{"[]" * i}: {count}, ' - view.remaining_ship_text.set(text[:-2]) - - -def next_game_mode(): - global game_mode - - if game_mode == GameMode.MENU: - game_mode = GameMode.PLAN - elif game_mode == GameMode.PLAN: - game_mode = GameMode.BATTLE - elif game_mode == GameMode.BATTLE: - game_mode = GameMode.END - - update_game_mode() - - - -def update_game_mode(): - global game_mode - - if game_mode == GameMode.MENU: - window.geometry('400x280') - my_view.ship_field.set_field_mode(ShipMode.INACTIVE) - enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) - - lbl_lower_enemy_horizontal.grid_forget() - lbl_lower_horizontal.grid_forget() - - savebutton.grid_forget() - loadbutton.grid_forget() - - start_button.grid(column=start_column_enemy_field, row=load_button_row, columnspan=4) - load_game_button.grid(column=start_column_enemy_field, row=load_button_row + 1, columnspan=4) - exit_button.grid(column=start_column_enemy_field, row=load_button_row + 2, columnspan=4) - - hide_view(my_view) - hide_view(enemy_view) - - elif game_mode == GameMode.PLAN: - window.geometry('1020x640') - - load_field(enemy_view, "default.json") - - my_view.ship_field.set_field_mode(ShipMode.PUT) - enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) - - lbl_lower_enemy_horizontal.grid(column=start_column_my_field, row=row_horizontal_separator, columnspan=10) - lbl_lower_horizontal.grid(column=start_column_enemy_field, row=row_horizontal_separator, columnspan=10) - - savebutton.grid(column=start_column_my_field, row=load_button_row, columnspan=4) - loadbutton.grid(column=start_column_my_field + 6, row=load_button_row, columnspan=4) - - start_button.grid(column=start_column_my_field + 11, row=load_button_row, columnspan=4) - load_game_button.grid_forget() - exit_button.grid_forget() - - show_view(my_view, start_column_my_field, start_row_my_field) - show_view(enemy_view, start_column_enemy_field, start_row_enemy_field) - - elif game_mode == GameMode.BATTLE: - window.geometry('1020x640') - my_view.ship_field.set_field_mode(ShipMode.INACTIVE) - enemy_view.ship_field.set_field_mode(ShipMode.SHOOT) - - lbl_lower_enemy_horizontal.grid_forget() - lbl_lower_horizontal.grid_forget() - - savebutton.grid_forget() - loadbutton.grid_forget() - - start_button.grid_forget() - load_game_button.grid_forget() - exit_button.grid_forget() - - show_view(my_view, start_column_my_field, start_row_my_field) - show_view(enemy_view, start_column_enemy_field, start_row_enemy_field) - - elif game_mode == GameMode.END: - window.geometry('400x280') - my_view.ship_field.set_field_mode(ShipMode.INACTIVE) - enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) - - lbl_lower_enemy_horizontal.grid_forget() - lbl_lower_horizontal.grid_forget() - - savebutton.grid_forget() - loadbutton.grid_forget() - - start_button.grid_forget() - load_game_button.grid_forget() - exit_button.grid_forget() - - hide_view(my_view) - hide_view(enemy_view) - - lbl_left_vertical.grid(column=start_column_my_field - 1, row=start_row_my_field) - lbl_center_vertical.grid(column=col_vertical_separator, row=start_row_my_field) - lbl_upper_horizontal.grid(column=start_column_my_field, row=start_row_my_field - 1) - - -window = Tk() -window.title("Ship Craft!") -window.bind_all('', keypress_handler) - -start_column_my_field = 1 -start_row_my_field = 1 - -start_column_enemy_field = start_column_my_field + ShipField.field_size + 1 -start_row_enemy_field = start_row_my_field - -col_vertical_separator = start_column_my_field + ShipField.field_size -row_horizontal_separator = start_row_my_field + ShipField.field_size - -load_button_row = start_row_my_field + ShipField.field_size + 1 - -my_view = create_view(window, False) -enemy_view = create_view(window, True) - -lbl_left_vertical = Label(window, text='', width=5, height=2) -lbl_center_vertical = Label(window, text='', width=5, height=2) -lbl_upper_horizontal = Label(window, text='', width=5, height=2) - - - -lbl_lower_horizontal = Label(window, text='', width=50, height=2, textvariable=my_view.remaining_ship_text) -lbl_lower_enemy_horizontal = Label(window, text='', width=50, height=2, textvariable=enemy_view.remaining_ship_text) - - -savebutton = Button(window, text='Save', width=20, height=2, command=lambda: savebutton_click(my_view)) -loadbutton = Button(window, text='Load', width=20, height=2, command=lambda: loadbutton_click(my_view)) - -start_button = Button(window, text='START', width=20, height=2, command=next_game_mode) -load_game_button = Button(window, text='LOAD', width=20, height=2) -exit_button = Button(window, text='EXIT', width=20, height=2) - - -game_mode = GameMode.MENU -update_game_mode() - -window.mainloop() - +import json +import os +import random +import time +from tkinter import * +from tkinter import filedialog +from ShipView import ShipView +from ShipMode import ShipMode +from ShipField import ShipField +from GameMode import GameMode +from ShootResult import ShootResult + + + +def create_view(window, enemy): + field = ShipField() + buttons = [] + view = ShipView(field, buttons, enemy) + for r in range(0, field.field_size): + for c in range(0, field.field_size): + btn = Button(window, text='', width=5, height=2) + btn.bind('', lambda e, x=r, y=c: left_button_click(view, x, y)) + btn.bind('', lambda e: right_button_click(view)) + btn.bind('', lambda e, x=r, y=c: button_enter(view, x, y)) + buttons.append(btn) + + colorize(view) + return view + +def show_view(view, col_offset=0, row_offset=0): + field_size = view.ship_field.field_size + + for r in range(0, field_size): + for c in range(0, field_size): + btn = view.buttons[r * field_size +c] + btn.grid(column=c + col_offset, row=r + row_offset) + +def hide_view(view): + for button in view.buttons: + button.grid_forget() + + +def colorize(view): + field = view.ship_field + for i in range(len(field.field)): + bg = "white" + if field.field[i] == "1" and not view.enemy: + bg = 'pink' + if field.field[i] == "\\": + bg = 'grey' + if field.field[i] == "x": + bg = 'red' + if field.field[i] == "0": + bg = 'black' + if field.field[i] == "p": + bg = 'blue' + if field.field[i] == "r": + bg = 'red' + if "+" in field.field[i] and view.enemy: + bg = 'orange' + + view.buttons[i].configure(bg=bg) + + refresh_remaining_ships_label(view) + + +def keypress_handler(e): + if e.keysym.isnumeric(): + if my_view.active: + my_view.ship_field.set_ship_size(int(e.keysym)) + elif enemy_view.active: + enemy_view.ship_field.set_ship_size(int(e.keysym)) + + +def left_button_click(view, row, col): + + action_result = view.ship_field.action(row, col) + + if action_result and view.enemy and game_mode == GameMode.BATTLE: + # Ход соперника + enemy_shoot_result = ShootResult.UNDEFINED + + while enemy_shoot_result != ShootResult.EMPTY: + my_row = random.randint(0, ShipField.field_size - 1) + my_col = random.randint(0, ShipField.field_size - 1) + + enemy_shoot_result = my_view.ship_field.shoot(my_row, my_col) + if game_mode == GameMode.BATTLE and my_view.ship_field.check_end(): + next_game_mode() + return + colorize(my_view) + + if game_mode == GameMode.BATTLE and view.ship_field.check_end(): + next_game_mode() + return + + colorize(view) + + +def right_button_click(view): + view.ship_field.toggle_ship_direction() + colorize(view) + + +def button_enter(view, row, col): + if view.enemy: + my_view.ship_field.clear_marker() + enemy_view.ship_field.target(row, col) + + enemy_view.active = True + my_view.active = False + else: + enemy_view.ship_field.clear_marker() + my_view.ship_field.target(row, col) + + enemy_view.active = False + my_view.active = True + + colorize(my_view) + colorize(enemy_view) + + +def savebutton_click(view): + file_path = filedialog.asksaveasfilename(filetypes=[("JSON files", "*.json")]) + if file_path: + with open(file_path, "w") as f: + json.dump({"shipField": view.ship_field}, f, default=ShipField.convert_to_json) + + +def loadbutton_click(view): + file_path = filedialog.askopenfilename(filetypes=[('JSON files', '*.json')]) + + load_field(view, file_path) + + +def load_field(view, file_path): + if os.path.isfile(file_path): + with open(file_path) as lines: + view.ship_field.from_json(json.load(lines)['shipField']) + + colorize(view) + +def refresh_remaining_ships_label(view): + text = '' + for i in range(1, 5): + count = view.ship_field.ships.count(i) + if count > 0: + text += f'{"[]" * i}: {count}, ' + view.remaining_ship_text.set(text[:-2]) + + +def next_game_mode(): + global game_mode + + if game_mode == GameMode.MENU: + game_mode = GameMode.PLAN + elif game_mode == GameMode.PLAN: + game_mode = GameMode.BATTLE + elif game_mode == GameMode.BATTLE: + game_mode = GameMode.END + + update_game_mode() + + + +def update_game_mode(): + global game_mode + + if game_mode == GameMode.MENU: + window.geometry('400x280') + my_view.ship_field.set_field_mode(ShipMode.INACTIVE) + enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) + + lbl_lower_enemy_horizontal.grid_forget() + lbl_lower_horizontal.grid_forget() + + savebutton.grid_forget() + loadbutton.grid_forget() + + start_button.grid(column=start_column_enemy_field, row=load_button_row, columnspan=4) + load_game_button.grid(column=start_column_enemy_field, row=load_button_row + 1, columnspan=4) + exit_button.grid(column=start_column_enemy_field, row=load_button_row + 2, columnspan=4) + + hide_view(my_view) + hide_view(enemy_view) + + elif game_mode == GameMode.PLAN: + window.geometry('1020x640') + + load_field(enemy_view, "default.json") + + my_view.ship_field.set_field_mode(ShipMode.PUT) + enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) + + lbl_lower_enemy_horizontal.grid(column=start_column_my_field, row=row_horizontal_separator, columnspan=10) + lbl_lower_horizontal.grid(column=start_column_enemy_field, row=row_horizontal_separator, columnspan=10) + + savebutton.grid(column=start_column_my_field, row=load_button_row, columnspan=4) + loadbutton.grid(column=start_column_my_field + 6, row=load_button_row, columnspan=4) + + start_button.grid(column=start_column_my_field + 11, row=load_button_row, columnspan=4) + load_game_button.grid_forget() + exit_button.grid_forget() + + show_view(my_view, start_column_my_field, start_row_my_field) + show_view(enemy_view, start_column_enemy_field, start_row_enemy_field) + + elif game_mode == GameMode.BATTLE: + window.geometry('1020x640') + my_view.ship_field.set_field_mode(ShipMode.INACTIVE) + enemy_view.ship_field.set_field_mode(ShipMode.SHOOT) + + lbl_lower_enemy_horizontal.grid_forget() + lbl_lower_horizontal.grid_forget() + + savebutton.grid_forget() + loadbutton.grid_forget() + + start_button.grid_forget() + load_game_button.grid_forget() + exit_button.grid_forget() + + show_view(my_view, start_column_my_field, start_row_my_field) + show_view(enemy_view, start_column_enemy_field, start_row_enemy_field) + + elif game_mode == GameMode.END: + window.geometry('400x280') + my_view.ship_field.set_field_mode(ShipMode.INACTIVE) + enemy_view.ship_field.set_field_mode(ShipMode.INACTIVE) + + lbl_lower_enemy_horizontal.grid_forget() + lbl_lower_horizontal.grid_forget() + + savebutton.grid_forget() + loadbutton.grid_forget() + + start_button.grid_forget() + load_game_button.grid_forget() + exit_button.grid_forget() + + hide_view(my_view) + hide_view(enemy_view) + + lbl_left_vertical.grid(column=start_column_my_field - 1, row=start_row_my_field) + lbl_center_vertical.grid(column=col_vertical_separator, row=start_row_my_field) + lbl_upper_horizontal.grid(column=start_column_my_field, row=start_row_my_field - 1) + + +window = Tk() +window.title("Ship Craft!") +window.bind_all('', keypress_handler) + +start_column_my_field = 1 +start_row_my_field = 1 + +start_column_enemy_field = start_column_my_field + ShipField.field_size + 1 +start_row_enemy_field = start_row_my_field + +col_vertical_separator = start_column_my_field + ShipField.field_size +row_horizontal_separator = start_row_my_field + ShipField.field_size + +load_button_row = start_row_my_field + ShipField.field_size + 1 + +my_view = create_view(window, False) +enemy_view = create_view(window, True) + +lbl_left_vertical = Label(window, text='', width=5, height=2) +lbl_center_vertical = Label(window, text='', width=5, height=2) +lbl_upper_horizontal = Label(window, text='', width=5, height=2) + + + +lbl_lower_horizontal = Label(window, text='', width=50, height=2, textvariable=my_view.remaining_ship_text) +lbl_lower_enemy_horizontal = Label(window, text='', width=50, height=2, textvariable=enemy_view.remaining_ship_text) + + +savebutton = Button(window, text='Save', width=20, height=2, command=lambda: savebutton_click(my_view)) +loadbutton = Button(window, text='Load', width=20, height=2, command=lambda: loadbutton_click(my_view)) + +start_button = Button(window, text='START', width=20, height=2, command=next_game_mode) +load_game_button = Button(window, text='LOAD', width=20, height=2) +exit_button = Button(window, text='EXIT', width=20, height=2) + + +game_mode = GameMode.MENU +update_game_mode() + +window.mainloop() + diff --git a/HNS/Excercises/ShipCraft/Переделка/test_ShipField.py b/HNS/Excercises/ShipCraft/Переделка/test_ShipField.py index 14fde4a..3fdfd5a 100644 --- a/HNS/Excercises/ShipCraft/Переделка/test_ShipField.py +++ b/HNS/Excercises/ShipCraft/Переделка/test_ShipField.py @@ -1,281 +1,281 @@ -from unittest import TestCase -from ShipField import ShipField -from ShootResult import ShootResult -from ShipMode import ShipMode -from ShipDirection import ShipDirection - - -class TestShipField(TestCase): - - def test_set_ship_size(self): - ship_field = ShipField() # Заводим объект типа ShipField - - ship_field.set_ship_size(1) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(2) - self.assertEqual(ship_field.ship_size, 2) - ship_field.set_ship_size(3) - self.assertEqual(ship_field.ship_size, 3) - ship_field.set_ship_size(4) - self.assertEqual(ship_field.ship_size, 4) - - def test_set_ship_size_outofrange(self): - ship_field = ShipField() # Заводим объект типа ShipField - ship_field.set_ship_size(1) - - ship_field.set_ship_size(-1) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(0) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(6) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(100) - self.assertEqual(ship_field.ship_size, 1) - - def test_set_ship_size_wrongtype(self): - ship_field = ShipField() # Заводим объект типа ShipField - ship_field.set_ship_size(1) - - ship_field.set_ship_size([]) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size('') - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(None) - self.assertEqual(ship_field.ship_size, 1) - ship_field.set_ship_size(False) - self.assertEqual(ship_field.ship_size, 1) - - def test_toggle_field_mode(self): - ship_field = ShipField() # Заводим объект типа ShipField - self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что изначальное значение field_mode равно 0 - - ship_field.toggle_field_mode() # Вызываем метод, который тестируем - self.assertEqual(ship_field.field_mode, ShipMode.SHOOT) # Проверяем, что field_mode принял желаемое значение - - ship_field.toggle_field_mode() # Вызываем метод, который тестируем - self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что field_mode принял желаемое значение - - def test_action(self): - self.fail() - - def test_target_ShipMode_PUT(self): - ship_field = ShipField() - ship_field.set_ship_size(3) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - index = 5 * ship_field.field_size + 5 - - old_field_string = str.join(' ', ship_field.field) - ship_field.target(5, 5) - field_after_target = [ship_field.field[index], ship_field.field[index + 1], ship_field.field[index + 2]] - ship_field.field[index] = ' ' - ship_field.field[index + 1] = ' ' - ship_field.field[index + 2] = ' ' - - new_field_string = str.join(' ', ship_field.field) - - self.assertListEqual(['p', 'p', 'p'], field_after_target) - self.assertNotIn('p', new_field_string) - self.assertEqual(new_field_string, old_field_string) - - def test_target_ShipMode_SHOOT(self): - ship_field = ShipField() - ship_field.toggle_field_mode() - - index = 5 * ship_field.field_size + 5 - - old_field_string = str.join(' ', ship_field.field) - ship_field.target(5, 5) - field_after_target = ship_field.field[index] - ship_field.field[index] = ship_field.field[index].replace('+', '') - new_field_string = str.join(' ', ship_field.field) - - self.assertIn('+', field_after_target) - self.assertNotIn('+', new_field_string) - self.assertEqual(new_field_string, old_field_string) - - def get_ship(self): - self.fail() - - def test_clear_marker(self): - ship_field = ShipField() - ship_field.field[0] = 'p' - ship_field.field[ship_field.field_size - 1] = 'p' - ship_field.field[ship_field.field_size - 4] = 'r' - ship_field.clear_marker() - - self.assertNotIn('p', ship_field.field) - self.assertNotIn('r', ship_field.field) - - def test_shoot_empty(self): - ship_field = ShipField() - - self.assertEqual(ship_field.field[0].strip(), '') - result = ship_field.shoot(0, 0) - - self.assertEqual(ship_field.field[0].strip(), '0') - self.assertEqual(result, ShootResult.EMPTY) - - def test_shoot_ship(self): - ship_field = ShipField() - - ship_field.field[0] = '1' - result = ship_field.shoot(0, 0) - - self.assertEqual(ship_field.field[0].strip(), '\\') - self.assertEqual(result, ShootResult.DAMAGED) - - def test_shoot_unknown(self): - ship_field = ShipField() - - ship_field.field[0] = 'x' - result = ship_field.shoot(0, 0) - - self.assertEqual(ship_field.field[0].strip(), 'x') - self.assertEqual(result, ShootResult.UNDEFINED) - - def test_shoot_outofrange(self): - ship_field = ShipField() - old_field_string = str.join(' ', ship_field.field) - - result = ship_field.shoot(-1, -1) - self.assertEqual(result, ShootResult.UNDEFINED) - - result = ship_field.shoot(-1, 0) - self.assertEqual(result, ShootResult.UNDEFINED) - - result = ship_field.shoot(1000, 1000) - self.assertEqual(result, ShootResult.UNDEFINED) - - result = ship_field.shoot(0, 1000) - self.assertEqual(result, ShootResult.UNDEFINED) - - new_field_string = str.join(' ', ship_field.field) - self.assertEqual(new_field_string, old_field_string) - - def test_check_possible_false(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - # action действие - ship_field.set_ship(5, 3) - # assertion проверка занятых - self.assertEqual(ship_field.check_possible(5, 3), False) - self.assertEqual(ship_field.check_possible(5, 4), False) - self.assertEqual(ship_field.check_possible(5, 5), False) - self.assertEqual(ship_field.check_possible(5, 6), False) - # проверка строки ниже - self.assertEqual(ship_field.check_possible(6, 3), False) - self.assertEqual(ship_field.check_possible(6, 4), False) - self.assertEqual(ship_field.check_possible(6, 5), False) - self.assertEqual(ship_field.check_possible(6, 6), False) - # проверка строки выше - self.assertEqual(ship_field.check_possible(4, 3), False) - self.assertEqual(ship_field.check_possible(4, 4), False) - self.assertEqual(ship_field.check_possible(4, 5), False) - self.assertEqual(ship_field.check_possible(4, 6), False) - - def test_check_possible_true(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - # action действие - ship_field.set_ship(5, 3) - - # проверка свободных ниже на 2 строки - self.assertEqual(ship_field.check_possible(7, 3), True) - self.assertEqual(ship_field.check_possible(7, 4), True) - self.assertEqual(ship_field.check_possible(7, 5), True) - self.assertEqual(ship_field.check_possible(7, 6), True) - # проверка свободных ВЫШЕ на 2 строки - self.assertEqual(ship_field.check_possible(3, 3), True) - self.assertEqual(ship_field.check_possible(3, 4), True) - self.assertEqual(ship_field.check_possible(3, 5), True) - self.assertEqual(ship_field.check_possible(3, 6), True) - - - def test_check_blocked(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - # action действие - ship_field.set_ship(5, 3) - # assertion проверка занятых - self.assertEqual(ship_field.check_blocked(5, 3), False) - self.assertEqual(ship_field.check_blocked(5, 4), False) - self.assertEqual(ship_field.check_blocked(5, 5), False) - self.assertEqual(ship_field.check_blocked(5, 6), False) - #проверка строки ниже - self.assertEqual(ship_field.check_blocked(6, 3), False) - self.assertEqual(ship_field.check_blocked(6, 4), False) - self.assertEqual(ship_field.check_blocked(6, 5), False) - self.assertEqual(ship_field.check_blocked(6, 7), False) - #проверка свободных ниже на 2 строки - self.assertEqual(ship_field.check_blocked(7, 3), True) - self.assertEqual(ship_field.check_blocked(7, 4), True) - self.assertEqual(ship_field.check_blocked(7, 5), True) - self.assertEqual(ship_field.check_blocked(7, 6), True) - - def test_set_ship_direction(self): - ship_field = ShipField() # Заводим объект типа ShipField - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - - ship_field.set_ship_direction(ShipDirection.VERTICAL) - self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) - - def test_set_ship_direction_outofrange(self): - ship_field = ShipField() # Заводим объект типа ShipField - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - - ship_field.set_ship_direction(-1) - ship_field.set_ship_direction(2) - self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - - def test_set_ship_direction_wrongtype(self): - ship_field = ShipField() # Заводим объект типа ShipField - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - - ship_field.set_ship_direction(None) - ship_field.set_ship_direction([2]) - ship_field.set_ship_direction({}) - self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - - def test_toggle_ship_direction(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_direction(ShipDirection.VERTICAL) - # action действие - ship_field.toggle_ship_direction() - # assertion проверка - self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - - ship_field.toggle_ship_direction() - self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) - - def test_set_ship(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - # action действие - ship_field.set_ship(5, 3) - # assertion проверка - self.assertEqual(ship_field.field[53].strip(), '1') - self.assertEqual(ship_field.field[54].strip(), '1') - self.assertEqual(ship_field.field[55].strip(), '1') - self.assertEqual(ship_field.field[56].strip(), '1') - - def test_set_ship_size4_vertical_outofrange(self): - # arrangement установка - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.VERTICAL) - old_field_string = str.join(" ", ship_field.field) - # action действие - ship_field.set_ship(7, 3) - # assertion проверка - new_field_string = str.join(" ", ship_field.field) +from unittest import TestCase +from ShipField import ShipField +from ShootResult import ShootResult +from ShipMode import ShipMode +from ShipDirection import ShipDirection + + +class TestShipField(TestCase): + + def test_set_ship_size(self): + ship_field = ShipField() # Заводим объект типа ShipField + + ship_field.set_ship_size(1) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(2) + self.assertEqual(ship_field.ship_size, 2) + ship_field.set_ship_size(3) + self.assertEqual(ship_field.ship_size, 3) + ship_field.set_ship_size(4) + self.assertEqual(ship_field.ship_size, 4) + + def test_set_ship_size_outofrange(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_size(1) + + ship_field.set_ship_size(-1) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(0) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(6) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(100) + self.assertEqual(ship_field.ship_size, 1) + + def test_set_ship_size_wrongtype(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_size(1) + + ship_field.set_ship_size([]) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size('') + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(None) + self.assertEqual(ship_field.ship_size, 1) + ship_field.set_ship_size(False) + self.assertEqual(ship_field.ship_size, 1) + + def test_toggle_field_mode(self): + ship_field = ShipField() # Заводим объект типа ShipField + self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что изначальное значение field_mode равно 0 + + ship_field.toggle_field_mode() # Вызываем метод, который тестируем + self.assertEqual(ship_field.field_mode, ShipMode.SHOOT) # Проверяем, что field_mode принял желаемое значение + + ship_field.toggle_field_mode() # Вызываем метод, который тестируем + self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что field_mode принял желаемое значение + + def test_action(self): + self.fail() + + def test_target_ShipMode_PUT(self): + ship_field = ShipField() + ship_field.set_ship_size(3) + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + index = 5 * ship_field.field_size + 5 + + old_field_string = str.join(' ', ship_field.field) + ship_field.target(5, 5) + field_after_target = [ship_field.field[index], ship_field.field[index + 1], ship_field.field[index + 2]] + ship_field.field[index] = ' ' + ship_field.field[index + 1] = ' ' + ship_field.field[index + 2] = ' ' + + new_field_string = str.join(' ', ship_field.field) + + self.assertListEqual(['p', 'p', 'p'], field_after_target) + self.assertNotIn('p', new_field_string) + self.assertEqual(new_field_string, old_field_string) + + def test_target_ShipMode_SHOOT(self): + ship_field = ShipField() + ship_field.toggle_field_mode() + + index = 5 * ship_field.field_size + 5 + + old_field_string = str.join(' ', ship_field.field) + ship_field.target(5, 5) + field_after_target = ship_field.field[index] + ship_field.field[index] = ship_field.field[index].replace('+', '') + new_field_string = str.join(' ', ship_field.field) + + self.assertIn('+', field_after_target) + self.assertNotIn('+', new_field_string) + self.assertEqual(new_field_string, old_field_string) + + def get_ship(self): + self.fail() + + def test_clear_marker(self): + ship_field = ShipField() + ship_field.field[0] = 'p' + ship_field.field[ship_field.field_size - 1] = 'p' + ship_field.field[ship_field.field_size - 4] = 'r' + ship_field.clear_marker() + + self.assertNotIn('p', ship_field.field) + self.assertNotIn('r', ship_field.field) + + def test_shoot_empty(self): + ship_field = ShipField() + + self.assertEqual(ship_field.field[0].strip(), '') + result = ship_field.shoot(0, 0) + + self.assertEqual(ship_field.field[0].strip(), '0') + self.assertEqual(result, ShootResult.EMPTY) + + def test_shoot_ship(self): + ship_field = ShipField() + + ship_field.field[0] = '1' + result = ship_field.shoot(0, 0) + + self.assertEqual(ship_field.field[0].strip(), '\\') + self.assertEqual(result, ShootResult.DAMAGED) + + def test_shoot_unknown(self): + ship_field = ShipField() + + ship_field.field[0] = 'x' + result = ship_field.shoot(0, 0) + + self.assertEqual(ship_field.field[0].strip(), 'x') + self.assertEqual(result, ShootResult.UNDEFINED) + + def test_shoot_outofrange(self): + ship_field = ShipField() + old_field_string = str.join(' ', ship_field.field) + + result = ship_field.shoot(-1, -1) + self.assertEqual(result, ShootResult.UNDEFINED) + + result = ship_field.shoot(-1, 0) + self.assertEqual(result, ShootResult.UNDEFINED) + + result = ship_field.shoot(1000, 1000) + self.assertEqual(result, ShootResult.UNDEFINED) + + result = ship_field.shoot(0, 1000) + self.assertEqual(result, ShootResult.UNDEFINED) + + new_field_string = str.join(' ', ship_field.field) + self.assertEqual(new_field_string, old_field_string) + + def test_check_possible_false(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_size(4) + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + # action действие + ship_field.set_ship(5, 3) + # assertion проверка занятых + self.assertEqual(ship_field.check_possible(5, 3), False) + self.assertEqual(ship_field.check_possible(5, 4), False) + self.assertEqual(ship_field.check_possible(5, 5), False) + self.assertEqual(ship_field.check_possible(5, 6), False) + # проверка строки ниже + self.assertEqual(ship_field.check_possible(6, 3), False) + self.assertEqual(ship_field.check_possible(6, 4), False) + self.assertEqual(ship_field.check_possible(6, 5), False) + self.assertEqual(ship_field.check_possible(6, 6), False) + # проверка строки выше + self.assertEqual(ship_field.check_possible(4, 3), False) + self.assertEqual(ship_field.check_possible(4, 4), False) + self.assertEqual(ship_field.check_possible(4, 5), False) + self.assertEqual(ship_field.check_possible(4, 6), False) + + def test_check_possible_true(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_size(4) + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + # action действие + ship_field.set_ship(5, 3) + + # проверка свободных ниже на 2 строки + self.assertEqual(ship_field.check_possible(7, 3), True) + self.assertEqual(ship_field.check_possible(7, 4), True) + self.assertEqual(ship_field.check_possible(7, 5), True) + self.assertEqual(ship_field.check_possible(7, 6), True) + # проверка свободных ВЫШЕ на 2 строки + self.assertEqual(ship_field.check_possible(3, 3), True) + self.assertEqual(ship_field.check_possible(3, 4), True) + self.assertEqual(ship_field.check_possible(3, 5), True) + self.assertEqual(ship_field.check_possible(3, 6), True) + + + def test_check_blocked(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_size(4) + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + # action действие + ship_field.set_ship(5, 3) + # assertion проверка занятых + self.assertEqual(ship_field.check_blocked(5, 3), False) + self.assertEqual(ship_field.check_blocked(5, 4), False) + self.assertEqual(ship_field.check_blocked(5, 5), False) + self.assertEqual(ship_field.check_blocked(5, 6), False) + #проверка строки ниже + self.assertEqual(ship_field.check_blocked(6, 3), False) + self.assertEqual(ship_field.check_blocked(6, 4), False) + self.assertEqual(ship_field.check_blocked(6, 5), False) + self.assertEqual(ship_field.check_blocked(6, 7), False) + #проверка свободных ниже на 2 строки + self.assertEqual(ship_field.check_blocked(7, 3), True) + self.assertEqual(ship_field.check_blocked(7, 4), True) + self.assertEqual(ship_field.check_blocked(7, 5), True) + self.assertEqual(ship_field.check_blocked(7, 6), True) + + def test_set_ship_direction(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) + + ship_field.set_ship_direction(ShipDirection.VERTICAL) + self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) + + def test_set_ship_direction_outofrange(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + + ship_field.set_ship_direction(-1) + ship_field.set_ship_direction(2) + self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) + + def test_set_ship_direction_wrongtype(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + + ship_field.set_ship_direction(None) + ship_field.set_ship_direction([2]) + ship_field.set_ship_direction({}) + self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) + + def test_toggle_ship_direction(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_direction(ShipDirection.VERTICAL) + # action действие + ship_field.toggle_ship_direction() + # assertion проверка + self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) + + ship_field.toggle_ship_direction() + self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) + + def test_set_ship(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_size(4) + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + # action действие + ship_field.set_ship(5, 3) + # assertion проверка + self.assertEqual(ship_field.field[53].strip(), '1') + self.assertEqual(ship_field.field[54].strip(), '1') + self.assertEqual(ship_field.field[55].strip(), '1') + self.assertEqual(ship_field.field[56].strip(), '1') + + def test_set_ship_size4_vertical_outofrange(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_size(4) + ship_field.set_ship_direction(ShipDirection.VERTICAL) + old_field_string = str.join(" ", ship_field.field) + # action действие + ship_field.set_ship(7, 3) + # assertion проверка + new_field_string = str.join(" ", ship_field.field) self.assertEqual(new_field_string, old_field_string) \ No newline at end of file