[Tutor] request to run program on a Linux machine

fredb7 fredb7 at HotPOP.com
Mon Feb 16 14:18:03 EST 2004


Run smoothly and no error message on OS X.
Good job.

Hope this helps.

Fred


On 16-févr.-04, at 18:52, Gregor Lingl wrote:

> Hi!
>
> At the moment I unfortunately don't have a computer running
> Linux at hand, so ...
>
> ... is there anybody out there using a machine running
> Python 2.3 with Tkinter under Linux, who is willing
> to run the attached program and give me feedback concerning
> two questions:
>
> (1) Does the program run smoothly
>
> (2) Does it terminate without error-messages (TclError)
> when the window is closed while the animation is running
> (i. e. while a disc is moving).
> This can be seen e.g. when you run it from within IDLE or
> from the commandline of some console window ...
>
> Many thanks in advance
> Gregor
>
> P.S. A second posting concerning this Hanoi program,
> concerning some remarks on the problem mentioned above
> will follow.
>
> ## Animated Tower-Of-Hanoi game with Tkinter GUI
> ## author: Gregor Lingl, Vienna, Austria
> ## email: glingl at aon.at
> ## date: 16. 2. 2004
>
> from Tkinter import *
>
> class Disc:
>     """Movable Rectangle on a Tkinter Canvas"""
>     def __init__(self,cv,pos,length,height,colour):
>         """creates disc on given Canvas cv at given pos-ition"""
>         x0, y0 = pos
>         x1, x2 = x0-length/2.0, x0+length/2.0
>         y1, y2 = y0-height, y0
>         self.cv = cv
>         self.item = cv.create_rectangle(x1,y1,x2,y2,
>                                         fill = "#%02x%02x%02x" % 
> colour)
>     def move_to(self, x, y, speed):
>         """moves bottom center of disc to position (x,y).
>            speed is intended to assume values from 1 to 10"""
>         x1,y1,x2,y2 = self.cv.coords(self.item)
>         x0, y0 = (x1 + x2)/2, y2
>         dx, dy = x-x0, y-y0
>         d = (dx**2+dy**2)**0.5
>         steps = int(d/(10*speed-5)) + 1
>         dx, dy = dx/steps, dy/steps
>         for i in range(steps):
>             self.cv.move(self.item,dx,dy)
>             self.cv.update()
>             self.cv.after(20)
>
> class Tower(list):
>     """Hanoi tower designed as a subclass of built-in type list"""
>     def __init__(self, x, y, h):
>         """ creates an empty tower.
>             (x,y) is floor-level position of tower,
>             h is height of the discs. """
>         self.x = x
>         self.y = y
>         self.h = h
>     def top(self):
>         return self.x, self.y - len(self)*self.h
>
>
> class HanoiEngine:
>     """Plays the Hanoi-game on a given canvas."""
>     def __init__(self, canvas, nrOfDiscs, speed, moveCntDisplay=None):
>         """Sets Canvas to play on as well as default values for
>         number of discs and animation-speed.
>         moveCntDisplay is a function with 1 parameter, which 
> communicates
>         the count of the actual move to the GUI containing the
>         Hanoi-engine-canvas."""
>         self.cv = canvas
>         self.nrOfDiscs = nrOfDiscs
>         self.speed = speed
>         self.moveDisplay = moveCntDisplay
>         self.running = False
>         self.moveCnt = 0
>         self.discs = []
>         self.towerA = Tower( 80, 190, 15)
>         self.towerB = Tower(220, 190, 15)
>         self.towerC = Tower(360, 190, 15)
>         self.reset()
>
>     def hanoi(self, n, src, dest, temp):
>         """The classical recursive Towers-Of-Hanoi algorithm."""
>         if n > 0:
>             for x in self.hanoi(n-1, src, temp, dest): yield None
>             yield self.move(src, dest)
>             for x in self.hanoi(n-1, temp, dest, src): yield None
>
>     def move(self, src_tower, dest_tower):
>         """moves uppermost disc of source tower to top of destination
>         tower."""
>         self.moveCnt += 1
>         self.moveDisplay(self.moveCnt)
>         disc = src_tower.pop()
>         x1, y1 = src_tower.top()
>         x2, y2 = dest_tower.top()
>         disc.move_to(x1,20, self.speed)
>         disc.move_to(x2,20, self.speed)
>         disc.move_to(x2,y2, self.speed)
>         dest_tower.append(disc)
>
>     def reset(self):
>         """Setup of (a new) game."""
>         self.moveCnt = 0
>         self.moveDisplay(self.moveCnt)
>         while self.towerA: self.towerA.pop()
>         while self.towerB: self.towerB.pop()
>         while self.towerC: self.towerC.pop()
>         for s in self.discs:
>             self.cv.delete(s.item)
>         ## Fancy colouring of discs: red ===> blue
>         if self.nrOfDiscs > 1:
>             colour_diff = 255 // (self.nrOfDiscs-1)
>         else:
>             colour_diff = 0
>         for i in range(self.nrOfDiscs):  # setup towerA
>             length_diff = 100 // self.nrOfDiscs
>             length = 120 - i * length_diff
>             s = Disc( self.cv, self.towerA.top(), length, 13,
>                          (255-i*colour_diff, 0, i*colour_diff))
>             self.discs.append(s)
>             self.towerA.append(s)
>         self.HG = self.hanoi(self.nrOfDiscs,
>                              self.towerA, self.towerC, self.towerB)
>
>     def run(self):
>         """runs game ;-)
>         returns True if game is over, else False"""
>         self.running = True
>         try:
>             while self.running:
>                 result = self.step()
>             return result  # True iff done
>         except StopIteration:  # game over
>             return True
>         except TclError:   # for silently terminating in case of 
> window closing
>             return False
>
>     def step(self):
>         """performs one single step of the game,
>         returns True if finished, else False"""
>         self.HG.next()
>         return 2**self.nrOfDiscs-1 == self.moveCnt
>
>     def stop(self):
>         """ ;-) """
>         self.running = False
>
>
> class Hanoi:
>     """GUI for animated towers-of-Hanoi-game with upto 10 discs:"""
>
>     def displayMove(self, move):
>         """method to be passed to the Hanoi-engine as a callback
>         to report move-count"""
>         self.moveCntLbl.configure(text = "move:\n%d" % move)
>
>     def adjust_nr_of_discs(self, e):
>         """callback function for nr-of-discs-scale-widget"""
>         self.hEngine.nrOfDiscs = self.discs.get()
>         self.reset()
>
>     def adjust_speed(self, e):
>         """callback function for speeds-scale-widget"""
>         self.hEngine.speed = self.tempo.get()
>
>     def setState(self, STATE):
>         """most simple representation of a finite state machine"""
>         self.state = STATE
>         try:
>             if STATE == "START":
>                 self.discs.configure(state=NORMAL)
>                 self.discs.configure(fg="black")
>                 self.discsLbl.configure(fg="black")
>                 self.resetBtn.configure(state=DISABLED)
>                 self.startBtn.configure(text="start", state=NORMAL)
>                 self.stepBtn.configure(state=NORMAL)
>             elif STATE == "RUNNING":
>                 self.discs.configure(state=DISABLED)
>                 self.discs.configure(fg="gray70")
>                 self.discsLbl.configure(fg="gray70")
>                 self.resetBtn.configure(state=DISABLED)
>                 self.startBtn.configure(text="pause", state=NORMAL)
>                 self.stepBtn.configure(state=DISABLED)
>             elif STATE == "PAUSE":
>                 self.discs.configure(state=NORMAL)
>                 self.discs.configure(fg="black")
>                 self.discsLbl.configure(fg="black")
>                 self.resetBtn.configure(state=NORMAL)
>                 self.startBtn.configure(text="resume", state=NORMAL)
>                 self.stepBtn.configure(state=NORMAL)
>             elif STATE == "DONE":
>                 self.discs.configure(state=NORMAL)
>                 self.discs.configure(fg="black")
>                 self.discsLbl.configure(fg="black")
>                 self.resetBtn.configure(state=NORMAL)
>                 self.startBtn.configure(text="start", state=DISABLED)
>                 self.stepBtn.configure(state=DISABLED)
>             elif STATE == "TIMEOUT":
>                 self.discs.configure(state=DISABLED)
>                 self.discs.configure(fg="gray70")
>                 self.discsLbl.configure(fg="gray70")
>                 self.resetBtn.configure(state=DISABLED)
>                 self.startBtn.configure(state=DISABLED)
>                 self.stepBtn.configure(state=DISABLED)
>         except TclError:
>             pass
>
>     def reset(self):
>         """restores START state for a new game"""
>         self.hEngine.reset()
>         self.setState("START")
>
>     def start(self):
>         """callback function for start button, which also serves as
>         pause button. Makes hEngine running until done or 
> interrupted"""
>         if self.state in ["START", "PAUSE"]:
>             self.setState("RUNNING")
>             if self.hEngine.run():
>                 self.setState("DONE")
>             else:
>                 self.setState("PAUSE")
>         elif self.state == "RUNNING":
>             self.setState("TIMEOUT")
>             self.hEngine.stop()
>
>     def step(self):
>         """callback function for step button.
>         makes hEngine perform a single step"""
>         self.setState("TIMEOUT")
>         if self.hEngine.step():
>             self.setState("DONE")
>         else:
>             self.setState("PAUSE")
>
>     def __init__(self, nrOfDiscs, speed):
>         """builds GUI, constructs Hanoi-engine and puts it into START 
> state
>         then launches mainloop()"""
>         root = Tk()
>         root.title("TOWERS OF HANOI")
>         #root.protocol("WM_DELETE_WINDOW",root.quit) #counter 
> productive here!?
>         cv = Canvas(root,width=440,height=210, bg="gray90")
>         cv.pack()
>
>         fnt = ("Arial", 12, "bold")
>
>         attrFrame = Frame(root) #contains scales to adjust game's 
> attributes
>         self.discsLbl = Label(attrFrame, width=7, height=2, font=fnt,
>                               text="discs:\n")
>         self.discs = Scale(attrFrame, from_=1, to_=10, 
> orient=HORIZONTAL,
>                            font=fnt, length=75, showvalue=1, 
> repeatinterval=10,
>                            command=self.adjust_nr_of_discs)
>         self.discs.set(nrOfDiscs)
>         self.tempoLbl = Label(attrFrame, width=8,  height=2, font=fnt,
>                               text = "   speed:\n")
>         self.tempo = Scale(attrFrame, from_=1, to_=10, 
> orient=HORIZONTAL,
>                            font=fnt, length=100, 
> showvalue=1,repeatinterval=10,
>                            command = self.adjust_speed)
>         self.tempo.set(speed)
>         self.moveCntLbl= Label(attrFrame, width=5, height=2, font=fnt,
>                                padx=20, text=" move:\n0", 
> anchor=CENTER)
>         for widget in ( self.discsLbl, self.discs, self.tempoLbl, 
> self.tempo,
>                                                              
> self.moveCntLbl ):
>             widget.pack(side=LEFT)
>         attrFrame.pack(side=TOP)
>
>
>         ctrlFrame = Frame(root) # contains Buttons to control the game
>         self.resetBtn = Button(ctrlFrame, width=11, text="reset", 
> font=fnt,
>                                state = DISABLED, padx=15, command = 
> self.reset)
>         self.stepBtn  = Button(ctrlFrame, width=11, text="step", 
> font=fnt,
>                                state = NORMAL,  padx=15, command = 
> self.step)
>         self.startBtn = Button(ctrlFrame, width=11, text="start", 
> font=fnt,
>                                state = NORMAL,  padx=15, command = 
> self.start)
>         for widget in self.resetBtn, self.stepBtn, self.startBtn:
>             widget.pack(side=LEFT)
>         ctrlFrame.pack(side=TOP)
>
>         # setup of the scene
>         peg1 = cv.create_rectangle(  75,  40,  85, 190, 
> fill='darkgreen')
>         peg2 = cv.create_rectangle( 215,  40, 225, 190, 
> fill='darkgreen')
>         peg3 = cv.create_rectangle( 355,  40, 365, 190, 
> fill='darkgreen')
>         floor = cv.create_rectangle( 10, 191, 430, 200, fill='black')
>
>         self.hEngine = HanoiEngine(cv, nrOfDiscs, speed, 
> self.displayMove)
>         self.state = "START"
>
>         root.mainloop()
>
> if __name__  == "__main__":
>     Hanoi(4,5)
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor




More information about the Tutor mailing list