import json import os import random from tkinter import filedialog from tkinter import * from ShootResult import ShootResult from ShipField import ShipField from ShipView import ShipView from ShipMode import ShipMode from GameMode import GameMode 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_ships_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 elif game_mode == GameMode.END: game_mode = GameMode.MENU 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.configure(text="START") 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') my_view.ship_field = ShipField() enemy_view.ship_field = ShipField() 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_horizontal.grid(column=start_column_my_field, row=row_horizontal_separator, columnspan=10) lbl_lower_enemy_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.configure(text="START") start_button.grid(column=start_column_my_field, row=load_button_row + 1, 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.configure(text="BACK TO MENU") start_button.grid(column=start_column_enemy_field, row=load_button_row, columnspan=4) 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_ships_text) lbl_lower_enemy_horizontal = Label(window, text='', width=50, height=2, textvariable=enemy_view.remaining_ships_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()