Welcome, guest | Sign In | My Account | Store | Cart
#author: A. Polino
import wx
import sys


## make sure the windows is focused than press any button, and the program will move a plate. keep  ## pressing until the problem is solved
## by default it will display 5 plates. To change this, you have to call the script with a second   ## argument, wich is the number of plates (max 10)

def gen_hanoi(stack, start=1, temp=2, goal=3):
    if stack == 2:
        yield start, temp
        yield start, goal
        yield temp, goal
    else:
        for x in gen_hanoi(stack - 1, start, goal, temp):
            yield x
        yield start, goal
        for x in gen_hanoi(stack - 1, temp, start, goal):
            yield x


class Plate(object):
    def __init__(self, x_len, x_start):
        self.x_len = x_len
        self.x_start = x_start


def create_plates(num):
    assert num <= 10
    x_start = 10
    x_len = 100
    plates = []
    for x in xrange(num):
        plates.append(Plate(x_len, x_start))
        x_len -= 10
        x_start += 5
    return plates


class HanoiWindow(wx.Window):
    def __init__(self, parent, num):
        wx.Window.__init__(self, parent, id=-1, pos = wx.Point(0, 0),
                           size=wx.DefaultSize, style=wx.SUNKEN_BORDER|
                           wx.WANTS_CHARS|wx.FULL_REPAINT_ON_RESIZE)
        self.SetBackgroundColour(wx.NamedColour('white'))
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
        self.towers = [create_plates(num), [], []]
        self.solver = gen_hanoi(num)

    def OnPaint(self, evt):
        def draw_rect(x_len, x_start, y_start):
            dc = wx.PaintDC(self)
            font = dc.GetFont()
            font.SetPointSize(15)
            dc.SetFont(font)
            size, colour = 2, wx.NamedColour('black')
            dc.SetPen(wx.Pen(colour, size, wx.SOLID))
            point = wx.Point(x_start, y_start)
            dc.DrawLines([point, point + wx.Point(x_len, 0)])
            dc.DrawLines([point - wx.Point(0, 5), point + wx.Point(x_len, 0) - wx.Point(0, 5)])
            dc.DrawLines([point, point - wx.Point(0, 5)])
            dc.DrawLines([point + wx.Point(x_len, 0), point - wx.Point(0, 5) + wx.Point(x_len, 0)])

        w, h = self.GetClientSizeTuple()
        buffer = wx.EmptyBitmap(w, h)
        dc = wx.PaintDC(self)
        font = dc.GetFont()
        font.SetPointSize(15)
        dc.SetFont(font)
        msg = 'Hanoi Towers'
        w, h = dc.GetTextExtent(msg)
        dc.DrawText(msg, 200, 20)
        size, colour = 8, wx.NamedColour('black')
        dc.SetPen(wx.Pen(colour, size, wx.SOLID))
        for num in xrange(len(self.towers)):
            y_start = 300
            tower = self.towers[num]
            num = num * 200 + 10
            point = wx.Point(num, y_start)
            dc.DrawLines([point, point + wx.Point(120, 0)]) #base
            ## plates
            for plate in tower:
                y_start -= 10
                draw_rect(plate.x_len, num + plate.x_start, y_start)

    def OnKeyUp(self, evt):
        try:
            from_, to = self.solver.next()
            self.towers[to-1].append(self.towers[from_-1].pop())
            self.Refresh()
        except StopIteration:
            wx.MessageBox('Problem Solved!', 'Problem solved', wx.OK)
                

class HanoiFrame(wx.Frame):
    def __init__(self, title, num):
        wx.Frame.__init__(self, parent=None, id=-1,
                          title=title, size=(600, 500), pos=(200, 200))
        self.Window = HanoiWindow(self, num)
        self.Bind(wx.EVT_CLOSE, self.close_frame)

    def close_frame(self, evt):
        sys.exit(0)


class HanoiApp(wx.App):
    def OnInit(self):
        if len(sys.argv) < 2:
            num = 5
        else:
            num = int(sys.argv[1])
        hano = HanoiFrame('Hanoi Towers', num)
        hano.Show(True)
        self.SetTopWindow(hano)
        return True


if __name__ == '__main__':
    fh = HanoiApp(0)
    fh.MainLoop()

Diff to Previous Revision

--- revision 2 2010-12-21 21:08:52
+++ revision 3 2010-12-21 21:11:33
@@ -3,6 +3,8 @@
 import sys
 
 
+## make sure the windows is focused than press any button, and the program will move a plate. keep  ## pressing until the problem is solved
+## by default it will display 5 plates. To change this, you have to call the script with a second   ## argument, wich is the number of plates (max 10)
 
 def gen_hanoi(stack, start=1, temp=2, goal=3):
     if stack == 2:

History