|
|
# -*- encoding: utf-8 -*-
|
|
|
"""
|
|
|
@Author: packy945
|
|
|
@FileName: main.py
|
|
|
@DateTime: 2023/5/11 11:34
|
|
|
@SoftWare: PyCharm
|
|
|
"""
|
|
|
from tkinter import simpledialog
|
|
|
|
|
|
from data import *
|
|
|
import tkinter as tk
|
|
|
import tkinter.messagebox
|
|
|
from collections import Counter
|
|
|
import random
|
|
|
from itertools import permutations
|
|
|
from TreeNode import *
|
|
|
from setting import *
|
|
|
from tkinter import *
|
|
|
from PIL import ImageTk
|
|
|
from PIL import Image as imim
|
|
|
import sys
|
|
|
|
|
|
|
|
|
sz = []
|
|
|
A = Aexp([0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0])
|
|
|
img_open = []
|
|
|
img_png = []
|
|
|
|
|
|
|
|
|
def set_canvas_button(button_pot: list, button_photo: ImageTk.PhotoImage, command, tags=None, bg="#3E97C1"):
|
|
|
button = C.create_image(button_pot[0], button_pot[1], anchor=tk.NW, image=button_photo)
|
|
|
C.tag_bind(button, "<Button-1>", command)
|
|
|
|
|
|
|
|
|
def to_image(path, resize=None) -> ImageTk.PhotoImage:
|
|
|
if resize:
|
|
|
return ImageTk.PhotoImage(imim.open(path).resize(resize))
|
|
|
return ImageTk.PhotoImage(imim.open(path))
|
|
|
|
|
|
|
|
|
def change_card():
|
|
|
card = []
|
|
|
for n in tree.Node:
|
|
|
if n[1] == 'Value':
|
|
|
if n[5] == 1:
|
|
|
card.append([n[6], 'A'])
|
|
|
else:
|
|
|
card.append([n[6], str(n[5])])
|
|
|
# print(card)
|
|
|
if len(card) == 4:
|
|
|
show(card)
|
|
|
else:
|
|
|
tk.messagebox.showinfo('', '无法显示卡牌')
|
|
|
|
|
|
|
|
|
def TorF(flag):
|
|
|
'''
|
|
|
显示答案是否正确
|
|
|
:param flag: 答案是否正确
|
|
|
:return:
|
|
|
'''
|
|
|
if flag == 1:
|
|
|
clo1 = to_image(sys.path[0] + "/./images/对-高亮.png", (30, 30))
|
|
|
clo2 = to_image(sys.path[0] + "/./images/错.png", (30, 30))
|
|
|
clo3 = to_image(sys.path[0] + '/./images/chushi.png', (30, 30))
|
|
|
elif flag == 0:
|
|
|
clo1 = to_image(sys.path[0] + "/./images/对.png", (30, 30))
|
|
|
clo2 = to_image(sys.path[0] + "/./images/错.png", (30, 30))
|
|
|
clo3 = to_image(sys.path[0] + '/./images/chushi.png', (30, 30))
|
|
|
else:
|
|
|
clo1 = to_image(sys.path[0] + "/./images/对.png", (30, 30))
|
|
|
clo2 = to_image(sys.path[0] + "/./images/错-高亮.png", (30, 30))
|
|
|
clo3 = to_image(sys.path[0] + '/./images/chushi.png', (30, 30))
|
|
|
|
|
|
label3 = tk.Label(window, image=clo1, relief="sunken", borderwidth=0)
|
|
|
label4 = tk.Label(window, image=clo2, relief="sunken", borderwidth=0)
|
|
|
label5 = tk.Label(window, image=clo3, relief="sunken", borderwidth=0)
|
|
|
label3.image = clo1
|
|
|
label4.image = clo2
|
|
|
label5.image = clo3
|
|
|
|
|
|
if flag == 1:
|
|
|
label3.place(x=ENTRY_WIDTH + 200, y=CARD_CANVAS_HEIGHT + 18, width=30, height=30)
|
|
|
elif flag == 0:
|
|
|
label5.place(x=ENTRY_WIDTH + 200, y=CARD_CANVAS_HEIGHT + 18, width=30, height=30)
|
|
|
else:
|
|
|
label4.place(x=ENTRY_WIDTH + 200, y=CARD_CANVAS_HEIGHT + 18, width=30, height=30)
|
|
|
# label3.place(x=ENTRY_WIDTH + 200, y=CARD_CANVAS_HEIGHT + 18, width=30, height=15)
|
|
|
# label4.place(x=ENTRY_WIDTH + 200, y=CARD_CANVAS_HEIGHT + 8 + 30, width=30, height=15)
|
|
|
|
|
|
|
|
|
def ans_cal(ans=None):
|
|
|
"""
|
|
|
绘制结果框
|
|
|
:param ans:
|
|
|
:return:
|
|
|
"""
|
|
|
if not ans:
|
|
|
label2 = tk.Label(window, text='= ?', font=('楷体', 18, 'bold'), width=30, height=10, background="#4acb69",
|
|
|
# 设置填充区距离、边框宽度和其样式(凹陷式)
|
|
|
borderwidth=0, relief="raised")
|
|
|
else:
|
|
|
label2 = tk.Label(window, text=f'={ans}', font=('楷体', 18, 'bold'), width=30, height=10, background="#4acb69",
|
|
|
# 设置填充区距离、边框宽度和其样式(凹陷式)
|
|
|
borderwidth=0, relief="raised")
|
|
|
label2.place(x=ENTRY_WIDTH + LEFT_PADDING + 25, y=CARD_CANVAS_HEIGHT + 15, width=100, height=ENTRY_HEIGHT)
|
|
|
|
|
|
|
|
|
def init():
|
|
|
ans_cal()
|
|
|
all_ans["state"] = 'disable'
|
|
|
entry.delete(0, "end")
|
|
|
F.clear()
|
|
|
TorF(0)
|
|
|
|
|
|
|
|
|
# 展示卡牌
|
|
|
def show_card():
|
|
|
'''
|
|
|
随机展示四张卡片
|
|
|
:return:
|
|
|
'''
|
|
|
global sz # 全局变量存放点数
|
|
|
sz = []
|
|
|
# 清空卡牌列表
|
|
|
init()
|
|
|
# 清空中间的表达式输入串Aexp, 同时清空中间的表达式输入框、结果显示框和结果正确与错误标志
|
|
|
kp_list = []
|
|
|
size_list = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
|
|
|
col_list = ["Club", "Diamond", "Spade", "Heart"]
|
|
|
sz_list = ['a', 'j', 'q', 'k']
|
|
|
|
|
|
for i in range(4):
|
|
|
kp_list.append([random.choice(col_list), random.choice(size_list)]) # 随机生成花色以及点数
|
|
|
sz.append([kp_list[i][0], kp_list[i][1], kp_list[i][1]])
|
|
|
if kp_list[i][-1] == '1':
|
|
|
kp_list[i][-1] = random.choice(sz_list)
|
|
|
sz[i][2] = kp_list[i][-1]
|
|
|
|
|
|
show(kp_list)
|
|
|
global A
|
|
|
A.refresh(sz[0], sz[1], sz[2], sz[3])
|
|
|
C.update()
|
|
|
|
|
|
|
|
|
def show(kp_list):
|
|
|
# 根据花色以及点数显示卡牌
|
|
|
global img_open, img_png
|
|
|
img_open = []
|
|
|
img_png = []
|
|
|
C.delete('card')
|
|
|
i = 150 # 卡牌位置偏移量
|
|
|
for k in range(4):
|
|
|
img_open.append(
|
|
|
imim.open(sys.path[0] + "/./card/" + kp_list[k][0] + "/" + kp_list[k][0] + kp_list[k][1] + '.png').resize(
|
|
|
(int((CARD_CANVAS_HEIGHT - 10) * 0.6) + 10, CARD_CANVAS_HEIGHT - 10)))
|
|
|
img_png.append(ImageTk.PhotoImage(img_open[k]))
|
|
|
C.create_image(50 + i, 100, image=img_png[k], tags="card")
|
|
|
i += int((CARD_CANVAS_HEIGHT - 10) * 0.6) + 80
|
|
|
C.update()
|
|
|
|
|
|
|
|
|
# 展示结果
|
|
|
def show_result(ss, sz):
|
|
|
'''
|
|
|
展示计算结果
|
|
|
:param ss: 输入框中的表达式
|
|
|
:param sz: 题中给的卡牌数字
|
|
|
:return:
|
|
|
'''
|
|
|
numbers = [int(number) for number in re.findall(r'\d+', ss)]
|
|
|
a = Counter(numbers)
|
|
|
# char_list = [] # 用于存放算式中的数字
|
|
|
# for i in range(len(ss)):
|
|
|
# if '0' < ss[i] <= '9':
|
|
|
# char_list.append(ss[i])
|
|
|
# a = Counter(char_list) # 计数函数Counter
|
|
|
if sz:
|
|
|
b = Counter([sz[0][1], sz[1][1], sz[2][1], sz[3][1]])
|
|
|
try:
|
|
|
ans = eval(ss)
|
|
|
except:
|
|
|
tk.messagebox.showinfo('', '表达式不可运算')
|
|
|
else:
|
|
|
ans_cal(int(ans))
|
|
|
# 设置颜色
|
|
|
if ans == 24:
|
|
|
TorF(1)
|
|
|
else:
|
|
|
TorF(-1)
|
|
|
|
|
|
|
|
|
# 展示一个可行算式
|
|
|
def show_answer():
|
|
|
# 自动求解
|
|
|
if len(sz) != 4:
|
|
|
tk.messagebox.showinfo('', '未出题')
|
|
|
return
|
|
|
|
|
|
answer = (A.answer[0], A.Color[0])
|
|
|
# print()
|
|
|
# print(answer)
|
|
|
if A.num == 0:
|
|
|
entry.delete(0, "end")
|
|
|
tk.messagebox.showinfo('', '无法得出24点')
|
|
|
else:
|
|
|
entry.delete(0, "end")
|
|
|
entry.insert("end", answer[0])
|
|
|
F.show_tree(answer)
|
|
|
if A.num > 1:
|
|
|
all_ans["state"] = 'normal'
|
|
|
else:
|
|
|
all_ans["state"] = 'disable'
|
|
|
|
|
|
|
|
|
def show_next():
|
|
|
global A
|
|
|
A.Aexp_cur += 1
|
|
|
answer = (A.answer[A.Aexp_cur], A.Color[A.Aexp_cur])
|
|
|
entry.delete(0, "end")
|
|
|
entry.insert("end", answer[0])
|
|
|
F.show_tree(answer)
|
|
|
|
|
|
if A.Aexp_cur == A.num - 1:
|
|
|
all_ans["state"] = 'disable'
|
|
|
tk.messagebox.showinfo('', '已显示所有答案')
|
|
|
|
|
|
|
|
|
# 显示所有答案,通过一个新窗口
|
|
|
def show_all():
|
|
|
global Aexp_cur
|
|
|
|
|
|
answer = Aexp(int(sz[0][1]), int(sz[1][1]), int(sz[2][1]), int(sz[3][1]))
|
|
|
# Tree_all = []
|
|
|
# for item in answer:
|
|
|
# Tree_all.append(Decomposition(item))
|
|
|
root = tk.Tk()
|
|
|
# root.geometry('500x300')
|
|
|
width = 500
|
|
|
height = 300
|
|
|
screen_width = window.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小
|
|
|
screen_height = window.winfo_screenheight()
|
|
|
x = int((screen_width - width) / 2)
|
|
|
y = int((screen_height - height) / 2) - 40
|
|
|
size = '{}x{}+{}+{}'.format(width, height, x, y)
|
|
|
root.geometry(size)
|
|
|
b1 = tk.Scrollbar(root, width=40)
|
|
|
# b1.place(x=410,y=200)
|
|
|
b1.pack(side=tk.RIGHT, fill=tk.Y)
|
|
|
b2 = tk.Listbox(root, yscrollcommand=b1.set, width=100)
|
|
|
for i in range(len(answer)):
|
|
|
b2.insert(tk.END, answer[i])
|
|
|
b2.pack(side=tk.LEFT, fill=tk.BOTH)
|
|
|
# b2.place(x=520,y=100)
|
|
|
b1.config(command=b2.yview)
|
|
|
root.mainloop()
|
|
|
|
|
|
|
|
|
def Buts():
|
|
|
global all_ans
|
|
|
global but5
|
|
|
but_image = to_image(sys.path[0] + "/./images/chuti.png", (TOP_BUTTON_WIDTH, TOP_BUTTON_HEIGHT))
|
|
|
but = Button(window, image=but_image, command=show_card, bd=0, relief="solid", bg="#141414", highlightthickness=0)
|
|
|
but.image = but_image
|
|
|
but.place(x=CARD_CANVAS_WIDTH + TOP_BUTTON_WIDTH + 50, y=40, width=TOP_BUTTON_WIDTH, height=TOP_BUTTON_HEIGHT)
|
|
|
|
|
|
but2_image = to_image(sys.path[0] + "/./images/换牌.png", (TOP_BUTTON_WIDTH, TOP_BUTTON_HEIGHT))
|
|
|
but2 = tk.Button(window, image=but2_image, command=show_card, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
but2.image = but2_image
|
|
|
but2.place(x=CARD_CANVAS_WIDTH + TOP_BUTTON_WIDTH + 50, y=70 + TOP_BUTTON_HEIGHT, width=TOP_BUTTON_WIDTH,
|
|
|
height=TOP_BUTTON_HEIGHT, )
|
|
|
|
|
|
but4_image = to_image(sys.path[0] + "/./images/计算.png", (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but4 = tk.Button(window, image=but4_image, command=lambda: show_result(entry.get(), sz), bd=0, relief="solid",
|
|
|
bg="#141414", highlightthickness=0)
|
|
|
but4.place(x=ENTRY_WIDTH + 245, y=CARD_CANVAS_HEIGHT + 15, width=MIDDLE_BUTTON_WIDTH, height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but4.image = but4_image
|
|
|
|
|
|
##报错
|
|
|
but3_image = to_image(sys.path[0] + "/./images/自动求解.png", (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but3 = tk.Button(window, image=but3_image, command=lambda: show_answer(), bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
but3.place(x=60, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but3.image = but3_image
|
|
|
|
|
|
all_ans_image = to_image(sys.path[0] + "/./images/所有答案.png", (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
all_ans = tk.Button(window, image=all_ans_image, command=lambda: show_next(), bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, state='disable')
|
|
|
all_ans.place(x=60 + MIDDLE_BUTTON_WIDTH * 2 + 50 * 2, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
all_ans.image = all_ans_image
|
|
|
|
|
|
##报错
|
|
|
but5_image = to_image(sys.path[0] + "/./images/画树.png", (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but5 = tk.Button(window, image=but5_image, command=lambda: F.show_tree(entry.get()), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
|
|
|
but5.place(x=60 + MIDDLE_BUTTON_WIDTH + 50, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but5.image = but5_image
|
|
|
|
|
|
but6_image = to_image(sys.path[0] + '/./images/生成表达式.png', (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but6 = tk.Button(window, image=but6_image, command=lambda: expressions(), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
but6.place(x=60 + MIDDLE_BUTTON_WIDTH * 3 + 50 * 3, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but6.image = but6_image
|
|
|
|
|
|
##报错
|
|
|
but7_image = to_image(sys.path[0] + '/./images/生成语法树.png', (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but7 = tk.Button(window, image=but7_image, command=lambda: F.show_tree(expression_tree()), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
but7.place(x=60 + MIDDLE_BUTTON_WIDTH * 4 + 50 * 4, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but7.image = but7_image
|
|
|
|
|
|
but8_image = to_image(sys.path[0] + '/./images/一致性检查.png', (MIDDLE_BUTTON_WIDTH, MIDDLE_BUTTON_HEIGHT))
|
|
|
but8 = tk.Button(window, image=but8_image, command=lambda: examine(), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
but8.place(x=60 + MIDDLE_BUTTON_WIDTH * 5 + 50 * 5, y=CARD_CANVAS_HEIGHT + 65, width=MIDDLE_BUTTON_WIDTH,
|
|
|
height=MIDDLE_BUTTON_HEIGHT, )
|
|
|
but8.image = but8_image
|
|
|
|
|
|
|
|
|
def left2(event):
|
|
|
# 查找鼠标左键按下时位置是否在某个牌上
|
|
|
# print(event.x, event.y)
|
|
|
# if not A.card
|
|
|
left = []
|
|
|
right = []
|
|
|
i = 150
|
|
|
for j in range(4):
|
|
|
left.append(i)
|
|
|
right.append(i + (CARD_CANVAS_HEIGHT - 10) * 0.6)
|
|
|
i += int((CARD_CANVAS_HEIGHT - 10) * 0.6) + 80
|
|
|
up = 5
|
|
|
down = CARD_CANVAS_HEIGHT - 10
|
|
|
# 添加数值节点
|
|
|
if F.mode == 2:
|
|
|
for cur in range(4):
|
|
|
if up <= event.y <= down and right[cur] >= event.x >= left[cur]:
|
|
|
# 检查数值节点是否已存在
|
|
|
a = []
|
|
|
b = []
|
|
|
for card in A.card:
|
|
|
a.append([card[0], int(card[1])])
|
|
|
for node in tree.Node:
|
|
|
if node[1] == 'Value':
|
|
|
b.append([node[6], node[5]])
|
|
|
c = a.copy()
|
|
|
for x in b:
|
|
|
for i in range(len(c)):
|
|
|
try:
|
|
|
c[i]
|
|
|
except:
|
|
|
break
|
|
|
|
|
|
if x[0] == c[i][0] and x[1] == c[i][1]:
|
|
|
del c[i]
|
|
|
flag = 0
|
|
|
for l in c:
|
|
|
# 若所选card还没有对应的节点,则新建一个数值节点
|
|
|
if not flag and l[0] == A.card[cur][0] and l[1] == int(A.card[cur][1]):
|
|
|
tree.Node.append(
|
|
|
[len(tree.Node), 'Value', None, None, None, int(A.card[cur][1]), A.card[cur][0]])
|
|
|
print(tree.Node)
|
|
|
flag = 1
|
|
|
|
|
|
if not flag:
|
|
|
# 若所选card已经存在,则进行警告
|
|
|
tk.messagebox.showinfo('', '所选card已存在')
|
|
|
# 操作完成,进行复位
|
|
|
F.mode = 0
|
|
|
F.tips = ''
|
|
|
tree.remark()
|
|
|
F.draw()
|
|
|
# 改变运算输入的第二步
|
|
|
elif F.mode == 6:
|
|
|
for cur in range(4):
|
|
|
# 若单击了一张card
|
|
|
if up <= event.y <= down and right[cur] >= event.x >= left[cur]:
|
|
|
|
|
|
# 标记的节点序号
|
|
|
mark = -1
|
|
|
for i in range(len(tree.mark)):
|
|
|
if tree.mark[i] == 1:
|
|
|
mark = i
|
|
|
|
|
|
flag = 0
|
|
|
|
|
|
for now in range(len(tree.Node)):
|
|
|
# 若单击的card已经存在一个数值节点
|
|
|
if tree.Node[now][6] == A.card[cur][0] and tree.Node[now][5] == int(A.card[cur][1]):
|
|
|
# 则将这两个数值节点进行交换
|
|
|
tree.Node[now][5] = tree.Node[mark][5]
|
|
|
tree.Node[now][6] = tree.Node[mark][6]
|
|
|
|
|
|
tree.Node[mark][5] = int(A.card[cur][1])
|
|
|
tree.Node[mark][6] = A.card[cur][0]
|
|
|
flag = 1
|
|
|
|
|
|
if not flag:
|
|
|
# 若单击的card没有存在数值节点,则将该节点改为这张card
|
|
|
tree.Node[mark][5] = int(A.card[cur][1])
|
|
|
tree.Node[mark][6] = A.card[cur][0]
|
|
|
# 操作完毕,进行复位
|
|
|
F.mode = 0
|
|
|
F.tips = ''
|
|
|
tree.remark()
|
|
|
F.draw()
|
|
|
|
|
|
|
|
|
class Frame_Tree:
|
|
|
def __init__(self, window):
|
|
|
self.opt = '+'
|
|
|
self.mode = 0
|
|
|
|
|
|
'''
|
|
|
当前操作:
|
|
|
0 无
|
|
|
1 添加运算节点
|
|
|
2 添加数值节点
|
|
|
3 改变运算输入
|
|
|
4 改变节点运算
|
|
|
5 数值节点交换
|
|
|
'''
|
|
|
self.tips = ''
|
|
|
self.Tree_cv = C
|
|
|
add_image = to_image(sys.path[0] + "/./images/+.png", (40, 40))
|
|
|
self.opt1 = tk.Button(window, image=add_image, command=lambda: self.set_opt(1), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
self.opt1.image = add_image
|
|
|
self.opt1.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 200, width=40, height=40)
|
|
|
|
|
|
jian_image = to_image(sys.path[0] + "/./images/-.png", (40, 40))
|
|
|
self.opt2 = tk.Button(window, image=jian_image, command=lambda: self.set_opt(2), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
self.opt2.place(x=TREE_CANVAS_WIDTH - 10, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 200, width=40, height=40)
|
|
|
self.opt2.image = jian_image
|
|
|
|
|
|
chen_image = to_image(sys.path[0] + "/./images/X.png", (40, 40))
|
|
|
self.opt3 = tk.Button(window, image=chen_image, command=lambda: self.set_opt(3), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
self.opt3.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 250, width=40, height=40)
|
|
|
self.opt3.image = chen_image
|
|
|
|
|
|
chu_image = to_image(sys.path[0] + "/./images/÷.png", (40, 40))
|
|
|
self.opt4 = tk.Button(window, image=chu_image, command=lambda: self.set_opt(4), bd=0, relief="solid",
|
|
|
bg="#141414",
|
|
|
highlightthickness=0)
|
|
|
self.opt4.place(x=TREE_CANVAS_WIDTH - 10, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 250, width=40, height=40)
|
|
|
self.opt4.image = chu_image
|
|
|
|
|
|
self.set_opt(1)
|
|
|
|
|
|
dy = 150
|
|
|
|
|
|
bot_image = to_image(sys.path[0] + "/./images/添加运算节点.png", (100, 50))
|
|
|
bot1 = tk.Button(window, image=bot_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.add_opt())
|
|
|
bot1.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 150 + dy, width=100, height=50)
|
|
|
bot1.image = bot_image
|
|
|
|
|
|
bot2_image = to_image(sys.path[0] + "/./images/添加数值节点.png", (100, 50))
|
|
|
bot2 = tk.Button(window, image=bot2_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.add_number())
|
|
|
bot2.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 200 + dy, width=100, height=50)
|
|
|
bot2.image = bot2_image
|
|
|
|
|
|
bot3_image = to_image(sys.path[0] + "/./images/改变运算输入.png", (100, 50))
|
|
|
bot3 = tk.Button(window, image=bot3_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.change_num())
|
|
|
bot3.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 250 + dy, width=100, height=50)
|
|
|
bot3.image = bot3_image
|
|
|
|
|
|
bot4_image = to_image(sys.path[0] + "/./images/改变节点运算.png", (100, 50))
|
|
|
bot4 = tk.Button(window, image=bot4_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.change_opt())
|
|
|
bot4.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 300 + dy, width=100, height=50)
|
|
|
bot4.image = bot4_image
|
|
|
|
|
|
bot5_image = to_image(sys.path[0] + "/./images/数值节点交换.png", (100, 50))
|
|
|
bot5 = tk.Button(window, image=bot5_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.change_node())
|
|
|
bot5.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 350 + dy, width=100, height=50)
|
|
|
bot5.image = bot5_image
|
|
|
|
|
|
#bot6_image = to_image(sys.path[0] + "/./images/产生表达式.png", (80, 30))
|
|
|
#bot6 = tk.Button(window, image=bot6_image, bd=0, relief="solid", bg="#141414",
|
|
|
# highlightthickness=0, command=lambda: self.Aexp())
|
|
|
#bot6.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 400 + dy, width=80, height=30)
|
|
|
#bot6.image = bot6_image
|
|
|
|
|
|
bot7_image = to_image(sys.path[0] + "/./images/清空画布.png", (100, 50))
|
|
|
bot7 = tk.Button(window, image=bot7_image, bd=0, relief="solid", bg="#141414",
|
|
|
highlightthickness=0, command=lambda: self.clear())
|
|
|
bot7.place(x=TREE_CANVAS_WIDTH - 50, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 400 + dy, width=100, height=50)
|
|
|
bot7.image = bot7_image
|
|
|
|
|
|
self.draw()
|
|
|
|
|
|
def set_opt(self, x):
|
|
|
opt = ['+', '-', '*', '/']
|
|
|
self.opt = opt[x - 1]
|
|
|
for i in range(4):
|
|
|
exec('self.opt' + str(i + 1) + '["state"] = "normal"')
|
|
|
exec('self.opt' + str(i + 1) + "['bg']='#131415'")
|
|
|
exec('self.opt' + str(i + 1) + "['fg']='black'")
|
|
|
|
|
|
exec('self.opt' + str(x) + "['state']='disable'")
|
|
|
exec('self.opt' + str(x) + "['bg']='#8f735c'")
|
|
|
exec('self.opt' + str(x) + "['fg']='white'")
|
|
|
self.draw()
|
|
|
|
|
|
def add_opt(self):
|
|
|
tree.remark()
|
|
|
self.tips = '请选择两个节点'
|
|
|
self.mode = 1
|
|
|
self.draw()
|
|
|
|
|
|
def change_node(self):
|
|
|
tree.remark()
|
|
|
self.tips = '请选择两个数值节点'
|
|
|
self.mode = 5
|
|
|
self.draw()
|
|
|
|
|
|
def change_opt(self):
|
|
|
tree.remark()
|
|
|
self.tips = '请选择一个运算节点'
|
|
|
self.mode = 4
|
|
|
self.draw()
|
|
|
|
|
|
def add_num(self):
|
|
|
tree.remark()
|
|
|
self.tips = '请选择一张card'
|
|
|
self.mode = 2
|
|
|
self.draw()
|
|
|
|
|
|
def add_number(self):
|
|
|
root = Tk()
|
|
|
root.withdraw()
|
|
|
number = simpledialog.askfloat("输入框", "请输入数字:")
|
|
|
if number is not None:
|
|
|
tree.remark()
|
|
|
self.mode = 2
|
|
|
tree.Node.append(
|
|
|
[len(tree.Node), 'Value', None, None, None, int(number), 'Spade'])
|
|
|
self.draw()
|
|
|
|
|
|
def change_num(self):
|
|
|
tree.remark()
|
|
|
self.tips = '请选择一个数值节点'
|
|
|
self.mode = 3
|
|
|
self.draw()
|
|
|
|
|
|
def left1(self, event):
|
|
|
# 无操作
|
|
|
if self.mode == 0:
|
|
|
return
|
|
|
# 添加运算节点
|
|
|
elif self.mode == 1:
|
|
|
i = 0
|
|
|
for T in tree.place:
|
|
|
if abs(event.x - T[0]) <= tree.bc / 2 and abs(event.y - T[1]) <= tree.bc / 2:
|
|
|
# 标记点击的节点
|
|
|
tree.mark[i] = not tree.mark[i]
|
|
|
i += 1
|
|
|
|
|
|
nodes = []
|
|
|
for i in range(len(tree.Node)):
|
|
|
if tree.mark[i] == 1:
|
|
|
nodes.append(i)
|
|
|
|
|
|
if len(nodes) == 2:
|
|
|
# 若已经选择两个节点
|
|
|
tree.check()
|
|
|
# 检查节点是否合法
|
|
|
if tree.ck[nodes[0]] == 1 and tree.ck[nodes[1]] == 1:
|
|
|
# 若节点合法,则添加新运算节点并将其设置为根节点
|
|
|
ID = len(tree.Node)
|
|
|
tree.Node.append([ID, 'Operator', self.opt, nodes[0], nodes[1], None, None])
|
|
|
tree.rootID = ID
|
|
|
else:
|
|
|
# 若节点不合法则显示警告
|
|
|
tk.messagebox.showinfo('', '所选节点不合法')
|
|
|
# 添加运算节点操作结束
|
|
|
self.mode = 0
|
|
|
self.tips = ''
|
|
|
tree.remark()
|
|
|
# 添加数值节点
|
|
|
elif self.mode == 2:
|
|
|
# 添加数值节点无需点击节点
|
|
|
pass
|
|
|
# 改变运算输入
|
|
|
elif self.mode == 3:
|
|
|
i = 0
|
|
|
flag = 0
|
|
|
for T in tree.place:
|
|
|
if abs(event.x - T[0]) <= tree.bc / 2 and abs(event.y - T[1]) <= tree.bc / 2:
|
|
|
# 若点击节点为数值节点,则标记
|
|
|
if tree.Node[i][1] == 'Value':
|
|
|
tree.mark[i] = 1
|
|
|
flag = 1
|
|
|
# 若点击节点为运算节点,则弹窗警告
|
|
|
else:
|
|
|
tk.messagebox.showinfo('', '所选节点不合法')
|
|
|
flag = 1
|
|
|
i += 1
|
|
|
|
|
|
if flag:
|
|
|
# 选择节点完成过后,还需选择card
|
|
|
self.mode = 6
|
|
|
self.tips = '请选择一张card'
|
|
|
self.draw()
|
|
|
# 改变节点运算
|
|
|
elif self.mode == 4:
|
|
|
i = 0
|
|
|
flag = 0
|
|
|
for T in tree.place:
|
|
|
if abs(event.x - T[0]) <= tree.bc / 2 and abs(event.y - T[1]) <= tree.bc / 2:
|
|
|
# 检查节点是否合法,若选择的是运算节点,则进行运算符的改变
|
|
|
if tree.Node[i][1] == 'Operator':
|
|
|
tree.Node[i][2] = self.opt
|
|
|
flag = 1
|
|
|
# 若选择的是数值节点,则弹窗警告
|
|
|
else:
|
|
|
tk.messagebox.showinfo('', '所选节点不合法')
|
|
|
flag = 1
|
|
|
i += 1
|
|
|
|
|
|
if flag:
|
|
|
# 操作完毕,进行复位
|
|
|
self.mode = 0
|
|
|
self.tips = ''
|
|
|
tree.remark()
|
|
|
# 数值节点交换
|
|
|
elif self.mode == 5:
|
|
|
i = 0
|
|
|
for T in tree.place:
|
|
|
# 标记选择的节点
|
|
|
if abs(event.x - T[0]) <= tree.bc / 2 and abs(event.y - T[1]) <= tree.bc / 2:
|
|
|
tree.mark[i] = not tree.mark[i]
|
|
|
|
|
|
i += 1
|
|
|
|
|
|
nodes = []
|
|
|
for i in range(len(tree.Node)):
|
|
|
if tree.mark[i] == 1:
|
|
|
nodes.append(i)
|
|
|
|
|
|
if len(nodes) == 2:
|
|
|
# 已经选择两个节点
|
|
|
if tree.Node[nodes[0]][1] == 'Value' and tree.Node[nodes[1]][1] == 'Value':
|
|
|
# 若选择的节点都是数值节点,则交换两个节点的数值与花色
|
|
|
Value = tree.Node[nodes[0]][5]
|
|
|
Color = tree.Node[nodes[0]][6]
|
|
|
tree.Node[nodes[0]][5] = tree.Node[nodes[1]][5]
|
|
|
tree.Node[nodes[0]][6] = tree.Node[nodes[1]][6]
|
|
|
tree.Node[nodes[1]][5] = Value
|
|
|
tree.Node[nodes[1]][6] = Color
|
|
|
else:
|
|
|
# 若选择的不是数值节点,则进行警告
|
|
|
tk.messagebox.showinfo('', '所选节点不合法')
|
|
|
# 操作结束,复位
|
|
|
self.mode = 0
|
|
|
self.tips = ''
|
|
|
tree.remark()
|
|
|
self.draw()
|
|
|
|
|
|
def clear(self):
|
|
|
self.Tree_cv.delete('tree')
|
|
|
tree.Node = []
|
|
|
tree.rootID = None
|
|
|
|
|
|
def Aexp(self):
|
|
|
entry.delete(0, "end")
|
|
|
try:
|
|
|
exp = tree.Aexp(tree.Node[tree.rootID])
|
|
|
except:
|
|
|
tk.messagebox.showinfo('', '语法树不合法')
|
|
|
return
|
|
|
entry.insert("end", exp)
|
|
|
ans = float(tree.calculate(tree.Node[tree.rootID]))
|
|
|
ans_cal(f'{float(tree.calculate(tree.Node[tree.rootID])):.2f}')
|
|
|
if ans == 24:
|
|
|
TorF(1)
|
|
|
else:
|
|
|
TorF(-1)
|
|
|
|
|
|
char_list = [] # 用于存放算式中的数字
|
|
|
for i in range(len(exp)):
|
|
|
if exp[i] > '0' and exp[i] <= '9':
|
|
|
char_list.append(exp[i])
|
|
|
a = Counter(char_list) # 计数函数Counter
|
|
|
# b = Counter([sz[0][1], sz[1][1], sz[2][1], sz[3][1]])
|
|
|
# if len(char_list) != 4:
|
|
|
# tk.messagebox.showinfo('', '请输入符合所给卡牌点数的可运算表达式')
|
|
|
|
|
|
def show_tree(self, ss):
|
|
|
# 清空画布
|
|
|
self.Tree_cv.delete('tree')
|
|
|
if len(ss) == 0:
|
|
|
tk.messagebox.showinfo('', '表达式不存在')
|
|
|
return
|
|
|
|
|
|
build_ast(ss)
|
|
|
self.draw()
|
|
|
|
|
|
def element(self, path):
|
|
|
# 加载图元对应的图片文件
|
|
|
img = Image.open(path)
|
|
|
# 使用resize方法调整图片
|
|
|
img = img.resize((70, 70))
|
|
|
# 把Image对象转换成PhotoImage对象
|
|
|
img = ImageTk.PhotoImage(img)
|
|
|
# 保存图片的引用,防止被垃圾回收
|
|
|
window.img = img
|
|
|
return img
|
|
|
|
|
|
def draw(self):
|
|
|
self.Tree_cv.delete('tree')
|
|
|
mode = ['无', '添加运算节点', '添加数值节点', '改变运算输入', '改变节点运算', '数值节点交换', '添加数值节点']
|
|
|
lab1 = tk.Label(self.Tree_cv, text='当前操作:', bg='#131415', fg="white", font=('微软雅黑', 14, 'bold'),
|
|
|
borderwidth=0, anchor='w')
|
|
|
lab1.place(x=30, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 100, width=90, height=30)
|
|
|
lab2 = tk.Label(self.Tree_cv, text=mode[self.mode], bg='#131415', fg="white", font=('微软雅黑', 14, 'bold'),
|
|
|
borderwidth=5, anchor='w')
|
|
|
lab2.place(x=120, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 100, width=150, height=30)
|
|
|
lab3 = tk.Label(self.Tree_cv, text=self.tips, bg='#131415', fg="white", font=('微软雅黑', 14, 'bold'),
|
|
|
borderwidth=5, anchor='w')
|
|
|
lab3.place(x=300, y=CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 100, width=200, height=30)
|
|
|
|
|
|
tree.deepth = []
|
|
|
for i in range(len(tree.Node)):
|
|
|
tree.deepth.append(-1)
|
|
|
# 格式化树节点的深度
|
|
|
tree.deep()
|
|
|
|
|
|
# 初始化节点数与深度
|
|
|
dept, nums = -1, 0
|
|
|
tree.place = []
|
|
|
for i in range(len(tree.deepth)):
|
|
|
dept = max(dept, tree.deepth[i])
|
|
|
tree.place.append((None, None))
|
|
|
if tree.deepth[i] == 0:
|
|
|
nums += 1
|
|
|
|
|
|
tree_length = TREE_CANVAS_WIDTH
|
|
|
tree_height = TREE_CANVAS_HEIGHT * 0.7
|
|
|
dx = tree_length // (nums + 1)
|
|
|
dy = tree_height // (dept + 2)
|
|
|
# 若为数字节点
|
|
|
cur = 0
|
|
|
for i in range(len(tree.deepth)):
|
|
|
if tree.deepth[i] == 0:
|
|
|
draw_number(str(tree.Node[i][5])) # 生成数字图片
|
|
|
img = self.element(sys.path[0] + "/./images/{}.png".format(tree.Node[i][5])) # 生成图片对象 img
|
|
|
NUMBER_IMAGES.append(img) # 防止覆盖,将图片保存在图片列表里
|
|
|
cur += 1
|
|
|
tree.place[i] = (cur * dx, tree_height - dy + CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 200)
|
|
|
self.Tree_cv.create_image(tree.place[i][0] - tree.bc / 2, tree.place[i][1] - tree.bc / 2,
|
|
|
image=img, anchor=NW, tags="tree")
|
|
|
|
|
|
for d in range(dept):
|
|
|
cur_d = d + 1
|
|
|
for i in range(len(tree.deepth)):
|
|
|
if tree.deepth[i] == cur_d:
|
|
|
lnode = tree.place[tree.Node[i][3]]
|
|
|
rnode = tree.place[tree.Node[i][4]]
|
|
|
node = (
|
|
|
(lnode[0] + rnode[0]) / 2,
|
|
|
tree_height - (cur_d + 1) * dy + CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 150)
|
|
|
self.Tree_cv.create_line(lnode[0], lnode[1] - tree.bc / 2 + 10, node[0], node[1] + tree.bc / 2 - 10,
|
|
|
fill='#246B80', width=1, tags="tree")
|
|
|
self.Tree_cv.create_line(rnode[0], rnode[1] - tree.bc / 2 + 10, node[0], node[1] + tree.bc / 2 - 10,
|
|
|
fill='#246B80', width=1, tags="tree")
|
|
|
tree.place[i] = node
|
|
|
color = 'white'
|
|
|
if tree.mark[i]:
|
|
|
color = '#d1d2c8'
|
|
|
self.Tree_cv.create_image(tree.place[i][0] - tree.bc / 2, tree.place[i][1] - tree.bc / 2,
|
|
|
image=FUNCTION_IMAGES[str(tree.Node[i][2])], anchor=NW, tags="tree")
|
|
|
self.Tree_cv.update()
|
|
|
|
|
|
|
|
|
# 随机生成表达式
|
|
|
def expressions():
|
|
|
init()
|
|
|
but5.configure(state='disabled')
|
|
|
with open(sys.path[0]+'/./expressions.txt', 'r') as file:
|
|
|
expressions = file.readlines()
|
|
|
random_expression = random.choice(expressions)
|
|
|
entry.insert("end", random_expression.strip())
|
|
|
|
|
|
|
|
|
# 随机生成语法树
|
|
|
def expression_tree():
|
|
|
init()
|
|
|
with open(sys.path[0]+'/./expressions.txt', 'r') as file:
|
|
|
expressions = file.readlines()
|
|
|
random_expression = random.choice(expressions)
|
|
|
return random_expression
|
|
|
|
|
|
|
|
|
# 一致性检查
|
|
|
def examine():
|
|
|
expression = entry.get()
|
|
|
if expression == '':
|
|
|
return tk.messagebox.showinfo(message='请输入表达式!')
|
|
|
expression_ans = eval(expression) # 计算用户输入的表达式的值
|
|
|
try:
|
|
|
tree_ans = float(tree.calculate(tree.Node[tree.rootID]))
|
|
|
if expression_ans == tree_ans:
|
|
|
but5.configure(state='active')
|
|
|
tk.messagebox.showinfo('', '语法树与表达式一致!')
|
|
|
else:
|
|
|
tk.messagebox.showinfo('', '语法树与表达式不一致!')
|
|
|
except:
|
|
|
return tk.messagebox.showinfo(message='请绘制语法树!')
|
|
|
|
|
|
|
|
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
|
|
|
|
# 绘制数字图片
|
|
|
def draw_number(number):
|
|
|
# 打开背景图片
|
|
|
background_image = Image.open(sys.path[0] + "/./images/number_ground.png")
|
|
|
# 设置图片尺寸
|
|
|
image_width = 48
|
|
|
image_height = 48
|
|
|
# 缩放背景图片
|
|
|
background_image = background_image.resize((image_width, image_height))
|
|
|
# 创建空白图片
|
|
|
image = Image.new("RGBA", (image_width, image_height), (255, 255, 255, 0))
|
|
|
# 在空白图片上绘制背景图片
|
|
|
image.paste(background_image, (0, 0))
|
|
|
# 设置字体和字号
|
|
|
#以下字体出现问题,已经注释
|
|
|
# if int(number) < 100:
|
|
|
# font = ImageFont.truetype("arial.ttf", 15)
|
|
|
# elif 100 <= int(number) <= 999:
|
|
|
# font = ImageFont.truetype("arial.ttf", 13)
|
|
|
# else:
|
|
|
# font = ImageFont.truetype("arial.ttf", 9)
|
|
|
|
|
|
# 创建绘图对象
|
|
|
draw = ImageDraw.Draw(image)
|
|
|
# 计算文字位置居中
|
|
|
#以下字体出现问题,已经注释,font=font
|
|
|
bbox = draw.textbbox((0, 0), number)
|
|
|
text_width = bbox[2] - bbox[0]
|
|
|
text_height = bbox[3] - bbox[1]
|
|
|
# text_width, text_height = 15,9
|
|
|
# text_width, text_height = draw.textsize(number, font=font)
|
|
|
text_x = (image_width - text_width) // 2 - 1
|
|
|
text_y = (image_height - text_height) // 2 - 1
|
|
|
# 在图片上绘制数字
|
|
|
#以下字体出现问题,已经注释,font=font
|
|
|
draw.text((text_x, text_y), number,fill="rgb(88,204,230)")
|
|
|
# 保存图片
|
|
|
file = sys.path[0] + "/./images/" + number + ".png"
|
|
|
image.save(file)
|
|
|
|
|
|
|
|
|
def click(event):
|
|
|
if event.y < CARD_CANVAS_HEIGHT:
|
|
|
left2(event)
|
|
|
else:
|
|
|
F.left1(event)
|
|
|
|
|
|
|
|
|
window = tk.Tk()
|
|
|
window.title('二十四点')
|
|
|
NUMBER_IMAGES = []
|
|
|
FUNCTION_IMAGES = {
|
|
|
"+": ImageTk.PhotoImage(imim.open(sys.path[0] + "/./images/+.png").resize((70, 70))),
|
|
|
"-": ImageTk.PhotoImage(imim.open(sys.path[0] + "/./images/-.png").resize((70, 70))),
|
|
|
"*": ImageTk.PhotoImage(imim.open(sys.path[0] + "/./images/X.png").resize((70, 70))),
|
|
|
"/": ImageTk.PhotoImage(imim.open(sys.path[0] + "/./images/÷.png").resize((70, 70)))
|
|
|
}
|
|
|
var = tk.StringVar()
|
|
|
var2 = tk.StringVar()
|
|
|
width = WINDOW_WIDTH
|
|
|
height = WINDOW_HEIGHT # 窗口大小
|
|
|
screen_width = window.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小
|
|
|
screen_height = window.winfo_screenheight()
|
|
|
x = int((screen_width - width) / 2)
|
|
|
y = int((screen_height - height) / 2)#-40
|
|
|
size = '{}x{}+{}+{}'.format(width, height, x, y)
|
|
|
window.geometry(size)
|
|
|
window.resizable(True, True)
|
|
|
window.resizable(False, False)
|
|
|
C = Canvas(window, bg="blue", height=WINDOW_HEIGHT, width=WINDOW_WIDTH)
|
|
|
filename = ImageTk.PhotoImage(imim.open(BACKGROUND_IMG).resize((WINDOW_WIDTH, WINDOW_HEIGHT))) # 创建语法树的背景图片
|
|
|
C.create_image(0, 0, image=filename, anchor=NW)
|
|
|
qianzhi = ImageTk.PhotoImage(imim.open(sys.path[0] + "/./images/前置背景.png").resize((WINDOW_WIDTH, 30)))
|
|
|
C.create_image(0, CARD_CANVAS_HEIGHT + ENTRY_HEIGHT + 70, image=qianzhi, anchor=NW)
|
|
|
C.pack()
|
|
|
F = Frame_Tree(window)
|
|
|
C.bind('<Button-1>', click)
|
|
|
entry = tk.Entry(window, show=None, font=('宋体', 15, 'bold'))
|
|
|
entry.place(x=LEFT_PADDING, y=CARD_CANVAS_HEIGHT + 15, width=ENTRY_WIDTH, height=ENTRY_HEIGHT)
|
|
|
all_ans = None
|
|
|
Buts()
|
|
|
init()
|
|
|
window.mainloop()
|