LifeGameを書き直してみた。

#!/usr/bin/env python

import Tkinter

class lifeGameBoard():
    def __init__(self,w,h):
        self.w = w
        self.h = h
        self.map = {}
    def increment(self):
        w, h = self.w, self.h
        aroundMap = {}
        for x,y in self.map.keys():
            for ii in range(x-1,x+2):
                for jj in range(y-1,y+2):
                    if 0 <= ii < w and 0 <= jj < h and (x != ii or y != jj):
                        if (ii,jj) in aroundMap:
                            aroundMap[ii,jj] = aroundMap[ii,jj] + 1
                        else:
                            aroundMap[ii,jj] = 1
        tmpMap = {}
        for x,y in self.map.keys():
            if (x,y) in aroundMap and (aroundMap[x,y]==2 or aroundMap[x,y]==3):
                tmpMap[x,y] = 1
        for x,y in aroundMap.keys():
            if aroundMap[x,y]==3:
                tmpMap[x,y] = 1
        self.map = tmpMap
            
    def press(self,w,h):
        if (w,h) in self.map:
            del self.map[w,h]
        else:
            self.map[w,h] = 1
        
class Lifegame:
    def __init__(self):
        window = Tkinter.Tk()
        self.width = 80
        self.height = 60
        self.scale = 10
        self.gameBoard = lifeGameBoard(self.width,self.height)
        self.objects = []

        self.canvas = Tkinter.Canvas(window, bg="white",
                                     width=self.width*self.scale,
                                     height=self.height*self.scale)
        self.canvas.pack()

        self.move = Tkinter.Button(window, text="increment",
                                   command=self.increment)
        self.move.pack(side=Tkinter.RIGHT)

        self.chooser = Tkinter.Scale(window, from_=1, to=10000, orient=Tkinter.HORIZONTAL)
        self.chooser.pack(side=Tkinter.LEFT)

        self.canvas.bind("<ButtonPress-1>",self.pressCanvas)
        self.canvas.bind("<B1-Motion>",self.pressCanvas)
        self.window = window

        window.mainloop()

    def increment(self,count=-1):
        if count==-1:
            count = self.chooser.get()
        if count==0:
            return
        self.gameBoard.increment()
        self.paintBoard()
        self.window.after(1,self.increment,count-1)
    def paintBoard(self):
        self.clearCanvas()
        scale = self.scale
        for ii,jj in self.gameBoard.map.keys():
            self.objects.append(self.canvas.create_rectangle(ii*scale,
                                                             jj*scale,
                                                             ii*scale+scale,
                                                             jj*scale+scale,
                                                             outline="black",
                                                             fill="black"))
    def pressCanvas(self,event):
        self.gameBoard.press(event.x/self.scale,event.y/self.scale)
        self.paintBoard()

    def clearCanvas(self):
        for item in self.objects[:]:
            self.canvas.delete(item)
        self.objects = []

Lifegame()

かなり高速化した模様。
これ以上高速化するならTkinterのほうをどうにかしなければならない模様。
deleteが一番遅いっぽいんですが、抑制してもそんなに速くはならないっぽい。

追記。

clearCanvasでself.objectsをクリアしていなかったのが遅かった原因っぽい。
クリアするとすげえ高速で動きました。
そっか、存在しないオブジェクトをdeleteしようとしていたから遅かったんだな。