-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaniStack.py
More file actions
163 lines (129 loc) · 5.65 KB
/
aniStack.py
File metadata and controls
163 lines (129 loc) · 5.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from tkinter import *
import time
import math
# 以下为全局变量
TubeX0 = 50 # 栈的左上角坐标位置
TubeY0 = 150
TubeDeep = 5 # 栈的深度(能容纳5个球)
BallRaius = 50 # 每个球的半径
# 预先计算栈的其他坐标点
TubeX1 = TubeX0+BallRaius # 栈底部小球的中心坐标
TubeY1 = TubeY0+BallRaius*TubeDeep
TubeTopX = TubeX0+BallRaius/2 # 栈顶部出入口外的中心坐标
TubeTopY = TubeY0 - BallRaius/2-BallRaius/4
QueueX0 = 200 # 待进栈小球的坐标位置
QueueY0 = 100
# 运算动画时的相关坐标
EvalX1 = TubeX1 + (BallRaius+2)*2
EvalY = TubeY1-BallRaius/2
EvalX2 = EvalX1 + (BallRaius+2)*2
EvalXe = (EvalX1+EvalX2)/2
Speed = 2 # 小球移动的速度
class Ball: # window:TK窗口对象,canvas:画布对象,txt:小球的内容,txt:小球的坐标
def __init__(self, window, canvas, txt, pos):
self.window = window
self.canvas = canvas
self.txt = txt
self.ballId = self.canvas.create_oval(
pos[0]-BallRaius/2, pos[1]-BallRaius /
2, pos[0]+BallRaius/2, pos[1]+BallRaius/2,
fill='green', outline='green')
self.numId = self.canvas.create_text(pos[0], pos[1],
text=self.txt, fill='yellow',
font=('', BallRaius-25))
def getTxt(self):
return self.txt
# def getIndex(self):
# return self.index
def getPos(self):
pos = self.canvas.coords(self.ballId)
return [(pos[0]+pos[2])/2, (pos[1]+pos[3])/2]
def animate(self, poly):
for pos in poly: # 遍历路径的每一个途经点
startPos = self.getPos() # 获得开始位置坐标
distance = self.distance(startPos, pos) # 获得每一步需移动的x和y的步长(可能为负数)
while not self.match(self.getPos(), pos): # 测试是否到途经点
# 根据x和y的步长,分别移动小球和小球里的数字(符号)
self.canvas.move(self.ballId, distance[0], distance[1])
self.canvas.move(self.numId, distance[0], distance[1])
self.window.update()
time.sleep(0.01)
def distance(self, pos1, pos2):
dx = pos2[0]-pos1[0] # 分别计算x坐标和y坐标的距离
dy = pos2[1]-pos1[1]
dist = math.sqrt(dx*dx+dy*dy) # 利用勾股定理计算两点的距离
dtime = dist/Speed # 走完行程所用的时间
return [dx/dtime, dy/dtime] # 返回每次移动的步长
def match(self, pos1, pos2, mat=1): # 判断两个坐标点pos1和pos2是否重合,mat为精度,即mat=1时,误差+-0.5都算重合
if abs(pos2[0]-pos1[0]) < mat and abs(pos2[1]-pos1[1]) < mat: #简单计算而不用勾股定理计算距离
return True
return False
def destory(self):
self.canvas.delete(self.ballId)
self.canvas.delete(self.numId)
class Stack: # canvas:画布对象
def __init__(self, canvas):
self.stack = []
self.canvas = canvas
# 画出栈的外形
self.canvas.create_line(TubeX0-2, TubeY0-2,
TubeX0-2, TubeY1+2,
TubeX1+2, TubeY1+2,
TubeX1+2, TubeY0-2,
width=4, fill='blue', joinstyle=BEVEL)
def push(self, ball):
index = len(self.stack)
# 小球移动的动画,参数是两个坐标点,先到栈口上部,然后落到栈里
ball.animate([[TubeTopX, TubeTopY], [TubeTopX, TubeY1-(index*BallRaius)-BallRaius/2]])
self.stack.append(ball)
def pop(self):
index = len(self.stack)-1
ball = self.stack.pop()
# 出栈动画,小球移动到栈口上方
ball.animate([[TubeTopX, TubeTopY]])
return ball
def main():
strBuf = '65+1-5*' # 需解析的字符串
queue = [] # 等待处理的球的队列
window = Tk()
window.title('Stack animate')
# window.geometry('640x480+50+50')
canvas = Canvas(window, width=640, height=480,)
canvas.pack()
stk = Stack(canvas)
# 生成球的队列
index = 0
for char in strBuf:
ball = Ball(window, canvas, char, [QueueX0+BallRaius*index, QueueY0])
queue.append(ball)
# print(ball.getPos())
index += 1
for ball in queue:
c = ball.getTxt()
if c.isnumeric(): # 判断球内的字符是否数字
stk.push(ball) # 是数字,球就进栈
elif c == '+' or c == '-' or c == '*' or c == '/':
#下面几个animate方法演示计算过程的动画
ball.animate([[EvalXe, EvalY]])
ball1 = stk.pop()
ball1.animate([[TubeTopX+BallRaius, TubeTopY], [EvalX1, EvalY]])
ball2 = stk.pop()
ball2.animate([[TubeTopX+BallRaius, TubeTopY], [EvalX2, EvalY]])
a1 = ball1.getTxt()
a2 = ball2.getTxt()
ball1.animate([[EvalXe, EvalY]])
ball2.animate([[EvalXe, EvalY]])
result = eval(a1+c+a2)
newBall = Ball(window, canvas, str(result), ball.getPos())
ball1.destory()
ball2.destory()
ball.destory()
# ball.setTxt(str(result))
stk.push(newBall)
# 删除ball1,ball2
ball = stk.pop()
ball.animate([[EvalXe, EvalY]])
# time.sleep(1)
window.mainloop()
if __name__ == "__main__":
main()