hnc-eduard/HNS/Excercises/ShipCraft/main.py

305 lines
9.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from tkinter import *
from enum import Enum
my_buttons = []
enemy_buttons = []
field_size = 10
active_field = 0
ship_size_left = 4
ship_direction_left = 0
field_mode_left = 0
ship_size_right = 4
ship_direction_right = 0
field_mode_right = 0
empty_field = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
my_field = list(empty_field)
enemy_field = list(empty_field)
# 1. Определите перечисление (Enum) ShootResult со следующими значениями:
# EMPTY (мимо), DAMAGED (ранен), KILLED (убит), UNDEFINED (действие не определено)
class ShootResult(Enum):
EMPTY = "EMPTY"
DAMAGED = "DAMAGED"
KILLED = "KILLED"
UNDEFINED = "UNDEFINED"
def set_ship(field, row, col, ship_size, direction):
if row < 0 or row > field_size:
return
if col < 0 or col > field_size:
return
index = row * field_size + col
if direction == 0:
if field_size - row < ship_size:
return
for r in range(row, row + ship_size):
index = r * field_size + col
field[index] = "1"
if direction == 1:
if field_size - col < ship_size:
return
for c in range(col, col + ship_size):
index = row * field_size + c
field[index] = "1"
def shoot(field, row, col):
if row < 0 or row > field_size - 1:
return ShootResult.UNDEFINED
if col < 0 or col > field_size - 1:
return ShootResult.UNDEFINED
index = row * field_size + col
if (field[index]).strip() == "":
field[index] = "0"
return ShootResult.EMPTY
elif (field[index]).strip() == "1":
field[index] = "\\"
return ShootResult.DAMAGED
else:
return ShootResult.UNDEFINED
def draw_field(window, field, col_offset):
buttons = []
for r in range(0, field_size):
for c in range(0, field_size):
index = r * field_size + c
btn = Button(window, text='', width=5, height=2)
btn.grid(column=c + col_offset, row=r)
btn.bind('<Button-1>', lambda e, x=r, y=c: left_button_click(field, buttons, x, y))
btn.bind('<Button-3>', right_button_click)
btn.bind('<Enter>', lambda e, x=r, y=c: button_enter(field, buttons, x, y))
buttons.append(btn)
colorize(field, buttons)
return buttons
def colorize(field, buttons):
for i in range(len(field)):
bg = "white"
if field[i] == "1":
bg = 'pink'
if field[i] == "\\":
bg = 'red'
if field[i] == "0":
bg = 'black'
if field[i] == "p":
bg = 'blue'
buttons[i].configure(bg=bg)
def keypress_handler(e):
global ship_size_left
global field_mode_left
global ship_size_right
global field_mode_right
if e.keysym.isnumeric():
number = int(e.keysym)
if 1 <= number <= 4:
if active_field == 0:
ship_size_left = number
else:
ship_size_right = number
else:
if e.keysym == 'm':
if active_field == 0:
field_mode = field_mode_left
else:
field_mode = field_mode_right
if field_mode == 0:
field_mode = 1
else:
field_mode = 0
if active_field == 0:
field_mode_left = field_mode
else:
field_mode_right = field_mode
def left_button_click(field, buttons, row, col):
global ship_size_left
global ship_direction_left
global ship_size_right
global ship_direction_right
if active_field == 0:
field_mode = field_mode_left
ship_size = ship_size_left
ship_direction = ship_direction_left
else:
field_mode = field_mode_right
ship_size = ship_size_right
ship_direction = ship_direction_right
if field_mode == 0:
if check_possible(field, row, col, ship_size, ship_direction):
set_ship(field, row, col, ship_size, ship_direction)
elif field_mode == 1:
shoot(field, row, col)
colorize(field, buttons)
def right_button_click(d):
global ship_direction_left
global ship_direction_right
global field_mode_left
global field_mode_right
if active_field == 0:
field_mode = field_mode_left
ship_direction = ship_direction_left
else:
field_mode = field_mode_right
ship_direction = ship_direction_right
if field_mode == 0:
if ship_direction == 0:
ship_direction = 1
else:
ship_direction = 0
if active_field == 0:
ship_direction_left = ship_direction
else:
ship_direction_right = ship_direction
def button_enter(field, buttons, row, col):
global active_field
global ship_direction_left
global ship_direction_right
global ship_size_left
global ship_size_right
global field_mode_left
global field_mode_right
if buttons == my_buttons:
active_field = 0
elif buttons == enemy_buttons:
active_field = 1
if active_field == 0:
field_mode = field_mode_left
ship_direction = ship_direction_left
ship_size = ship_size_left
other_field = enemy_field
other_buttons = enemy_buttons
else:
field_mode = field_mode_right
ship_direction = ship_direction_right
ship_size = ship_size_right
other_field = my_field
other_buttons = my_buttons
colorize(other_field, other_buttons)
if check_possible(field, row, col,ship_size, ship_direction):
if ship_direction == 0:
for r in range(row, row + ship_size):
field[r * field_size + col] = "p"
if ship_direction == 1:
for c in range(col, col + ship_size):
field[row * field_size + c] = "p"
colorize(field, buttons)
def check_possible(field, row, col, ship_size, ship_direction):
# Функция должна возвращать True, если можно поставить сюда корабль,
# в противном случае - False
if ship_direction == 0:
# Здесь мы знаем, что корабль помещается на поле.
if field_size - row >= ship_size:
# Теперь нужно проверить, не заблокировано ли какое-то из полей,
for r in range(row, row + ship_size):
if not check_blocked(field, r, col):
return False
return True
if ship_direction == 1:
if field_size - col >= ship_size:
for c in range(col, col + ship_size):
if not check_blocked(field, row, c):
return False
return True
return False
def check_blocked(field, row, col):
# Функция возвращает True, если все клетки вокруг клетки с координатами row, col
# либо находятся за пределами поля, либо в них нет корабля/они пустые
for r in range(row - 1, row + 2):
for c in range(col - 1, col + 2):
if 0 <= r < field_size and 0 <= c < field_size:
cell = (field[r * field_size + c]).strip()
if cell != '' and cell != 'p':
return False
return True
window = Tk()
window.title("Ship Craft!")
window.geometry('940x410')
window.bind_all('<KeyPress>', keypress_handler)
set_ship(my_field, 1, 1, 4, 1)
set_ship(my_field,0, 6, 3, 0)
set_ship(my_field, 7, 3, 1, 0)
my_buttons = draw_field(window, my_field, 0)
enemy_buttons = draw_field(window, enemy_field, 11)
print(len(my_buttons))
print(len(enemy_buttons))
lbl = Label(window, text='', width=5, height=2)
lbl.grid(column=10, row=0)
#window.mainloop()
for r in range(0, field_size):
blocked_string = ""
ship_string = ""
for c in range(0, field_size):
blocked_string += str(check_blocked(my_field, r, c))[0] + ", "
ship_string += my_field[r * field_size + c] + ', '
print(blocked_string[:-2] + ' ' + ship_string[:-2])
print("********************************************************************")
for r in range(0, field_size):
possible_string = ""
impossible_string = ""
for c in range(0, field_size):
possible_string += str(check_possible(my_field, r, c))[0] + ", "
impossible_string += my_field[r * field_size + c] + ', '
print(possible_string[:-2] + ' ' + impossible_string[:-2])