[Up]

Pentomino (wxPython版)

ネット上に公開されていたPythonのPentominoプログラムを、wxPythonを用いて表示するように改変した。 特に大きな問題はなかっったが、途中でプログラムを止めるための工夫が必要であった。

wxPythonでのGraphicsなどの参考になる。

#
# Pentomino puzzle solver
#    Jean-Claude Rimbault (pynokio.org, 2005)
#
#    modified for wx
#       14-november-2011 
#       by keiji imoto
#          department of information physiology
#          national institute for physiological sciences
#          okazaki, japan
#  

import wx

class Pentomino():

    def __init__(self, parent):

        self.parent = parent
        self.w = 10
        self.h = 6
        self.board = ['#'] * 160

        for row in range(self.w):
            for col in range(self.h):
                self.board[row*10+col+11] = ' '

        self.runmode = 0
        self.n = 0

        self.pieces = [ 'C', 'X', 'T', 'Y', 'F', 'W', 
                        'P', 'I', 'S', 'L', 'V', 'N' ]
        self.shapes = {
            'C': ((0, 1, 10, 20, 21),
                (0, 1, 11, 20, 21),
                (0, -10, -9, -8, 2),
                (0, 10, 11, 12, 2)),
            'F': ((0, 1, -9, 2, 12),
                (0, 1, 11, 2, -8),
                (0, 10, 11, 21, 12),
                (0, -10, -9, -19, -8),
                (0, 1, 11, 21, 12),
                (0, 1, -9, -19, -8),
                (0, 1, 11, -9, 12),
                (0, 1, 11, -9, -8)),
            'I': ((0, 1, 2, 3, 4),
                (0, 10, 20, 30, 40)),
            'L': ((0, 1, 2, 3, 13),
                (0, 1, 2, 3, -7),
                (0, 10, 20, 30, 1),
                (0, -10, -20, -30, 1),
                (0, 1, 11, 21, 31),
                (0, 1, -9, -19, -29),
                (0, 10, 1, 2, 3),
                (0, -10, 1, 2, 3)),
            'N': ((0, 1, 11, 12, 13),
                (0, 1, -9, -8, -7),
                (0, 1, 2, 12, 13),
                (0, 1, 2, -8, -7),
                (0, 10, 20, 21, 31),
                (0, 10, 20, 19, 29),
                (0, 10, 11, 21, 31),
                (0, 10, 9, 19, 29)),
            'P': ((0, 1, 2, 11, 12),
                (0, 1, 2, -9, -8),
                (0, 1, 2, 10, 11),
                (0, 1, 2, -10, -9),
                (0, 1, 10, 11, 20),
                (0, 1, 10, 11, 21),
                (0, 1, -10, -9, -20),
                (0, 1, -10, -9, -19)),
            'S': ((0, 1, 11, 21, 22),
                (0, 1, -9, -19, -18),
                (0, 10, 11, 12, 22),
                (0, -10, -9, -8, -18)),
            'T': ((0, 1, 11, 21, 2),
                (0, 1, -9, -19, 2),
                (0, 1, 2, -8, 12),
                (0, 10, -10, 1, 2)),
            'V': ((0, 1, 2, 12, 22),
                (0, 1, 2, -8, -18),
                (0, 1, 2, 10, 20),
                (0, 1, 2, -10, -20)),
            'W': ((0, 1, 11, 12, 22),
                (0, 1, -9, -8, -18),
                (0, 10, 11, 21, 22),
                (0, -10, -9, -19, -18)),
            'X': ((0, -9, 1, 11, 2),),
            'Y': ((0, 1, 2, 3, 12),
                (0, 1, 2, 3, -8),
                (0, 10, 20, 30, 11),
                (0, -10, -20, -30, -9),
                (0, 1, 11, 21, -9),
                (0, 1, -9, -19, 11),
                (0, 11, 1, 2, 3),
                (0, -9, 1, 2, 3))
        }       
    
    def display(self):
        self.parent.statusbar.SetStatusText('n = ' + str(self.n))
        self.panel.Refresh()
        self.panel.Update()

#
# main loop
#
    def solve(self):
        for q in range(len(self.board)):
            try:
                if self.board[q] == ' ':
                    for p in self.pieces:
                        for s in self.shapes[p]:
                            for c in s:
                                for d in s:
                                    if self.board[q+d-c] != ' ':
                                        break
                                else:
                                    for d in s:
                                        self.board[q+d-c] = p
                                    i = self.pieces.index(p)
                                    self.pieces.remove(p)
                                    if not self.pieces:
                                        self.n += 1
                                        self.display()
                                    else:
                                        if self.runmode:
                                            self.display()
                                        self.solve()
                                    self.pieces.insert(i, p)
                                    for d in s:
                                        self.board[q+d-c] = ' '
                    return
            except(KeyboardInterrupt, SystemExit):
                raise

    def start(self, event):
        self.solve()

class Frame(wx.Frame):

    def __init__(self, parent, id, title, ww, wh):
        wx.Frame.__init__(self, parent, id, title, size=(ww, wh))

        self.pen = Pentomino(self)

        self.panel = Panel(self, self.pen)
        self.pen.panel = self.panel

        self.isRunning = False


        self.statusbar = self.CreateStatusBar()
        self.startButton = wx.Button(self, wx.ID_ANY, 'Start', (220,230))
        self.Bind(wx.EVT_BUTTON, self.buttonControl)

        self.Centre()
        self.Show(True)


    def buttonControl(self, event):

        if self.isRunning == False:
            self.pen.start(event)
            isRunning = True


class Panel(wx.Panel):

    def __init__(self, parent, pen):
        wx.Panel.__init__(self, parent)

        self.pen = pen
        self.w = self.pen.w
        self.h = self.pen.h
 
        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.SetFocus()

        self.colors = {
            ' ': (0,0,0),
            'X': (0xEF, 0x84, 0x5c), 
            'T': (0xF9, 0xC2, 0x70),
            'C': (0xFF, 0xF6, 0x7F),
            'W': (0xC1, 0xDB, 0x81),  
            'I': (0x69, 0xBD, 0x83), 
            'S': (0x61, 0xC1, 0xBE),
            'F': (0x54, 0xC3, 0xF1),
            'P': (0x6C, 0x9B, 0xD2), 
            'L': (0x79, 0x6B, 0xAF),
            'V': (0xBA, 0x79, 0xB1),
            'Y': (0xEE, 0x87, 0xB4),
            'N': (0xEF, 0x85, 0x8C),
        }

        self.light = {
            ' ': (0,0,0),
 	    'X': (0xF8, 0xC5, 0xAC),
            'T': (0xFC, 0xE2, 0xBA),
            'C': (0xFF, 0xFB, 0xC7),
            'W': (0xE2, 0xEE, 0xC5),
            'I': (0xBE, 0xDF, 0xC2),
            'S': (0xBC, 0xE1, 0xDF),
            'F': (0xBA, 0xE3, 0xF9),
            'P': (0xBB, 0xCC, 0xE9),
            'L': (0xBB, 0xB3, 0xD8),
            'V': (0xDB, 0xBE, 0xDA),
            'Y': (0xF7, 0xC9, 0xDD),
            'N': (0xF7, 0xC7, 0xC6),
        }

        self.dark = {
            ' ': (0, 0, 0),
            'X': (0xE6, 0x00, 0x12),
            'T': (0xF3, 0x98, 0x00),
            'C': (0xFF, 0xF1, 0x00),
            'W': (0x8F, 0xC3, 0x1F),
            'I': (0x00, 0x99, 0x44),
            'S': (0x00, 0x9E, 0x96),
            'F': (0x00, 0xA0, 0xE9),
            'P': (0x00, 0x68, 0xB7),
            'L': (0x1D, 0x20, 0x88),
            'V': (0x92, 0x07, 0x83),
            'Y': (0xE4, 0x00, 0x7F),
            'N': (0xE5, 0x00, 0x4F),
        }



    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        for col in range(self.h):
            for row in range(self.w):
                x = 30*row + 20
                y = 30*col + 40
                c = self.pen.board[row*10+col+11]

                dc.SetBrush(wx.Brush(self.colors[c]))
                dc.DrawRectangle(x, y, 30, 30)

                dc.SetPen(wx.Pen(self.light[c]))
                dc.DrawLine(x, y + 29, x, y)
                dc.DrawLine(x, y, x + 29, y)

                dc.SetPen(wx.Pen(self.dark[c]))
                dc.DrawLine(x + 1, y + 29, x + 29, y + 29)
                dc.DrawLine(x + 29, y + 29, x + 29, y + 1)

def main():

    app   = wx.App()
    frame = Frame(None, -1, 'Pentomino', 340, 300)
    app.MainLoop()    

if __name__ == '__main__':
    main()

[Up]