from email import message
import tkinter
from turtle import reset
import numpy as np
import matplotlib.pyplot as plt
import tkinter.messagebox
from tkinter import *
from PIL import Image, ImageTk
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
#存储已访问的节点
class State:
def __init__(self,a,b,prev,step,operation):
self.a=a #A现有水的升数
self.b=b #B现有水的升数
self.prev=prev #父节点指针
self.step=step #节点数,也就是记录步数
self.operation=operation
visited=[[False for i in range(1000)]for j in range(1000)]
#广度优先算法(BFS)
def BFS(capativy_a,capativy_b,left_c,order):
queue=[]
s=State(a=0,b=0,prev=None,step=0,operation=None)
queue.append(s)
visited[0][0]=True
while queue:
state=queue.pop(0)
for i in range(6):
a ,b ,operation =None,None,None
if i==0:
operation = "将杯子A的水倒空"
a=0
b=state.b
elif i==1:
operation = "将杯子B的水倒空"
a=state.a
b=0
elif i==2:
operation = "将杯子A的水倒满"
a=capativy_a
b=state.b
elif i==3:
operation = "将杯子B的水倒满"
b=capativy_b
a=state.a
elif i==4:#将杯子A的水倒入杯子B中
if capativy_b-state.b>state.a:
operation = "将杯子A的水倒入杯子B,直至杯子A被倒空"
a=0
b=state.a+state.b
else :
operation = "将杯子A的水倒入杯子B,直至杯子B被倒满"
b=capativy_b
a=state.a-(capativy_b-state.b)
elif i==5:#将杯子B的水倒入杯子A中
if capativy_a-state.a>state.b:
operation = "杯子B中的水倒入杯子A中,直至杯子B被倒空"
b=0
a=state.a+state.b
else:
operation = "杯子B中的水倒入杯子A中,直至杯子A被倒满"
a=capativy_a
b=state.b-(capativy_a-state.a)
if not visited[a][b]:
new_state=State(a=a,b=b,prev=state,step=state.step+1,operation=operation)
visited[a][b]=True
queue.append(new_state)
#order_check(str(order))
if order == 'a' or order == 'A':
if left_c==a:
return new_state
elif order == 'b' or order == 'B':
if left_c==b:
return new_state
return None
def get_path(state,x_axis,y_axis):
path=[]
queue_a=[]
queue_b=[]
while state.prev:
queue_a.append(state.a)
queue_b.append(state.b)
path.append(state.operation)
state = state.prev
i=len(path)
queue_a.append(0)
queue_b.append(0)
queue_a.reverse()
queue_b.reverse()
plot_map(queue_a,queue_b,x_axis,y_axis,i)
return path[::-1]
#祖贝等式Ax+By=C
def gcd(A,B,C):
if A > B:
min = B
else:
min = A
for i in range(1,min+1):
#满足公因数的条件:
if (A % i == 0) and (B % i == 0):
c = i
if C % c != 0:
tkinter.messagebox.showerror(title="警告",message="问题无解")
exit()
def order_check(order):
if str(order) == 'a' or str(order) == 'A' or str(order) == 'b' or str(order) == 'B':
return order
else:
tkinter.messagebox.showerror(title="警告",message="错误的数据格式")
exit()
def plot_map(list_1,list_2,x_axis,y_axis,circle):
x_ticks=range(x_axis)
y_ticks=range(y_axis)
plt.axis([0,x_axis,0,y_axis])
plt.grid(True, linestyle="--", alpha=1)
plt.title("取水问题的可视化"+" "+"解决方案步数:"+str(circle))
plt.xlabel("水杯A的容量")
plt.ylabel("水杯B的容量")
plt.xticks(x_ticks,fontsize=18)
plt.yticks(y_ticks,fontsize=18)
for i in range(0,circle):
plt.annotate(i+1,xy=(list_1[i+1], list_2[i+1]),xytext=(list_1[i],list_2[i]),arrowprops=dict(facecolor='black', shrink=0.05),zorder=5)
#plt.axis([0,x_axis,0,y_axis])
plt.plot(list_1,list_2)
plt.show()
def main():
root = tkinter.Tk()
root.title("取水问题 V1.0")
root.minsize(600, 400) #初始化窗口大小
root.maxsize(1000,600) #放大之后窗口大小
labelt = tkinter.Label(root, text= "取水问题")
labelt.place(relx = 0.4, rely = 0.10)
labelt1 = tkinter.Label(root, text= "请确保您输入的数据满足以下要求:")
labelt1.place(relx = 0.2, rely = 0.2)
labelt2 = tkinter.Label(root, text= "1、两水杯容量应该互质;")
labelt2.place(relx = 0.2, rely = 0.25)
labelt3 = tkinter.Label(root, text= "2、两水杯容量的最大值应该大于想获得的升数。")
labelt3.place(relx = 0.2, rely = 0.3)
#创建输入框
label1 = tkinter.Label(root, text= "请定义水杯A的容量(1-1000):")
label1.place(relx = 0.12, rely = 0.4) #relx距离左边框的距离, rely距离上边框的距离
entry1 = tkinter.Entry(root)
entry1.place(relx = 0.5, rely = 0.4, width = 200, height = 20)
label2 = tkinter.Label(root, text= "请定义水杯B的容量(1-1000):")
label2.place(relx = 0.12, rely = 0.5)
entry2 = tkinter.Entry(root)
entry2.place(relx = 0.5, rely = 0.5, width = 200, height = 20)
label3 = tkinter.Label(root, text= "请输入想获得的升数:")
label3.place(relx = 0.12, rely = 0.6)
entry3 = tkinter.Entry(root)
entry3.place(relx = 0.5, rely = 0.6, width = 200, height = 20)
label4_1 = tkinter.Label(root, text= "你想在哪个水杯中获得所要求的水:")
label4_1.place(relx = 0.12, rely = 0.7)
label4_2 = tkinter.Label(root, text= "(A/B,大小写均可):")
label4_2.place(relx = 0.12, rely = 0.75)
entry4 = tkinter.Entry(root)
entry4.place(relx = 0.5, rely = 0.7, width = 200, height = 20)
#创建按钮
button1 = tkinter.Button(root, text="计算")
button1.place(relx = 0.38, rely = 0.8, width = 80)
button2 = tkinter.Button(root, text="计算流程")
button2.place(relx = 0.6, rely = 0.1, width = 80)
label5 = tkinter.Label(root, text= "此版本每次成功计算后需要重新打开。")
label5.place(relx = 0.3, rely = 0.9)
def liuchen(self):
global photo
top = Toplevel()
top.title("流程图")
top.geometry("600x550")
img = Image.open('E:\取水问题\流程图.png')
photo = ImageTk.PhotoImage(img)
label_img = tkinter.Label(top, image=photo)
label_img.grid(row=1, column=0, pady=10)
#img_png = Tkinter.PhotoImage(file = 'E:\倒水问题\流程图.png')
#label_img = Tkinter.Label(root, image = img_png)
#label_img.pack()
def program(self):
capativy_a = int(entry1.get()) #获取第一个输入框的值
capativy_b = int(entry2.get()) #获取第二个输入框的值
left_c = int(entry3.get()) #获取第三个输入框的值
order = str(entry4.get()) #获取第四个输入框的值
#首先判断数据格式是否正确,如果错误直接结束程序
if capativy_a==0 or capativy_b==0 or left_c==0 or left_c>max(capativy_a,capativy_b) or capativy_a%capativy_b==0 or capativy_b%capativy_a==0:
tkinter.messagebox.showerror(title="警告",message="错误的数据格式")
#判断所给数据是否有解,如果无解直接结束程序
gcd(capativy_a,capativy_b,left_c)
order_check(order)
result = BFS(capativy_a,capativy_b,left_c,order)
get_path(result,capativy_a,capativy_b)
button1.bind("<ButtonRelease-1>",program)
button2.bind("<ButtonRelease-1>",liuchen)
root.mainloop()
return
main()
这篇主要是代码,之后会上传相关的理论部分。

2543

被折叠的 条评论
为什么被折叠?



