[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