mirror of
https://github.com/AlekseyLobanov/PythonDevelopment2021.git
synced 2026-01-11 12:42:01 +03:00
120 lines
3.8 KiB
Python
120 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import random
|
|
import time
|
|
from functools import partial
|
|
|
|
import tkinter as tk
|
|
from tkinter import messagebox as mb
|
|
|
|
|
|
GAME_SIZE = 4
|
|
POSSIBLE_MOVES = [(1, 0), (-1, 0), (0, 1), (0, -1)]
|
|
INIT_RANDOM_STEPS = 5
|
|
NEW_GAME_RANDOM_STEPS = 1000
|
|
|
|
|
|
def get_val_pos(state, val):
|
|
for i in range(GAME_SIZE):
|
|
for j in range(GAME_SIZE):
|
|
if state[i][j] == val:
|
|
return i, j
|
|
|
|
|
|
def swap_cells(state, first, second):
|
|
state[first[0]][first[1]], state[second[0]][second[1]] = (
|
|
state[second[0]][second[1]],
|
|
state[first[0]][first[1]],
|
|
)
|
|
|
|
|
|
def get_game_state(steps=0):
|
|
res = [[0 for i in range(GAME_SIZE)] for j in range(GAME_SIZE)]
|
|
for i in range(GAME_SIZE):
|
|
for j in range(4):
|
|
if i == GAME_SIZE - 1 and j == GAME_SIZE - 1:
|
|
# empty cell
|
|
continue
|
|
res[i][j] = i * GAME_SIZE + j + 1
|
|
|
|
empty_pos = get_val_pos(res, 0)
|
|
for step_ind in range(steps):
|
|
possbile_next_cells = []
|
|
for delta_x, delta_y in POSSIBLE_MOVES:
|
|
next_cell = (empty_pos[0] + delta_x, empty_pos[1] + delta_y)
|
|
if 0 <= next_cell[0] < GAME_SIZE and 0 <= next_cell[1] < GAME_SIZE:
|
|
possbile_next_cells.append(next_cell)
|
|
next_cell = random.choice(possbile_next_cells)
|
|
# swap == one move
|
|
swap_cells(res, empty_pos, next_cell)
|
|
empty_pos = next_cell
|
|
return res
|
|
|
|
|
|
class Application(tk.Frame):
|
|
def __init__(self, master=None):
|
|
super().__init__(master)
|
|
tk.Grid.rowconfigure(self.master, 0, weight=1)
|
|
tk.Grid.columnconfigure(self.master, 0, weight=1)
|
|
self.grid(sticky="news", column=0, row=0)
|
|
self.createWidgets()
|
|
|
|
self.rowconfigure(0, weight=1)
|
|
for i in range(1, 5):
|
|
self.rowconfigure(i, weight=3)
|
|
for i in range(4):
|
|
self.columnconfigure(i, weight=1)
|
|
|
|
def createWidgets(self):
|
|
self.new_bt = tk.Button(self, text="New", command=self.process_new_game)
|
|
self.exit_bt = tk.Button(self, text="Exit", command=self.quit)
|
|
self.new_bt.grid(row=0, column=0, columnspan=2)
|
|
self.exit_bt.grid(row=0, column=2, columnspan=2)
|
|
self.game_buttons = self.create_game_buttons()
|
|
self.game_state = get_game_state(INIT_RANDOM_STEPS)
|
|
self.render_current_state()
|
|
|
|
def create_game_buttons(self):
|
|
res = {}
|
|
for i in range(GAME_SIZE * GAME_SIZE):
|
|
btn_value = i + 1
|
|
btn = tk.Button(
|
|
self,
|
|
text=str(btn_value),
|
|
command=partial(self.process_number_press, btn_value),
|
|
)
|
|
res[btn_value] = btn
|
|
return res
|
|
|
|
def process_number_press(self, val):
|
|
val_pos = get_val_pos(self.game_state, val)
|
|
empty_pos = get_val_pos(self.game_state, 0)
|
|
delta = (empty_pos[0] - val_pos[0], empty_pos[1] - val_pos[1])
|
|
if delta not in POSSIBLE_MOVES:
|
|
return
|
|
swap_cells(self.game_state, val_pos, empty_pos)
|
|
self.render_current_state()
|
|
if self.game_state == get_game_state(0):
|
|
mb.showinfo(title="Info", message="You win!")
|
|
self.game_state = get_game_state(NEW_GAME_RANDOM_STEPS)
|
|
self.render_current_state()
|
|
|
|
def process_new_game(self):
|
|
self.game_state = get_game_state(NEW_GAME_RANDOM_STEPS)
|
|
self.render_current_state()
|
|
|
|
def render_current_state(self):
|
|
for i in range(4):
|
|
for j in range(4):
|
|
btn_value = self.game_state[i][j]
|
|
if btn_value == 0:
|
|
continue
|
|
btn = self.game_buttons[btn_value]
|
|
btn.grid(row=i + 1, column=j, sticky="news")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = Application()
|
|
app.master.title("15-шки")
|
|
app.mainloop()
|