Merge remote-tracking branch 'origin/main'

This commit is contained in:
Artur Savitskiy 2024-04-29 19:13:14 +02:00
commit a689e9d9c5
12 changed files with 227 additions and 53 deletions

View File

@ -0,0 +1,6 @@
from enum import Enum
class ShipDirection(Enum):
VERTICAL = "VERTICAL"
HORIZONTAL = "HORIZONTAL"
UNKNOWN = "UNKNOWN"

View File

@ -1,4 +1,7 @@
import copy
from ShootResult import ShootResult from ShootResult import ShootResult
from ShipMode import ShipMode
from ShipDirection import ShipDirection
class ShipField: class ShipField:
@ -17,9 +20,9 @@ class ShipField:
self.ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1] self.ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1]
self.field_size = 10 self.field_size = 10
self.field_mode = 0 self.field_mode = ShipMode.PUT
self.ship_size = 4 self.ship_size = 4
self.ship_direction = 0 self.ship_direction = ShipDirection.VERTICAL
def __getitem__(self, item): def __getitem__(self, item):
@ -38,27 +41,30 @@ class ShipField:
def action(self, row, col): def action(self, row, col):
self.clear_marker() self.clear_marker()
if self.field_mode == 0: if self.field_mode == ShipMode.PUT:
if self.ship_size in self.ships and self.check_possible(row, col): 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) self.set_ship(row, col)
elif self.field_mode == 1: elif self.field_mode == ShipMode.SHOOT:
self.shoot(row, col) self.shoot(row, col)
def target(self, row, col): def target(self, row, col):
self.clear_marker() self.clear_marker()
if self.field_mode == 0: if self.field_mode == ShipMode.PUT:
if self.check_possible(row, col): if self.check_possible(row, col):
if self.ship_direction == 0: if self.ship_direction == ShipDirection.VERTICAL:
for r in range(row, row + self.ship_size): for r in range(row, row + self.ship_size):
if self.ship_size in self.ships: if self.ship_size in self.ships:
self.field[r * self.field_size + col] = "p" self.field[r * self.field_size + col] = "p"
else: else:
self.field[r * self.field_size + col] = "r" self.field[r * self.field_size + col] = "r"
if self.ship_direction == 1: if self.ship_direction == ShipDirection.HORIZONTAL:
for c in range(col, col + self.ship_size): for c in range(col, col + self.ship_size):
if self.ship_size in self.ships: if self.ship_size in self.ships:
self.field[row * self.field_size + c] = "p" self.field[row * self.field_size + c] = "p"
@ -83,13 +89,13 @@ class ShipField:
if col < 0 or col > self.field_size: if col < 0 or col > self.field_size:
return return
index = row * self.field_size + col index = row * self.field_size + col
if self.ship_direction == 0: if self.ship_direction == ShipDirection.VERTICAL:
if self.field_size - row < self.ship_size: if self.field_size - row < self.ship_size:
return return
for r in range(row, row + self.ship_size): for r in range(row, row + self.ship_size):
index = r * self.field_size + col index = r * self.field_size + col
self.field[index] = "1" self.field[index] = "1"
if self.ship_direction == 1: if self.ship_direction == ShipDirection.HORIZONTAL:
if self.field_size - col < self.ship_size: if self.field_size - col < self.ship_size:
return return
for c in range(col, col + self.ship_size): for c in range(col, col + self.ship_size):
@ -99,6 +105,59 @@ class ShipField:
if self.ship_size in self.ships: if self.ship_size in self.ships:
self.ships.remove(self.ship_size) 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_direction = ShipDirection.VERTICAL
self.field[r * self.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[r * self.field_size + col] = ''
else:
break
if ship_direction == ShipDirection.UNKNOWN:
# check horizontal
for c in range(col + 1, self.field_size):
if self.check_ship(row, c):
ship_size += 1
ship_direction = ShipDirection.HORIZONTAL
self.field[row * self.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 * self.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): def shoot(self, row, col):
if row < 0 or row > self.field_size - 1: if row < 0 or row > self.field_size - 1:
return ShootResult.UNDEFINED return ShootResult.UNDEFINED
@ -113,16 +172,19 @@ class ShipField:
return ShootResult.DAMAGED return ShootResult.DAMAGED
else: else:
return ShootResult.UNDEFINED return ShootResult.UNDEFINED
def check_ship(self, row, col):
return self.field[row * self.field_size + col].strip() == '1'
def check_possible(self, row, col): def check_possible(self, row, col):
if self.ship_direction == 0: if self.ship_direction == ShipDirection.VERTICAL:
if self.field_size - row >= self.ship_size: if self.field_size - row >= self.ship_size:
for r in range(row, row + self.ship_size): for r in range(row, row + self.ship_size):
if not self.check_blocked(r, col): if not self.check_blocked(r, col):
return False return False
return True return True
if self.ship_direction == 1: if self.ship_direction == ShipDirection.HORIZONTAL:
if self.field_size - col >= self.ship_size: if self.field_size - col >= self.ship_size:
for c in range(col, col + self.ship_size): for c in range(col, col + self.ship_size):
if not self.check_blocked(row, c): if not self.check_blocked(row, c):
@ -154,24 +216,24 @@ class ShipField:
if value is None: if value is None:
return return
if type(value) is str and value.isnumeric(): if type(value) is not ShipDirection:
value = int(value) return
if type(value) is int and 0 <= value <= 1: if value != ShipDirection.UNKNOWN:
self.ship_direction = value self.ship_direction = value
def toggle_ship_direction(self): def toggle_ship_direction(self):
if self.field_mode == 0: if self.field_mode == ShipMode.PUT:
if self.ship_direction == 0: if self.ship_direction == ShipDirection.VERTICAL:
self.ship_direction = 1 self.ship_direction = ShipDirection.HORIZONTAL
else: else:
self.ship_direction = 0 self.ship_direction = ShipDirection.VERTICAL
def toggle_field_mode(self): def toggle_field_mode(self):
if self.field_mode == 0: if self.field_mode == ShipMode.PUT:
self.field_mode = 1 self.field_mode = ShipMode.SHOOT
else: else:
self.field_mode = 0 self.field_mode = ShipMode.PUT
def print_field(self): def print_field(self):
for r in range(0, self.field_size): for r in range(0, self.field_size):
@ -181,4 +243,13 @@ class ShipField:
blocked_string += str(self.check_blocked(r, c))[0] + ", " blocked_string += str(self.check_blocked(r, c))[0] + ", "
ship_string += self.field[r * self.field_size + c] + ', ' ship_string += self.field[r * self.field_size + c] + ', '
print(blocked_string[:-2] + ' ' + ship_string[:-2]) print(blocked_string[:-2] + ' ' + ship_string[:-2])
print("********************************************************************") print("********************************************************************")
@staticmethod
def convert_to_json(obj):
if isinstance(obj, ShipField):
result = copy.copy(obj.__dict__)
result['field_mode'] = obj.field_mode.value
result['ship_direction'] = obj.ship_direction.value
return result

View File

@ -1,6 +1,8 @@
from unittest import TestCase from unittest import TestCase
from ShipField import ShipField from ShipField import ShipField
from ShootResult import ShootResult from ShootResult import ShootResult
from ShipMode import ShipMode
from ShipDirection import ShipDirection
class TestShipField(TestCase): class TestShipField(TestCase):
@ -45,20 +47,16 @@ class TestShipField(TestCase):
def test_toggle_field_mode(self): def test_toggle_field_mode(self):
ship_field = ShipField() # Заводим объект типа ShipField ship_field = ShipField() # Заводим объект типа ShipField
self.assertEqual(ship_field.field_mode, 0) # Проверяем, что изначальное значение field_mode равно 0 self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что изначальное значение field_mode равно 0
ship_field.toggle_field_mode() # Вызываем метод, который тестируем ship_field.toggle_field_mode() # Вызываем метод, который тестируем
self.assertEqual(ship_field.field_mode, 1) # Проверяем, что field_mode принял желаемое значение self.assertEqual(ship_field.field_mode, ShipMode.SHOOT) # Проверяем, что field_mode принял желаемое значение
ship_field.toggle_field_mode() # Вызываем метод, который тестируем ship_field.toggle_field_mode() # Вызываем метод, который тестируем
self.assertEqual(ship_field.field_mode, 0) # Проверяем, что field_mode принял желаемое значение self.assertEqual(ship_field.field_mode, ShipMode.PUT) # Проверяем, что field_mode принял желаемое значение
def test_action(self): def test_action(self):
ship_field = ShipField() self.fail()
self.assertEqual(ship_field.action, 0)
ship_field.action()
self.assertEqual(ship_field.action, 1)
def test_target(self): def test_target(self):
self.fail() self.fail()
@ -67,10 +65,12 @@ class TestShipField(TestCase):
ship_field = ShipField() ship_field = ShipField()
ship_field.field[0] = 'p' ship_field.field[0] = 'p'
ship_field.field[ship_field.field_size - 1] = 'p' ship_field.field[ship_field.field_size - 1] = 'p'
ship_field.field[ship_field.field_size - 4] = 'r'
ship_field.clear_marker() ship_field.clear_marker()
self.assertNotIn('p', ship_field.field) self.assertNotIn('p', ship_field.field)
self.assertNotIn('r', ship_field.field)
def test_shoot_empty(self): def test_shoot_empty(self):
ship_field = ShipField() ship_field = ShipField()
@ -133,7 +133,7 @@ class TestShipField(TestCase):
def test_set_ship_size4_horizontal_direction(self): def test_set_ship_size4_horizontal_direction(self):
ship_field = ShipField() ship_field = ShipField()
ship_field.set_ship_size(4) ship_field.set_ship_size(4)
ship_field.set_ship_direction(1) ship_field.set_ship_direction(ShipDirection.HORIZONTAL)
ship_field.set_ship(6, 3) ship_field.set_ship(6, 3)
@ -154,18 +154,56 @@ class TestShipField(TestCase):
self.assertEqual(new_field_string, old_field_string) self.assertEqual(new_field_string, old_field_string)
def test_check_possible(self): def test_check_possible(self):
self.fail() ship_field = ShipField()
ship_field.set_ship_size(4)
ship_field.set_ship_direction(ShipDirection.HORIZONTAL)
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)
def test_check_blocked(self): def test_check_blocked(self):
self.fail() ship_field = ShipField()
ship_field.set_ship_size(4)
ship_field.set_ship_direction(ShipDirection.HORIZONTAL)
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)
def test_set_ship_direction(self): def test_set_ship_direction(self):
ship_field = ShipField() ship_field = ShipField()
ship_field.set_ship_direction(1) ship_field.set_ship_direction(ShipDirection.HORIZONTAL)
self.assertEqual(ship_field.ship_direction, 1) self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL)
ship_field.set_ship_direction(0) ship_field.set_ship_direction(ShipDirection.VERTICAL)
self.assertEqual(ship_field.ship_direction, 0) self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL)
def test_toggle_ship_direction(self): def test_toggle_ship_direction(self):
@ -173,9 +211,9 @@ class TestShipField(TestCase):
ship_field.toggle_ship_direction() ship_field.toggle_ship_direction()
self.assertEqual(ship_field.ship_direction, 1) self.assertEqual(ship_field.ship_direction, ShipDirection.HORIZONTAL)
ship_field.toggle_ship_direction() ship_field.toggle_ship_direction()
self.assertEqual(ship_field.ship_direction, 0) self.assertEqual(ship_field.ship_direction, ShipDirection.VERTICAL)

View File

@ -0,0 +1,5 @@
from enum import Enum
class ShipMode(Enum):
PUT = "PUT"
SHOOT = "SHOOT"

View File

@ -0,0 +1,28 @@
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(',')
# a - массив чисел из а
f.close()
return a

View File

@ -0,0 +1,7 @@
{
"my_field":{
"field": [],
"ships": [],
"field_mode": "PUT"
}
}

View File

@ -1,3 +1,4 @@
import json
from tkinter import * from tkinter import *
from ShipField import ShipField from ShipField import ShipField
@ -32,10 +33,10 @@ def colorize(field, buttons):
bg = 'black' bg = 'black'
if field.field[i] == "p": if field.field[i] == "p":
bg = 'blue' bg = 'blue'
if field.field[i] == "r":
bg = 'red'
if "+" in field.field[i]: if "+" in field.field[i]:
bg = 'orange' bg = 'orange'
if "r" in field[i]:
bg = 'red'
buttons[i].configure(bg=bg) buttons[i].configure(bg=bg)
@ -76,24 +77,41 @@ def button_enter(buttons, row, col):
colorize(my_field, my_buttons) colorize(my_field, my_buttons)
colorize(enemy_field, enemy_buttons) colorize(enemy_field, enemy_buttons)
def savebutton_click(event):
with open('test.json', 'w') as f:
json.dump({'my_field': my_field}, f, default=ShipField.convert_to_json)
def loadbutton_click(event):
data_list = []
with open('test.json') as lines:
data = json.load(lines)
for i in data['shapes']:
sh1 = create_shape(i)
data_list.append(sh1)
return data_list
window = Tk() window = Tk()
window.title("Ship Craft!") window.title("Ship Craft!")
window.geometry('940x410') window.geometry('940x510')
window.bind_all('<KeyPress>', keypress_handler) window.bind_all('<KeyPress>', keypress_handler)
my_field.toggle_ship_direction()
my_field.set_ship_size(4)
my_field.set_ship(1, 1)
my_field.toggle_ship_direction()
my_field.set_ship_size(3)
my_field.set_ship(0, 6)
my_field.set_ship_size(1)
my_field.set_ship(7, 3)
my_buttons = draw_field(window, my_field, 0) my_buttons = draw_field(window, my_field, 0)
enemy_buttons = draw_field(window, enemy_field, 11) enemy_buttons = draw_field(window, enemy_field, 11)
lbl = Label(window, text='', width=5, height=2) lbl = Label(window, text='', width=5, height=2)
lbl.grid(column=10, row=0) lbl.grid(column=10, row=0)
savebutton = Button(window, text='Save', width=20, height=2)
savebutton.bind('<Button-1>', savebutton_click)
savebutton.grid(column=0, row=11, columnspan=4)
loadbutton = Button(window, text='Load', width=20, height=2)
loadbutton.bind('<Button-1>', loadbutton_click)
loadbutton.grid(column=5, row=11, columnspan=4)
window.mainloop() window.mainloop()

View File

@ -0,0 +1 @@
{"shapes": {"field": ["1", "1", "1", "1", " ", " ", " ", " ", "", "1", "", "", " ", " ", " ", "1", " ", "", "", "1", "", "", "", "", "", "", "", "1", "", "", "1", "", "", "", "", "1", "", "", "", "", "1", "", "", "1", "", "", "", "1", " ", " ", "1", "", "", "1", " ", " ", " ", "", "", "", " ", "", "", "", " ", " ", "", "", "", "", " ", "1", "", " ", " ", " ", " ", " ", "", "", " ", "1", "", " ", " ", " ", " ", " ", " ", " ", " ", "1", "", " ", " ", " ", "r", "", "1", "1"], "ships": [], "field_size": 10, "field_mode": "PUT", "ship_size": 1, "ship_direction": "VERTICAL"}}