22import time
33import math
44
5- TubeX0 = 50
5+ # 以下为全局变量
6+ TubeX0 = 50 # 栈的左上角坐标位置
67TubeY0 = 150
7- TubeDeep = 5
8- BallRaius = 50
9-
10- QueueX0 = 200
11- QueueY0 = 100
12-
13- MoveStep = 100
14- Speed = 2
15-
16- TubeX1 = TubeX0 + BallRaius
8+ TubeDeep = 5 # 栈的深度(能容纳5个球)
9+ BallRaius = 50 # 每个球的半径
10+ # 预先计算栈的其他坐标点
11+ TubeX1 = TubeX0 + BallRaius # 栈底部小球的中心坐标
1712TubeY1 = TubeY0 + BallRaius * TubeDeep
18- TubeTopX = TubeX0 + BallRaius / 2
13+ TubeTopX = TubeX0 + BallRaius / 2 # 栈顶部出入口外的中心坐标
1914TubeTopY = TubeY0 - BallRaius / 2 - BallRaius / 4
2015
16+ QueueX0 = 200 # 待进栈小球的坐标位置
17+ QueueY0 = 100
18+
19+ # 运算动画时的相关坐标
2120EvalX1 = TubeX1 + (BallRaius + 2 )* 2
2221EvalY = TubeY1 - BallRaius / 2
2322EvalX2 = EvalX1 + (BallRaius + 2 )* 2
2423EvalXe = (EvalX1 + EvalX2 )/ 2
2524
25+ Speed = 2 # 小球移动的速度
2626
27- class Ball :
28- def __init__ (self , canvas , txt , pos ):
27+ class Ball : # window:TK窗口对象,canvas:画布对象,txt:小球的内容,txt:小球的坐标
28+ def __init__ (self , window , canvas , txt , pos ):
29+ self .window = window
2930 self .canvas = canvas
3031 self .txt = txt
31- # self.index = index
3232
3333 self .ballId = self .canvas .create_oval (
3434 pos [0 ]- BallRaius / 2 , pos [1 ]- BallRaius /
@@ -41,35 +41,33 @@ def __init__(self, canvas, txt, pos):
4141 def getTxt (self ):
4242 return self .txt
4343
44- def getIndex (self ):
45- return self .index
44+ # def getIndex(self):
45+ # return self.index
4646
4747 def getPos (self ):
4848 pos = self .canvas .coords (self .ballId )
4949 return [(pos [0 ]+ pos [2 ])/ 2 , (pos [1 ]+ pos [3 ])/ 2 ]
5050
5151 def animate (self , poly ):
52- for pos in poly :
53- startPos = self .getPos ()
54- distance = self .distance (startPos , pos )
55- # dx = (pos[0]-startPos[0])/MoveStep
56- # dy = (pos[1]-startPos[1])/MoveStep
57- while not self .match (self .getPos (), pos ): # 测试是否到达终点
58- global window
52+ for pos in poly : # 遍历路径的每一个途经点
53+ startPos = self .getPos () # 获得开始位置坐标
54+ distance = self .distance (startPos , pos ) # 获得每一步需移动的x和y的步长(可能为负数)
55+ while not self .match (self .getPos (), pos ): # 测试是否到途经点
56+ # 根据x和y的步长,分别移动小球和小球里的数字(符号)
5957 self .canvas .move (self .ballId , distance [0 ], distance [1 ])
6058 self .canvas .move (self .numId , distance [0 ], distance [1 ])
61- window .update ()
59+ self . window .update ()
6260 time .sleep (0.01 )
6361
6462 def distance (self , pos1 , pos2 ):
65- dx = pos2 [0 ]- pos1 [0 ]
63+ dx = pos2 [0 ]- pos1 [0 ] # 分别计算x坐标和y坐标的距离
6664 dy = pos2 [1 ]- pos1 [1 ]
67- dist = math .sqrt (dx * dx + dy * dy ) # 两点的距离
68- dtime = dist / Speed # 走完动画花的时间
69- return [dx / dtime , dy / dtime ]
65+ dist = math .sqrt (dx * dx + dy * dy ) # 利用勾股定理计算两点的距离
66+ dtime = dist / Speed # 走完行程所用的时间
67+ return [dx / dtime , dy / dtime ] # 返回每次移动的步长
7068
71- def match (self , pos1 , pos2 , mat = 1 ):
72- if abs (pos2 [0 ]- pos1 [0 ]) < mat and abs (pos2 [1 ]- pos1 [1 ]) < mat :
69+ def match (self , pos1 , pos2 , mat = 1 ): # 判断两个坐标点pos1和pos2是否重合,mat为精度,即mat=1时,误差+-0.5都算重合
70+ if abs (pos2 [0 ]- pos1 [0 ]) < mat and abs (pos2 [1 ]- pos1 [1 ]) < mat : #简单计算而不用勾股定理计算距离
7371 return True
7472 return False
7573
@@ -78,10 +76,11 @@ def destory(self):
7876 self .canvas .delete (self .numId )
7977
8078
81- class Stack :
79+ class Stack : # canvas:画布对象
8280 def __init__ (self , canvas ):
8381 self .stack = []
8482 self .canvas = canvas
83+ # 画出栈的外形
8584 self .canvas .create_line (TubeX0 - 2 , TubeY0 - 2 ,
8685 TubeX0 - 2 , TubeY1 + 2 ,
8786 TubeX1 + 2 , TubeY1 + 2 ,
@@ -90,21 +89,19 @@ def __init__(self, canvas):
9089
9190 def push (self , ball ):
9291 index = len (self .stack )
93- # ball = Ball(self.canvas, number, [
94- # TubeX0+BallRaius/2, TubeY1-(index*BallRaius)-BallRaius/2])
95- ball .animate (
96- [[TubeTopX , TubeTopY ], [TubeTopX , TubeY1 - (index * BallRaius )- BallRaius / 2 ]])
92+ # 小球移动的动画,参数是两个坐标点,先到栈口上部,然后落到栈里
93+ ball .animate ([[TubeTopX , TubeTopY ], [TubeTopX , TubeY1 - (index * BallRaius )- BallRaius / 2 ]])
9794 self .stack .append (ball )
9895
9996 def pop (self ):
10097 index = len (self .stack )- 1
10198 ball = self .stack .pop ()
99+ # 出栈动画,小球移动到栈口上方
102100 ball .animate ([[TubeTopX , TubeTopY ]])
103101 return ball
104102
105103
106104def main ():
107- global window
108105
109106 strBuf = '65+1-5*' # 需解析的字符串
110107 queue = [] # 等待处理的球的队列
@@ -121,7 +118,7 @@ def main():
121118 # 生成球的队列
122119 index = 0
123120 for char in strBuf :
124- ball = Ball (canvas , char , [QueueX0 + BallRaius * index , QueueY0 ])
121+ ball = Ball (window , canvas , char , [QueueX0 + BallRaius * index , QueueY0 ])
125122 queue .append (ball )
126123 # print(ball.getPos())
127124 index += 1
@@ -131,6 +128,7 @@ def main():
131128 if c .isnumeric (): # 判断球内的字符是否数字
132129 stk .push (ball ) # 是数字,球就进栈
133130 elif c == '+' or c == '-' or c == '*' or c == '/' :
131+ #下面几个animate方法演示计算过程的动画
134132 ball .animate ([[EvalXe , EvalY ]])
135133
136134 ball1 = stk .pop ()
@@ -143,9 +141,9 @@ def main():
143141 a2 = ball2 .getTxt ()
144142 ball1 .animate ([[EvalXe , EvalY ]])
145143 ball2 .animate ([[EvalXe , EvalY ]])
146-
144+
147145 result = eval (a1 + c + a2 )
148- newBall = Ball (canvas , str (result ), ball .getPos ())
146+ newBall = Ball (window , canvas , str (result ), ball .getPos ())
149147
150148 ball1 .destory ()
151149 ball2 .destory ()
0 commit comments