diff --git a/TreeNode.py b/TreeNode.py new file mode 100644 index 0000000..a20f53e --- /dev/null +++ b/TreeNode.py @@ -0,0 +1,357 @@ +# -*- encoding: utf-8 -*- +""" + @Author: packy945 + @FileName: TreeNode.py + @DateTime: 2023/5/15 14:27 + @SoftWare: PyCharm +""" + +import re +import tkinter as tk +from data import * +import tkinter.messagebox + + +sz = [] +A = Aexp([0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]) +img_open = [] +img_png = [] + +class Tree: + def __init__(self): + self.bc = 40 + self.Node = [] + self.rootID = None + self.deepth = [] + self.place = [] + self.mark = [0] * 110 + self.ck = [] + + def check(self): + self.ck = [1] * len(self.Node) + for N in self.Node: + if N[3]: + self.ck[N[3]] = 0 + if N[4]: + self.ck[N[4]] = 0 + + def remark(self): + self.mark = [0] * 110 + + + + def deep(self): + flag = 0 + for i in range(len(self.Node)): + if self.Node[i][1] == 'Value': + self.deepth[i] = 0 + + for i in range(len(self.Node)): + if self.deepth[i] == -1: + flag = 1 + if self.Node[i][3] != None and self.Node[i][4] != None: + # print(self.Node[i][3], self.Node[i][4]) + self.deepth[i] = max(self.deepth[self.Node[i][3]], self.deepth[self.Node[i][4]]) + 1 + # print(self.deepth) + if flag: + self.deep() + + def calculate(self, node): + print(node) + if node[1] == 'Value': + return node[5] * 1.0 + elif node[1] == 'Operator': + a = self.calculate(self.Node[node[3]]) + b = self.calculate(self.Node[node[4]]) + if node[2] == '^': + return pow(int(a), int(b)) + else: + # print(a,node[2],b) + return eval(str(a) + node[2] + str(b)) + + def Aexp(self, node): + + if node[1] == 'Value': + return str(node[5]) + elif node[1] == 'Operator': + a = self.Aexp(self.Node[node[3]]) + b = self.Aexp(self.Node[node[4]]) + # print(a,node[2],b) + ans = '(' + str(a) + node[2] + str(b) + ')' + # print(ans) + return ans + + +tree = Tree() + + +cur = 0 +class TreeNode: + def __init__(self, Type, value, left=None, right=None, color='方块'): + global cur + self.NodeID = cur # 节点编号 + cur += 1 + self.NodeType = Type # 节点类型 + self.Ops = None # 运算符类型 + self.left = left + self.right = right + self.LeftNodeID = None + self.RightNodeID = None + if self.left: + self.LeftNodeID = left.NodeID # 左节点编号 + if self.right: + self.RightNodeID = right.NodeID # 右节点编号 + self.FaceValue = None # 节点数值 + self.FaceColor = color # 节点花色 + if Type == 'Value': + self.FaceValue = value + else: + self.Ops = value + + tree.Node.append([self.NodeID, self.NodeType, self.Ops, self.LeftNodeID, self.RightNodeID, self.FaceValue, self.FaceColor]) + + + +def build_ast(formula): + ''' + 建立语法树 + :param formula: 表达式,表达式的花色 + :return: 建立好的语法树 + ''' + # 去掉空格 + + global tree, cur + try: + expr, color = formula + except: + expr = formula + color = ['方块'] * 20 + if len(expr) == 0: + tk.messagebox.showinfo('', '表达式不存在') + return + cur = 0 + tree.__init__() + + expr = expr.replace(' ', '') + + # 将所有数字和符号分离出来 + tokens = re.findall(r'\d+|[()+\-*/^.]', expr) + i = 0 + for token in tokens: + if tokens[i] == '.': + + tokens[i - 1] = tokens[i - 1] + tokens[i] + tokens[i + 1] + del tokens[i: i + 2] + i += 1 + + # 定义优先级 + precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3} + + # 创建一个操作符栈和一个节点栈 + op_stack = [] + node_stack = [] + + color_cur = 0 + # 遍历所有 token + for token in tokens: + if token.isdigit(): + # print(cur, color[cur]) + node_stack.append(TreeNode('Value', int(token), color=color[color_cur])) + color_cur += 1 + elif token.count('.') == 1: + node_stack.append(TreeNode('Value', float(token), color=color[color_cur])) + color_cur += 1 + elif token in '+-*/^': + while op_stack and op_stack[-1] != '(' and precedence[token] <= precedence[op_stack[-1]]: + op = op_stack.pop() + right = node_stack.pop() + left = node_stack.pop() + node_stack.append(TreeNode('Operator', op, left, right)) + op_stack.append(token) + elif token == '(': + op_stack.append(token) + elif token == ')': + while op_stack and op_stack[-1] != '(': + op = op_stack.pop() + right = node_stack.pop() + left = node_stack.pop() + node_stack.append(TreeNode('Operator', op, left, right)) + op_stack.pop() + + # 处理剩下的操作符 + while op_stack: + op = op_stack.pop() + right = node_stack.pop() + left = node_stack.pop() + node_stack.append(TreeNode('Operator', op, left, right)) + + # 返回抽象语法树的根节点 + tree.rootID = node_stack[0].NodeID + # print(tree.rootID) + # print(tree.Node) + return node_stack[0] + + +def print_ast(node:TreeNode, prefix='', is_left=True): + if node: + if node.NodeType == 'Value': + s = str(node.FaceValue) + else: + s = str(node.Ops) + print(prefix + ('├── ' if is_left else '└── ') + s) + print_ast(node.left, prefix + ('│ ' if is_left else ' '), True) + print_ast(node.right, prefix + ('│ ' if is_left else ' '), False) + + + + + + +if __name__ == '__main__': + expr = "(34-13.121)*2*6" + # ast = build_ast(expr) + # print_ast(ast) + # print(tree.Node) + class Frame_Tree: + # def Frame_tree(): + def __init__(self, window): + self.Tree_root = tk.Frame(window, relief="groove", width=610, height=400) + self.Tree_root.place(x=50, y=250) # 树的显示 + + self.Tree_cv = tk.Canvas(self.Tree_root, width=610, height=400, bg='#b7bcc0') + self.Tree_cv.place(x=0, y=0) + # Tree_cv.create_rectangle(10, 10, 600, 290, width=10, outline='#ff9933') + + bot = tk.Button(self.Tree_root, text='添加运算节点', bg='#cca583', fg='black', ) + bot.place(x=500, y=40, width=80, height=30) + bot = tk.Button(self.Tree_root, text='添加数值节点', bg='#cca583', fg='black', ) + bot.place(x=500, y=75, width=80, height=30) + bot = tk.Button(self.Tree_root, text='改变运算输入', bg='#cca583', fg='black', ) + bot.place(x=500, y=110, width=80, height=30) + bot = tk.Button(self.Tree_root, text='改变节点运算', bg='#cca583', fg='black', ) + bot.place(x=500, y=145, width=80, height=30) + bot = tk.Button(self.Tree_root, text='数值节点交换', bg='#cca583', fg='black', ) + bot.place(x=500, y=180, width=80, height=30) + bot = tk.Button(self.Tree_root, text='产生表达式', bg='#cca583', fg='black', command=lambda: self.Aexp()) + bot.place(x=500, y=215, width=80, height=30) + # bot = tk.Button(self.Tree_root, text='计算', bg='#cca583', fg='black', command=lambda: tree.calculate(tree.Node[tree.rootID])) + # bot.place(x=500, y=250, width=80, height=30) + + + + + def clear(self): + self.Tree_cv.delete('all') + tree.Node = [] + tree.rootID = None + + def Aexp(self): + entry.delete(0, "end") + print(tree.Aexp(tree.Node[tree.rootID])) + entry.insert("end", tree.Aexp(tree.Node[tree.rootID])) + label2 = tk.Label(window, text=f'= {float(tree.calculate(tree.Node[tree.rootID])):.2f}', + font=('宋体', 15, 'bold'), width=30, height=10, + # 设置填充区距离、边框宽度和其样式(凹陷式) + borderwidth=5, relief="sunken") + label2.place(x=240, y=160, width=60, height=50) + + def show_tree(self, ss): + # 清空画布 + self.Tree_cv.delete('all') + build_ast(ss) + for i in range(len(tree.Node)): + tree.deepth.append(-1) + # print(tree.Node) + # print(tree.deepth) + # 格式化树节点的深度 + tree.deep() + # print(tree.deepth) + + # 初始化节点数与深度 + dept, nums = -1, 0 + 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 + # print(dept, nums) + + tree_length = 500 + tree_height = 400 + dx = tree_length // (nums + 1) + dy = tree_height // (dept + 2) + bc = 40 + # 若为数字节点 + cur = 0 + for i in range(len(tree.deepth)): + if tree.deepth[i] == 0: + cur += 1 + tree.place[i] = (cur * dx, tree_height - dy) + self.Tree_cv.create_rectangle(tree.place[i][0] - bc / 2, tree.place[i][1] - bc / 2, + tree.place[i][0] + bc / 2, + tree.place[i][1] + bc / 2, fill='white', width=0) + self.Tree_cv.create_text(tree.place[i][0], tree.place[i][1], text=str(tree.Node[i][5]), + font=('宋体', 15, 'bold'), anchor='center') + + 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) + self.Tree_cv.create_line(lnode[0], lnode[1] - bc / 2, node[0], node[1] + bc / 2, fill='#1ffbe9', + width=2) + self.Tree_cv.create_line(rnode[0], rnode[1] - bc / 2, node[0], node[1] + bc / 2, fill='#1ffbe9', + width=2) + tree.place[i] = node + self.Tree_cv.create_rectangle(tree.place[i][0] - bc / 2, tree.place[i][1] - bc / 2, + tree.place[i][0] + bc / 2, tree.place[i][1] + bc / 2, + fill='white', width=0) + self.Tree_cv.create_text(tree.place[i][0], tree.place[i][1], text=str(tree.Node[i][2]), + font=('宋体', 15, 'bold'), anchor='center') + window = tk.Tk() + var = tk.StringVar() + var2 = tk.StringVar() + width = 700 + height = 700 # 窗口大小 + 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) + + + # 基本组件显示 + cv = tk.Canvas(window, width=380, height=136, bg='#FFFFCC') + cv.place(x=100, y=3) + F = Frame_Tree(window) + but = tk.Button(window, text='出题', bg='#ffffcc', fg='black', command=lambda: show_card()) + but.place(x=500, y=20, width=100, height=50, ) + but2 = tk.Button(window, text='换牌', bg='#ffffcc', fg='black', ) + but2.place(x=500, y=80, width=100, height=50, ) + + entry = tk.Entry(window, show=None, font=('宋体', 15, 'bold')) + entry.place(x=50, y=160, width=180, height=50) + label2 = tk.Label(window, text='= 24', font=('宋体', 15, 'bold'), width=30, height=10, + # 设置填充区距离、边框宽度和其样式(凹陷式) + borderwidth=5, relief="sunken") + but4 = tk.Button(window, text='计算', bg='#ffffcc', fg='black', command=lambda: show_result(entry.get(), sz)) + but4.place(x=315, y=165, width=50, height=40, ) + label2.place(x=240, y=160, width=60, height=50) + + but3 = tk.Button(window, text='自动求解', bg='#ffffcc', fg='black', command=lambda: show_answer()) + but3.place(x=250, y=210, width=120, height=40, ) + but3 = tk.Button(window, text='所有答案', bg='#ffffcc', fg='black', command=lambda: show_all()) + but3.place(x=410, y=210, width=120, height=40, ) + + but5 = tk.Button(window, text='画树', bg='#ffffcc', fg='black', command=lambda: F.show_tree(expr)) + but5.place(x=80, y=210, width=120, height=40, ) + + + + # cv1 = tk.Canvas(window, width=380, height=90, bg='#FFFFCC') + # cv1.place(x=100, y=200) + + window.mainloop() diff --git a/card/Club/Club10.png b/card/Club/Club10.png new file mode 100644 index 0000000..8a57774 Binary files /dev/null and b/card/Club/Club10.png differ diff --git a/card/Club/Club2.png b/card/Club/Club2.png new file mode 100644 index 0000000..89b0856 Binary files /dev/null and b/card/Club/Club2.png differ diff --git a/card/Club/Club3.png b/card/Club/Club3.png new file mode 100644 index 0000000..56d80cb Binary files /dev/null and b/card/Club/Club3.png differ diff --git a/card/Club/Club4.png b/card/Club/Club4.png new file mode 100644 index 0000000..6f1c91c Binary files /dev/null and b/card/Club/Club4.png differ diff --git a/card/Club/Club5.png b/card/Club/Club5.png new file mode 100644 index 0000000..08e293f Binary files /dev/null and b/card/Club/Club5.png differ diff --git a/card/Club/Club6.png b/card/Club/Club6.png new file mode 100644 index 0000000..b883ac0 Binary files /dev/null and b/card/Club/Club6.png differ diff --git a/card/Club/Club7.png b/card/Club/Club7.png new file mode 100644 index 0000000..350fcd6 Binary files /dev/null and b/card/Club/Club7.png differ diff --git a/card/Club/Club8.png b/card/Club/Club8.png new file mode 100644 index 0000000..0e48bba Binary files /dev/null and b/card/Club/Club8.png differ diff --git a/card/Club/Club9.png b/card/Club/Club9.png new file mode 100644 index 0000000..f5d6067 Binary files /dev/null and b/card/Club/Club9.png differ diff --git a/card/Club/Cluba.png b/card/Club/Cluba.png new file mode 100644 index 0000000..28c50b8 Binary files /dev/null and b/card/Club/Cluba.png differ diff --git a/card/Club/Clubj.png b/card/Club/Clubj.png new file mode 100644 index 0000000..0939094 Binary files /dev/null and b/card/Club/Clubj.png differ diff --git a/card/Club/Clubk.png b/card/Club/Clubk.png new file mode 100644 index 0000000..e743cae Binary files /dev/null and b/card/Club/Clubk.png differ diff --git a/card/Club/Clubq.png b/card/Club/Clubq.png new file mode 100644 index 0000000..e66b6b9 Binary files /dev/null and b/card/Club/Clubq.png differ diff --git a/card/Diamond/Diamond10.png b/card/Diamond/Diamond10.png new file mode 100644 index 0000000..159d808 Binary files /dev/null and b/card/Diamond/Diamond10.png differ diff --git a/card/Diamond/Diamond2.png b/card/Diamond/Diamond2.png new file mode 100644 index 0000000..274d9fa Binary files /dev/null and b/card/Diamond/Diamond2.png differ diff --git a/card/Diamond/Diamond3.png b/card/Diamond/Diamond3.png new file mode 100644 index 0000000..eb10cb2 Binary files /dev/null and b/card/Diamond/Diamond3.png differ diff --git a/card/Diamond/Diamond4.png b/card/Diamond/Diamond4.png new file mode 100644 index 0000000..eed01a7 Binary files /dev/null and b/card/Diamond/Diamond4.png differ diff --git a/card/Diamond/Diamond5.png b/card/Diamond/Diamond5.png new file mode 100644 index 0000000..d33fd42 Binary files /dev/null and b/card/Diamond/Diamond5.png differ diff --git a/card/Diamond/Diamond6.png b/card/Diamond/Diamond6.png new file mode 100644 index 0000000..b60cf3c Binary files /dev/null and b/card/Diamond/Diamond6.png differ diff --git a/card/Diamond/Diamond7.png b/card/Diamond/Diamond7.png new file mode 100644 index 0000000..8f20654 Binary files /dev/null and b/card/Diamond/Diamond7.png differ diff --git a/card/Diamond/Diamond8.png b/card/Diamond/Diamond8.png new file mode 100644 index 0000000..bb9f311 Binary files /dev/null and b/card/Diamond/Diamond8.png differ diff --git a/card/Diamond/Diamond9.png b/card/Diamond/Diamond9.png new file mode 100644 index 0000000..d2785e0 Binary files /dev/null and b/card/Diamond/Diamond9.png differ diff --git a/card/Diamond/Diamonda.png b/card/Diamond/Diamonda.png new file mode 100644 index 0000000..2ad2cd9 Binary files /dev/null and b/card/Diamond/Diamonda.png differ diff --git a/card/Diamond/Diamondj.png b/card/Diamond/Diamondj.png new file mode 100644 index 0000000..cfabd22 Binary files /dev/null and b/card/Diamond/Diamondj.png differ diff --git a/card/Diamond/Diamondk.png b/card/Diamond/Diamondk.png new file mode 100644 index 0000000..162c8dd Binary files /dev/null and b/card/Diamond/Diamondk.png differ diff --git a/card/Diamond/Diamondq.png b/card/Diamond/Diamondq.png new file mode 100644 index 0000000..c8d58bf Binary files /dev/null and b/card/Diamond/Diamondq.png differ diff --git a/card/Heart/Heart10.png b/card/Heart/Heart10.png new file mode 100644 index 0000000..ef45f91 Binary files /dev/null and b/card/Heart/Heart10.png differ diff --git a/card/Heart/Heart2.png b/card/Heart/Heart2.png new file mode 100644 index 0000000..060190d Binary files /dev/null and b/card/Heart/Heart2.png differ diff --git a/card/Heart/Heart3.png b/card/Heart/Heart3.png new file mode 100644 index 0000000..690c345 Binary files /dev/null and b/card/Heart/Heart3.png differ diff --git a/card/Heart/Heart4.png b/card/Heart/Heart4.png new file mode 100644 index 0000000..aca2ab8 Binary files /dev/null and b/card/Heart/Heart4.png differ diff --git a/card/Heart/Heart5.png b/card/Heart/Heart5.png new file mode 100644 index 0000000..ff73f81 Binary files /dev/null and b/card/Heart/Heart5.png differ diff --git a/card/Heart/Heart6.png b/card/Heart/Heart6.png new file mode 100644 index 0000000..8875ad0 Binary files /dev/null and b/card/Heart/Heart6.png differ diff --git a/card/Heart/Heart7.png b/card/Heart/Heart7.png new file mode 100644 index 0000000..4e2bf76 Binary files /dev/null and b/card/Heart/Heart7.png differ diff --git a/card/Heart/Heart8.png b/card/Heart/Heart8.png new file mode 100644 index 0000000..d3af43c Binary files /dev/null and b/card/Heart/Heart8.png differ diff --git a/card/Heart/Heart9.png b/card/Heart/Heart9.png new file mode 100644 index 0000000..cec0a62 Binary files /dev/null and b/card/Heart/Heart9.png differ diff --git a/card/Heart/Hearta.png b/card/Heart/Hearta.png new file mode 100644 index 0000000..6b9c940 Binary files /dev/null and b/card/Heart/Hearta.png differ diff --git a/card/Heart/Heartj.png b/card/Heart/Heartj.png new file mode 100644 index 0000000..4356828 Binary files /dev/null and b/card/Heart/Heartj.png differ diff --git a/card/Heart/Heartk.png b/card/Heart/Heartk.png new file mode 100644 index 0000000..91de80a Binary files /dev/null and b/card/Heart/Heartk.png differ diff --git a/card/Heart/Heartq.png b/card/Heart/Heartq.png new file mode 100644 index 0000000..7e7668c Binary files /dev/null and b/card/Heart/Heartq.png differ diff --git a/card/Spade/Spade10.png b/card/Spade/Spade10.png new file mode 100644 index 0000000..6a0968f Binary files /dev/null and b/card/Spade/Spade10.png differ diff --git a/card/Spade/Spade2.png b/card/Spade/Spade2.png new file mode 100644 index 0000000..a2624c8 Binary files /dev/null and b/card/Spade/Spade2.png differ diff --git a/card/Spade/Spade3.png b/card/Spade/Spade3.png new file mode 100644 index 0000000..5af6c5e Binary files /dev/null and b/card/Spade/Spade3.png differ diff --git a/card/Spade/Spade4.png b/card/Spade/Spade4.png new file mode 100644 index 0000000..3434284 Binary files /dev/null and b/card/Spade/Spade4.png differ diff --git a/card/Spade/Spade5.png b/card/Spade/Spade5.png new file mode 100644 index 0000000..2657ac2 Binary files /dev/null and b/card/Spade/Spade5.png differ diff --git a/card/Spade/Spade6.png b/card/Spade/Spade6.png new file mode 100644 index 0000000..cdc8079 Binary files /dev/null and b/card/Spade/Spade6.png differ diff --git a/card/Spade/Spade7.png b/card/Spade/Spade7.png new file mode 100644 index 0000000..377af8b Binary files /dev/null and b/card/Spade/Spade7.png differ diff --git a/card/Spade/Spade8.png b/card/Spade/Spade8.png new file mode 100644 index 0000000..722911c Binary files /dev/null and b/card/Spade/Spade8.png differ diff --git a/card/Spade/Spade9.png b/card/Spade/Spade9.png new file mode 100644 index 0000000..ce3877a Binary files /dev/null and b/card/Spade/Spade9.png differ diff --git a/card/Spade/Spadea.png b/card/Spade/Spadea.png new file mode 100644 index 0000000..9b82294 Binary files /dev/null and b/card/Spade/Spadea.png differ diff --git a/card/Spade/Spadej.png b/card/Spade/Spadej.png new file mode 100644 index 0000000..6b77c4c Binary files /dev/null and b/card/Spade/Spadej.png differ diff --git a/card/Spade/Spadek.png b/card/Spade/Spadek.png new file mode 100644 index 0000000..b7c1c2f Binary files /dev/null and b/card/Spade/Spadek.png differ diff --git a/card/Spade/Spadeq.png b/card/Spade/Spadeq.png new file mode 100644 index 0000000..c82b344 Binary files /dev/null and b/card/Spade/Spadeq.png differ diff --git a/data.py b/data.py new file mode 100644 index 0000000..25c5a0b --- /dev/null +++ b/data.py @@ -0,0 +1,96 @@ +# -*- encoding: utf-8 -*- +""" + @Author: packy945 + @FileName: data.py + @DateTime: 2023/5/11 14:36 + @SoftWare: PyCharm +""" +from itertools import permutations +import random +import tkinter as tk + +MARK = '#ff0000' +NOMARK = '#cccccc' + + +class Aexp: + def __init__(self, a, b, c, d): + self.Aexp_cur = 0 + self.num = 0 + self.card = [a, b, c, d] + # print(self.card) + self.answer = [] + self.Color = [] + self.Aexp(a, b, c, d) + + def refresh(self, a, b, c, d): + self.Aexp_cur = 0 + self.num = 0 + self.card = [a, b, c, d] + # print(self.card) + self.answer = [] + self.Color = [] + self.Aexp(a, b, c, d) + + def Aexp(self, one, two, three, four): + ''' + 输入四个数,求24点 + :param one: + :param two: + :param three: + :param four: + :return: 求解24点结果。若无法得出则返回“无法求得结果” + ''' + self.Aexp_cur = 0 + my_list = [one, two, three, four] + result = [c for c in permutations(my_list, 4)] + list2 = [] # 算出24的排列组合的列表 + symbols = ["+", "-", "*", "/"] + flag = False + for one, two, three, four in result: + for s1 in symbols: + for s2 in symbols: + for s3 in symbols: + express = ["(({0}{1}{2}){3}{4}){5}{6}".format(one[1], s1, two[1], s2, three[1], s3, four[1]), + "({0}{1}{2}){3}({4}{5}{6})".format(one[1], s1, two[1], s2, three[1], s3, four[1]), + "({0}{1}({2}{3}{4})){5}{6}".format(one[1], s1, two[1], s2, three[1], s3, four[1]), + "{0}{1}(({2}{3}{4}){5}{6})".format(one[1], s1, two[1], s2, three[1], s3, four[1]), + "{0}{1}({2}{3}({4}{5}{6}))".format(one[1], s1, two[1], s2, three[1], s3, four[1])] + # if str(one) + str(two) + str(three) + str(four) == "8383": + # print(express) + for e in express: + try: + if round(eval(e), 6) == 24: + e = del_parentheses(e) + list2.append(e) + self.Color.append([one[0], two[0], three[0], four[0]]) + flag = True + except ZeroDivisionError: + pass + + + if flag: + self.answer = list2 + self.num = len(list2) + # return list3 + + else: + self.answer = ["无法得出24点"] + self.Color.append(None) + self.num = 0 + + +#删除最外层括号 +def del_parentheses(e): + if e[0] == '(' and e[-1] == ')': + try: + eval(e[1:len(e)-1]) + except: + pass + else: + if round(eval(e[1:len(e)-1]),6) == 24: + return e[1:len(e)-1] + return e + + + diff --git a/main.py b/main.py new file mode 100644 index 0000000..67ab916 --- /dev/null +++ b/main.py @@ -0,0 +1,781 @@ +# -*- encoding: utf-8 -*- +""" + @Author: packy945 + @FileName: main.py + @DateTime: 2023/5/11 11:34 + @SoftWare: PyCharm +""" +from data import * +import tkinter.messagebox +from collections import Counter +from PIL import Image, ImageTk +from TreeNode import * +import ttkbootstrap as ttk +from ttkbootstrap.constants import * +from ttkbootstrap import * + +sz = [] +A = Aexp([0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]) +img_open = [] +img_png = [] + +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 = MARK + clo2 = NOMARK + elif flag == 0: + clo1 = NOMARK + clo2 = NOMARK + else: + clo1 = NOMARK + clo2 = MARK + + + label3 = tk.Label(window, text='√', fg=clo1, font=('宋体', 10, 'bold italic'), borderwidth=5, relief="sunken") + label4 = tk.Label(window, text='×', fg=clo2, font=('宋体', 10, 'bold italic'), borderwidth=5, relief="sunken") + label3.place(x=625, y=240, width=30, height=25) + label4.place(x=625, y=270, width=30, height=25) + +def ans_cal(ans = None): + if not ans: + label2 = tk.Label(window, text='= ?', font=('楷体', 18, 'bold'), width=30, height=10, + # 设置填充区距离、边框宽度和其样式(凹陷式) + borderwidth=5, relief="sunken", anchor='w') + else: + label2 = tk.Label(window, text=f'={ans}', font=('楷体', 18, 'bold'), width=30, height=10, + # 设置填充区距离、边框宽度和其样式(凹陷式) + borderwidth=5, relief="sunken", anchor='w') + label2.place(x=425, y=240, width=100, height=50) + +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]) + cv.update() + +def show(kp_list): + # 根据花色以及点数显示卡牌 + # cv = tk.Canvas(window, width=380, height=136, bg='#FFFFCC') # 分配位置 + # cv.place(x=100, y=3) + global img_open, img_png + img_open = [] + img_png = [] + cv.delete('all') + i = 0 #卡牌位置偏移量 + for k in range(4): + img_open.append( + Image.open("card/" + kp_list[k][0] + "/" + kp_list[k][0] + kp_list[k][1] + '.png').resize((90, 130))) + img_png.append(ImageTk.PhotoImage(img_open[k])) + cv.create_image(50 + i, 70, image=img_png[k]) + i += 95 + ''' + img_open.append(Image.open("card/" + kp_list[0][0] + "/" + kp_list[0][0] + kp_list[0][1] + '.png').resize((90, 130))) + img_png.append(ImageTk.PhotoImage(img_open[0])) + cv.create_image(50 + i, 70, image=img_png[0]) + + # img_open = Image.open("card/" + kp_list[0][0] + "/" + kp_list[0][0] + kp_list[0][1] + '.png').resize((90, 130)) + # img_png = ImageTk.PhotoImage(img_open) + # cv.create_image(50 + i, 70, image=img_png) + + i += 95 + img_open.append( + Image.open("card/" + kp_list[1][0] + "/" + kp_list[1][0] + kp_list[1][1] + '.png').resize((90, 130))) + img_png.append(ImageTk.PhotoImage(img_open[1])) + cv.create_image(50 + i, 70, image=img_png[1]) + + # img_open1 = Image.open("card/" + kp_list[1][0] + "/" + kp_list[1][0] + kp_list[1][1] + '.png').resize((90, 130)) + # img_png1 = ImageTk.PhotoImage(img_open1) + # cv.create_image(50 + i, 70, image=img_png1) + i += 95 + + img_open2 = Image.open("card/" + kp_list[2][0] + "/" + kp_list[2][0] + kp_list[2][1] + '.png').resize((90, 130)) + img_png2 = ImageTk.PhotoImage(img_open2) + cv.create_image(50 + i, 70, image=img_png2) + i += 95 + img_open3 = Image.open("card/" + kp_list[3][0] + "/" + kp_list[3][0] + kp_list[3][1] + '.png').resize((90, 130)) + img_png3 = ImageTk.PhotoImage(img_open3) + cv.create_image(50 + i, 70, image=img_png3) + ''' + # window.mainloop() + cv.update() + + + +#展示结果 +def show_result(ss, sz): + ''' + 展示计算结果 + :param ss: 输入框中的表达式 + :param sz: 题中给的卡牌数字 + :return: + ''' + if len(sz) != 4: + tk.messagebox.showinfo('', '未出题') + return + char_list = [] #用于存放算式中的数字 + for i in range(len(ss)): + if ss[i]>'0' and ss[i]<='9': + char_list.append(ss[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('', '请输入符合所给卡牌点数的可运算表达式') + elif a != b: + tk.messagebox.showinfo('', '你的表达式中的点数与所给卡牌点数不同') + else: + 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 + try: + answer = (A.answer[0], A.Color[0]) + A.Aexp_cur = 0 + except: + tk.messagebox.showinfo('', '出错') + return + # 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]) + ''' + Treenode = Decomposition(answer) + label_answer = tk.Label(window,text=answer+' '+str(Treenode),bg="#FFFFCC",fg="black") + label_answer.place(x=105,y=210) + ''' + 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 + but = tk.Button(window, text='出题', bg='#ffffcc', fg='black', command=lambda: show_card()) + but.place(x=500, y=20, width=100, height=50, ) + but2 = tk.Button(window, text='换牌', bg='#ffffcc', fg='black', command=lambda: change_card()) + but2.place(x=500, y=80, width=100, height=50, ) + + but4 = tk.Button(window, text='计算', bg='#ffffcc', fg='black', command=lambda: show_result(entry.get(), sz)) + but4.place(x=530, y=240, width=80, height=50, ) + + but3 = tk.Button(window, text='自动求解', bg='#ffffcc', fg='black', command=lambda: show_answer()) + but3.place(x=250, y=210, width=120, height=40, ) + + all_ans = tk.Button(window, text='所有答案', bg='#ffffcc', fg='black', command=lambda: show_next(), state='disable') + all_ans.place(x=410, y=210, width=120, height=40, ) + + but5 = tk.Button(window, text='画树', bg='#ffffcc', fg='black', command=lambda: F.show_tree(entry.get())) + but5.place(x=80, y=210, width=120, height=40, ) + +def left2(event): + # 查找鼠标左键按下时位置是否在某个牌上 + # print(event.x, event.y) + # if not A.card + left = [5, 100, 195, 290] + right = [95, 190, 285, 380] + up = 5 + down = 135 + ''' + for i in range(4): + if up <= event.y <= down and right[i] >= event.x >= left[i]: + print(i + 1) + print(A.card[i]) + ''' + # 添加数值节点 + 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]]) + 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_root = tk.Frame(window, relief="groove", width=610, height=400) + self.Tree_root.place(x=50, y=250) # 树的显示 + + self.Tree_cv = tk.Canvas(self.Tree_root, width=610, height=400, bg='#b7bcc0') + self.Tree_cv.place(x=0, y=0) + # Tree_cv.create_rectangle(10, 10, 600, 290, width=10, outline='#ff9933') + + self.opt1 = tk.Button(self.Tree_root, text='+', bg='#cca583', fg='black', command=lambda: self.set_opt(1)) + self.opt1.place(x=500, y=20, width=30, height=30) + self.opt2 = tk.Button(self.Tree_root, text='-', bg='#cca583', fg='black', command=lambda: self.set_opt(2)) + self.opt2.place(x=535, y=20, width=30, height=30) + self.opt3 = tk.Button(self.Tree_root, text='*', bg='#cca583', fg='black', command=lambda: self.set_opt(3)) + self.opt3.place(x=500, y=55, width=30, height=30) + self.opt4 = tk.Button(self.Tree_root, text='/', bg='#cca583', fg='black', command=lambda: self.set_opt(4)) + self.opt4.place(x=535, y=55, width=30, height=30) + + self.set_opt(1) + + dy = 50 + + bot = tk.Button(self.Tree_root, text='添加运算节点', bg='#cca583', fg='black', command=lambda: self.add_opt()) + bot.place(x=500, y=40 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='添加数值节点', bg='#cca583', fg='black', command=lambda: self.add_num()) + bot.place(x=500, y=75 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='改变运算输入', bg='#cca583', fg='black', command=lambda: self.change_num()) + bot.place(x=500, y=110 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='改变节点运算', bg='#cca583', fg='black', command=lambda: self.change_opt()) + bot.place(x=500, y=145 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='数值节点交换', bg='#cca583', fg='black', command=lambda: self.change_node()) + bot.place(x=500, y=180 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='产生表达式', bg='#cca583', fg='black', command=lambda: self.Aexp()) + bot.place(x=500, y=215 + dy, width=80, height=30) + bot = tk.Button(self.Tree_root, text='清空画布', bg='#cca583', fg='black', command=lambda: self.clear()) + bot.place(x=500, y=250 + dy, width=80, height=30) + # bot = tk.Button(self.Tree_root, text='计算', bg='#cca583', fg='black', command=lambda: tree.calculate(tree.Node[tree.rootID])) + # bot.place(x=500, y=250, width=80, height=30) + self.Tree_cv.bind('', self.left1) + self.draw() + + + def set_opt(self, x): + # self.opt1["state"] = "disable" + # exec('self.opt1["state"] = "disable"') + 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']='#cca583'") + 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'") + # 8f735c + 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 change_num(self): + tree.remark() + self.tips = '请选择一个数值节点' + self.mode = 3 + self.draw() + + def left1(self, event): + # 查找鼠标左键按下时位置是否在某个节点内,并根据当前操作模式进行反馈 + ''' + print(event.x, event.y) + i = 0 + print(tree.place) + + 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] + print(tree.Node[i]) + + i += 1 + ''' + # 无操作 + 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('all') + 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 = int(tree.calculate(tree.Node[tree.rootID])) + 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('all') + if len(ss) == 0: + tk.messagebox.showinfo('', '表达式不存在') + return + + build_ast(ss) + self.draw() + + + def draw(self): + self.Tree_cv.delete('all') + mode = ['无', '添加运算节点', '添加数值节点', '改变运算输入', '改变节点运算', '数值节点交换', '添加数值节点'] + lab1 = tk.Label(self.Tree_cv, text='当前操作:', bg='#b7bcc0', font=('宋体', 14, 'bold'), borderwidth=5, anchor='w') + lab1.place(x=30, y=10, width=90, height=30) + lab2 = tk.Label(self.Tree_cv, text=mode[self.mode], bg='#b7bcc0', font=('宋体', 14, 'bold'), borderwidth=5, anchor='w') + lab2.place(x=120, y=10, width=150, height=30) + lab3 = tk.Label(self.Tree_cv, text=self.tips, bg='#b7bcc0', font=('宋体', 14, 'bold'), borderwidth=5, anchor='w') + lab3.place(x=300, y=10, 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 = 500 + tree_height = 400 + dx = tree_length // (nums + 1) + dy = tree_height // (dept + 2) + # 若为数字节点 + cur = 0 + for i in range(len(tree.deepth)): + if tree.deepth[i] == 0: + cur += 1 + tree.place[i] = (cur * dx, tree_height - dy) + color = 'white' + if tree.mark[i]: + color = '#d1d2c8' + self.Tree_cv.create_rectangle(tree.place[i][0] - tree.bc / 2, tree.place[i][1] - tree.bc / 2, + tree.place[i][0] + tree.bc / 2, + tree.place[i][1] + tree.bc / 2, fill=color, width=0) + self.Tree_cv.create_text(tree.place[i][0], tree.place[i][1], text=str(tree.Node[i][5]), + font=('宋体', 15, 'bold'), anchor='center') + + 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) + self.Tree_cv.create_line(lnode[0], lnode[1] - tree.bc / 2, node[0], node[1] + tree.bc / 2, + fill='#1ffbe9', width=2) + self.Tree_cv.create_line(rnode[0], rnode[1] - tree.bc / 2, node[0], node[1] + tree.bc / 2, + fill='#1ffbe9', width=2) + tree.place[i] = node + color = 'white' + if tree.mark[i]: + color = '#d1d2c8' + self.Tree_cv.create_rectangle(tree.place[i][0] - tree.bc / 2, tree.place[i][1] - tree.bc / 2, + tree.place[i][0] + tree.bc / 2, tree.place[i][1] + tree.bc / 2, + fill=color, width=0) + self.Tree_cv.create_text(tree.place[i][0], tree.place[i][1], text=str(tree.Node[i][2]), + font=('宋体', 15, 'bold'), anchor='center') + + self.Tree_cv.update() + +window = Window() +screen_width = window.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小 +screen_height = window.winfo_screenheight() +var = tk.StringVar() +var2 = tk.StringVar() +width = int(screen_width*0.8) +height = int(screen_height*0.8 ) # 窗口大小 +x = int((screen_width - width) / 2) +y = int((screen_height - height) / 2) - 40 +size = '{}x{}+{}+{}'.format(width, height, x, y) +window.geometry(size) + +F = Frame_Tree(window) +#基本组件显示 +cv = Canvas(window, width=width, height=height * 0.3, background='red') +cv.place(x=0, y=3) +cv.bind('', left2) +entry = tk.Entry(window, show=None, font=('宋体', 15, 'bold')) +entry.place(x=25, y=240, width=400, height=50) +all_ans = None +BUTs() + + + +''' + +label3 = tk.Label(window,text='√',fg='#cccccc',font=('宋体', 10, 'bold italic'), borderwidth=5, relief="sunken") +label4 = tk.Label(window,text='×',fg='#cccccc',font=('宋体', 10, 'bold italic'), borderwidth=5, relief="sunken") +label3.place(x=360,y=160,width=30,height=25) +label4.place(x=360,y=180,width=30,height=25) +label2 = tk.Label(window, text='= ?', font=('宋体', 15, 'bold'), width=30, height=10, + # 设置填充区距离、边框宽度和其样式(凹陷式) + borderwidth=5, relief="sunken") +label2.place(x=240, y=160, width=60, height=50) +''' +init() +# cv1 = tk.Canvas(window, width=380, height=90, bg='#FFFFCC') +# cv1.place(x=100, y=200) + + +''' +cv = tk.Canvas(window, width=610, height=300, bg='#ffffff') +cv.place(x=3, y=310) +cv.create_rectangle(10,10,600,290,width=10,outline='#ff9933') + + + +bot = tk.Button(window,text='添加运算节点',bg='#ffffcc',fg='black',) +bot.place(x=500,y=340,width=80,height=30) +bot = tk.Button(window,text='添加数值节点',bg='#ffffcc',fg='black',) +bot.place(x=500,y=375,width=80,height=30) +bot = tk.Button(window,text='改变运算输入',bg='#ffffcc',fg='black',) +bot.place(x=500,y=410,width=80,height=30) +bot = tk.Button(window,text='改变节点运算',bg='#ffffcc',fg='black',) +bot.place(x=500,y=445,width=80,height=30) +bot = tk.Button(window,text='数值节点交换',bg='#ffffcc',fg='black',) +bot.place(x=500,y=480,width=80,height=30) +bot = tk.Button(window,text='产生表达式',bg='#ffffcc',fg='black',) +bot.place(x=500,y=515,width=80,height=30) +''' + + +window.mainloop() + + +# if __name__ == "__main__": +# # 初始化Tree类的实例 +# tree = Tree() +# +# # 调用calculate方法,并传递要计算的节点作为参数 +# result = tree.calculate(tree.Node[3]) +# +# # 在这里对result进行后续操作,或者输出它 +# print(result) + diff --git a/test.py b/test.py new file mode 100644 index 0000000..caea306 --- /dev/null +++ b/test.py @@ -0,0 +1,63 @@ +import random +import tkinter as tk +from anytree import Node, RenderTree + +class Game: + def __init__(self): + self.root = tk.Tk() + self.root.title("24点游戏") + self.root.geometry("400x300") + self.root.resizable(False, False) + + self.numbers = [random.randint(1, 9) for _ in range(4)] + self.expression = tk.StringVar() + self.expression.set("输入表达式") + + self.number_labels = [] + for i in range(4): + label = tk.Label(self.root, text=str(self.numbers[i]), font=("Arial", 24)) + label.place(x=50 + i * 80, y=50) + self.number_labels.append(label) + + input_entry = tk.Entry(self.root, textvariable=self.expression, font=("Arial", 24)) + input_entry.place(x=50, y=150) + + calculate_button = tk.Button(self.root, text="计算", font=("Arial", 24), command=self.calculate) + calculate_button.place(x=250, y=150) + + self.result_label = tk.Label(self.root, text="", font=("Arial", 24)) + self.result_label.place(x=50, y=200) + + def calculate(self): + try: + root_node = Node("root") + expression = self.expression.get() + for char in expression: + if char.isdigit(): + node = Node(char, parent=root_node) + elif char == "+": + node = Node(char, parent=root_node) + elif char == "-": + node = Node(char, parent=root_node) + elif char == "*": + node = Node(char, parent=root_node) + elif char == "/": + node = Node(char, parent=root_node) + else: + raise Exception("Invalid character") + + result = eval(expression) + if result == 24: + self.result_label.config(text="正确") + else: + self.result_label.config(text="错误") + + for pre, fill, node in RenderTree(root_node): + print("%s%s" % (pre, node.name)) + + except Exception as e: + print(e) + self.result_label.config(text="错误") + +game = Game() +game.root.mainloop()