diff --git a/HNC/Exercises/Ship_Battle/ShipDirection.py b/HNC/Exercises/Ship_Battle/ShipDirection.py index 77bae97..522abd6 100644 --- a/HNC/Exercises/Ship_Battle/ShipDirection.py +++ b/HNC/Exercises/Ship_Battle/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 \ No newline at end of file + return ShipDirection.UNKNOWN diff --git a/HNC/Exercises/Ship_Battle/ShipField.py b/HNC/Exercises/Ship_Battle/ShipField.py index c1ed018..04fd698 100644 --- a/HNC/Exercises/Ship_Battle/ShipField.py +++ b/HNC/Exercises/Ship_Battle/ShipField.py @@ -31,8 +31,7 @@ class ShipField: 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 @@ -60,7 +59,7 @@ class ShipField: 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: @@ -83,11 +82,10 @@ class ShipField: 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 > self.field_size: return @@ -110,23 +108,21 @@ class ShipField: if self.ship_size in self.ships: self.ships.remove(self.ship_size) - def get_ship(self, row, col): if row < 0 or row > self.field_size: return if col < 0 or col > self.field_size: return - + self.field[row * self.field_size + col] = '' - + ship_size = 1 ship_direction = ShipDirection.UNKNOWN - # check vertical for r in range(row + 1, self.field_size): if self.check_ship(r, col): - ship_size += 1 + ship_size += 1 ship_direction = ShipDirection.VERTICAL self.field[r * self.field_size + col] = '' else: @@ -134,18 +130,17 @@ class ShipField: for r in range(row - 1, -1, -1): if self.check_ship(r, col): - ship_size += 1 + ship_size += 1 ship_direction = ShipDirection.VERTICAL self.field[r * self.field_size + col] = '' else: break - if ship_direction == ShipDirection.UNKNOWN: - # check horizontal + # check horizontal for c in range(col + 1, self.field_size): if self.check_ship(row, c): - ship_size += 1 + ship_size += 1 ship_direction = ShipDirection.HORIZONTAL self.field[row * self.field_size + c] = '' else: @@ -153,17 +148,17 @@ class ShipField: for c in range(col - 1, - 1, -1): if self.check_ship(row, c): - ship_size += 1 + ship_size += 1 ship_direction = ShipDirection.HORIZONTAL self.field[row * self.field_size + c] = '' else: break self.set_ship_direction(ship_direction) - self.set_ship_size(ship_size) + self.set_ship_size(self.ship_size) + + self.ships.append(self.ship_size) - self.ships.append(ship_size) - def shoot(self, row, col): if row < 0 or row > self.field_size - 1: return ShootResult.UNDEFINED @@ -178,7 +173,7 @@ class ShipField: return ShootResult.DAMAGED else: return ShootResult.UNDEFINED - + def check_ship(self, row, col): return self.field[row * self.field_size + col].strip() == '1' @@ -211,7 +206,7 @@ class ShipField: def set_ship_size(self, value): if value is None: return - + if type(value) is str and value.isnumeric(): value = int(value) @@ -221,10 +216,10 @@ class ShipField: 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 @@ -249,9 +244,8 @@ class ShipField: blocked_string += str(self.check_blocked(r, c))[0] + ", " ship_string += self.field[r * self.field_size + c] + ', ' print(blocked_string[:-2] + ' ' + ship_string[:-2]) - print("********************************************************************") - - + print("********************************************************************") + @staticmethod def convert_to_json(obj): if isinstance(obj, ShipField): diff --git a/HNC/Exercises/Ship_Battle/ShipField_test.py b/HNC/Exercises/Ship_Battle/ShipField_test.py index f12ede3..0c9459b 100644 --- a/HNC/Exercises/Ship_Battle/ShipField_test.py +++ b/HNC/Exercises/Ship_Battle/ShipField_test.py @@ -1,14 +1,14 @@ from unittest import TestCase from ShipField import ShipField from ShootResult import ShootResult -from ShipMode import ShipMode from ShipDirection import ShipDirection +from ShipMode import ShipMode class TestShipField(TestCase): def test_set_ship_size(self): - ship_field = ShipField() # Заводим объект типа ShipField + ship_field = ShipField() # Заводим объект типа ShipField ship_field.set_ship_size(1) self.assertEqual(ship_field.ship_size, 1) @@ -20,7 +20,7 @@ class TestShipField(TestCase): self.assertEqual(ship_field.ship_size, 4) def test_set_ship_size_outofrange(self): - ship_field = ShipField() # Заводим объект типа ShipField + ship_field = ShipField() # Заводим объект типа ShipField ship_field.set_ship_size(1) ship_field.set_ship_size(-1) @@ -33,7 +33,7 @@ class TestShipField(TestCase): self.assertEqual(ship_field.ship_size, 1) def test_set_ship_size_wrongtype(self): - ship_field = ShipField() # Заводим объект типа ShipField + ship_field = ShipField() # Заводим объект типа ShipField ship_field.set_ship_size(1) ship_field.set_ship_size([]) @@ -46,14 +46,14 @@ class TestShipField(TestCase): 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 = 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.SHOOT) # Проверяем, что field_mode принял желаемое значение - ship_field.toggle_field_mode() # Вызываем метод, который тестируем - self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что field_mode принял желаемое значение + ship_field.toggle_field_mode() # Вызываем метод, который тестируем + self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что field_mode принял желаемое значение def test_action(self): self.fail() @@ -66,11 +66,10 @@ class TestShipField(TestCase): 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) + self.assertNotIn('r', ship_field.field) def test_shoot_empty(self): ship_field = ShipField() @@ -118,102 +117,135 @@ class TestShipField(TestCase): new_field_string = str.join(' ', ship_field.field) self.assertEqual(new_field_string, old_field_string) - def test_set_ship_size4_vertical_direction(self): - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(0) #vertikal - - ship_field.set_ship(6, 3) - - self.assertEqual(ship_field.field[63].strip(), '1') - self.assertEqual(ship_field.field[73].strip(), '1') - self.assertEqual(ship_field.field[83].strip(), '1') - self.assertEqual(ship_field.field[93].strip(), '1') - - def test_set_ship_size4_horizontal_direction(self): - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - - ship_field.set_ship(6, 3) - - self.assertEqual(ship_field.field[63].strip(), '1') - self.assertEqual(ship_field.field[64].strip(), '1') - self.assertEqual(ship_field.field[65].strip(), '1') - self.assertEqual(ship_field.field[66].strip(), '1') - - def test_set_ship_size4_vertical_direction_outofrange(self): - ship_field = ShipField() - ship_field.set_ship_size(4) - ship_field.set_ship_direction(0) - old_field_string = str.join(' ', ship_field.field) - - ship_field.set_ship(7, 3) - - new_field_string = str.join(' ', ship_field.field) - self.assertEqual(new_field_string, old_field_string) - - def test_check_possible(self): + 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) - - 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(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) + # 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() - ship_field.set_ship_direction(ShipDirection.HORIZONTAL) - self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - + ship_field = ShipField() # Заводим объект типа ShipField ship_field.set_ship_direction(ShipDirection.VERTICAL) self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) - - def test_toggle_ship_direction(self): - ship_field = ShipField() - - ship_field.toggle_ship_direction() - + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) - ship_field.toggle_ship_direction() + def test_set_ship_direction_outofrange(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_direction(1) + ship_field.set_ship_direction(-1) + ship_field.set_ship_direction(2) self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) + def test_set_ship_direction_wrongtype(self): + ship_field = ShipField() # Заводим объект типа ShipField + ship_field.set_ship_direction(1) + + ship_field.set_ship_direction(None) + ship_field.set_ship_direction([2]) + ship_field.set_ship_direction({}) + self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) + + def test_toggle_ship_direction(self): + # arrangement установка + ship_field = ShipField() + ship_field.set_ship_direction(ShipDirection.HORIZONTAL) + # action действие + ship_field.toggle_ship_direction() + # assertion проверка + self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL) + + ship_field.toggle_ship_direction() + self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL) + + 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 diff --git a/HNC/Exercises/Ship_Battle/ShipMode.py b/HNC/Exercises/Ship_Battle/ShipMode.py index 42b7342..741f104 100644 --- a/HNC/Exercises/Ship_Battle/ShipMode.py +++ b/HNC/Exercises/Ship_Battle/ShipMode.py @@ -1,15 +1,15 @@ from enum import Enum + class ShipMode(Enum): PUT = "PUT" SHOOT = "SHOOT" UNKNOWN = "UNKNOWN" - @staticmethod def from_string(raw_value): if raw_value: value = raw_value.upper() if value in ShipMode.__members__: return ShipMode[value] - return ShipMode.UNKNOWN \ No newline at end of file + return ShipMode.UNKNOWN diff --git a/HNC/Exercises/Ship_Battle/ShootResult.py b/HNC/Exercises/Ship_Battle/ShootResult.py index 1e24d4f..b5b13da 100644 --- a/HNC/Exercises/Ship_Battle/ShootResult.py +++ b/HNC/Exercises/Ship_Battle/ShootResult.py @@ -5,4 +5,4 @@ class ShootResult(Enum): EMPTY = "EMPTY" DAMAGED = "DAMAGED" KILLED = "KILLED" - UNDEFINED = "UNDEFINED" \ No newline at end of file + UNDEFINED = "UNDEFINED" diff --git a/HNC/Exercises/Ship_Battle/__pycache__/ShipField_test.cpython-311-pytest-8.1.1.pyc b/HNC/Exercises/Ship_Battle/__pycache__/ShipField_test.cpython-311-pytest-8.1.1.pyc index add44a6..7082852 100644 Binary files a/HNC/Exercises/Ship_Battle/__pycache__/ShipField_test.cpython-311-pytest-8.1.1.pyc and b/HNC/Exercises/Ship_Battle/__pycache__/ShipField_test.cpython-311-pytest-8.1.1.pyc differ diff --git a/HNC/Exercises/Ship_Battle/main.py b/HNC/Exercises/Ship_Battle/main.py index 821ddcd..24f530c 100644 --- a/HNC/Exercises/Ship_Battle/main.py +++ b/HNC/Exercises/Ship_Battle/main.py @@ -9,14 +9,15 @@ my_field = ShipField() enemy_field = ShipField() active_field = my_field +active_text = {} -def draw_field(window, field, col_offset): +def draw_field(window, field, col_offset=0, row_offset=0): buttons = [] 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.grid(column=c + col_offset, row=r) + btn.grid(column=c + col_offset, row=r + row_offset) btn.bind('', lambda e, x=r, y=c: left_button_click(buttons, x, y)) btn.bind('', right_button_click) btn.bind('', lambda e, x=r, y=c: button_enter(buttons, x, y)) @@ -54,10 +55,13 @@ def keypress_handler(e): def left_button_click(buttons, row, col): global active_field + global active_text active_field.action(row, col) colorize(active_field, buttons) + refresh_remaining_ships_label(active_field, active_text) + def right_button_click(d): global active_field @@ -66,14 +70,17 @@ def right_button_click(d): def button_enter(buttons, row, col): global active_field + global active_text if buttons == my_buttons: active_field = my_field + active_text = my_remainingShipsText enemy_field.clear_marker() my_field.target(row, col) elif buttons == enemy_buttons: active_field = enemy_field + active_text = enemy_remainingShipsText my_field.clear_marker() enemy_field.target(row, col) @@ -81,68 +88,84 @@ def button_enter(buttons, row, col): colorize(enemy_field, enemy_buttons) -def savebutton_click(): +def savebutton_click(field): file_path = filedialog.asksaveasfilename(filetypes=[("JSON files", "*.json")]) if file_path: with open(file_path, 'w') as f: - json.dump({'my_field': my_field}, f, default=ShipField.convert_to_json) + json.dump({'shipField': field}, f, default=ShipField.convert_to_json) -def loadbutton_click(): - global my_field - - file_path = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")]) +def loadbutton_click(field, buttons): + file_path = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")]) if os.path.isfile(file_path): with open(file_path) as lines: - my_field.from_json(json.load(lines)["my_field"]) + field.from_json(json.load(lines)["shipField"]) - colorize(my_field, my_buttons) + colorize(field, buttons) -def savebutton_click_enemy(): - file_path = filedialog.asksaveasfilename(filetypes=[("JSON files", "*.json")]) +def refresh_remaining_ships_label(field, stringvar): + text = '' + for i in range(1, 5): + count = field.ships.count(i) + if count > 0: + text += f'{"[]" * i}: {count}, ' - if file_path: - with open(file_path, 'w') as f: - json.dump({'enemy_field': enemy_field}, f, default=ShipField.convert_to_json) - - -def loadbutton_click_enemy(): - global enemy_field - - file_path = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")]) - - if os.path.isfile(file_path): - with open(file_path) as lines: - enemy_field.from_json(json.load(lines)["enemy_field"]) - - colorize(enemy_field, enemy_buttons) + stringvar.set(text[:-2]) window = Tk() window.title("Ship Craft!") -window.geometry('940x510') +window.geometry('1020x540') window.bind_all('', keypress_handler) -my_buttons = draw_field(window, my_field, 0) -enemy_buttons = draw_field(window, enemy_field, 11) +my_remainingShipsText = StringVar() +enemy_remainingShipsText = StringVar() -lbl = Label(window, text='', width=5, height=2) -lbl.grid(column=10, row=0) +start_column_my_field = 1 +start_row_my_field = 1 -savebutton = Button(window, text='Save', width=20, height=2, command=savebutton_click) -savebutton.grid(column=0, row=11, columnspan=4) +start_column_enemy_field = start_column_my_field + my_field.field_size + 1 +start_row_enemy_field = start_row_my_field -loadbutton = Button(window, text='Load', width=20, height=2, command=loadbutton_click) -loadbutton.grid(column=5, row=11, columnspan=4) +col_vertical_separator = start_column_my_field + my_field.field_size +row_horizontal_separator = start_row_my_field + my_field.field_size -savebutton_enemy = Button(window, text='Save_enemy', width=20, height=2, command=savebutton_click_enemy) -savebutton_enemy.grid(column=11, row=11, columnspan=4) +load_button_row = start_row_my_field + my_field.field_size + 1 -loadbutton_enemy = Button(window, text='Load_enemy', width=20, height=2, command=loadbutton_click_enemy) -loadbutton_enemy.grid(column=16, row=11, columnspan=4) +my_buttons = draw_field(window, my_field, start_column_my_field, start_row_my_field) +enemy_buttons = draw_field(window, enemy_field, start_column_enemy_field, start_row_enemy_field) + +if start_column_my_field > 0: + lbl_left_vertical = Label(window, text='', width=5, height=2) + lbl_left_vertical.grid(column=start_column_my_field - 1, row=start_row_my_field) + +lbl_center_vertical = Label(window, text='', width=5, height=2) +lbl_center_vertical.grid(column=col_vertical_separator, row=start_row_my_field) + +if start_row_my_field > 0: + lbl_upper_horizontal = Label(window, text='', width=5, height=2) + lbl_upper_horizontal.grid(column=start_column_my_field, row=start_row_my_field - 1) + +lbl_lower_horizontal = Label(window, text='', width=50, height=2, textvariable=my_remainingShipsText) +lbl_lower_horizontal.grid(column=start_column_my_field, row=row_horizontal_separator, columnspan=10) + +lbl_lower_enemy_horizontal = Label(window, text='', width=50, height=2, textvariable=enemy_remainingShipsText) +lbl_lower_enemy_horizontal.grid(column=start_column_enemy_field, row=row_horizontal_separator, columnspan=10) + +savebutton = Button(window, text='Save', width=20, height=2, command=lambda: savebutton_click(my_field)) +savebutton.grid(column=start_column_my_field, row=load_button_row, columnspan=4) + +loadbutton = Button(window, text='Load', width=20, height=2, command=lambda: loadbutton_click(my_field, my_buttons)) +loadbutton.grid(column=start_column_my_field + 6, row=load_button_row, columnspan=4) + +savebutton_enemy = Button(window, text='Save', width=20, height=2, command=lambda: savebutton_click(enemy_field)) +savebutton_enemy.grid(column=start_column_enemy_field, row=load_button_row, columnspan=4) + +loadbutton_enemy = Button(window, text='Load', width=20, height=2, command=lambda: loadbutton_click(enemy_field, enemy_buttons)) +loadbutton_enemy.grid(column=start_column_enemy_field + 6, row=load_button_row, columnspan=4) window.mainloop()