IN_IDLE = 0 from Tkinter import * import random SIZE = 400 class SchiebePuzzle: def __init__(self,nx=4,ny=4): self.root = Tk() self.root.title("Schiebepuzzle (c) Wolfgang.Urban@schule.at") rframe = Frame(self.root) bsize1 = Button(rframe,text="3x2",font=("Courier",8), command=lambda a=3,b=2: self.resize(a,b)) bsize2 = Button(rframe,text="3x3",font=("Courier",8), command=lambda a=3,b=3: self.resize(a,b)) bsize3 = Button(rframe,text="4x3",font=("Courier",8), command=lambda a=4,b=3: self.resize(a,b)) bsize4 = Button(rframe,text="4x4",font=("Courier",8), command=lambda a=4,b=4: self.resize(a,b)) bsize5 = Button(rframe,text="5x5",font=("Courier",8), command=lambda a=5,b=5: self.resize(a,b)) bsize6 = Button(rframe,text="6x6",font=("Courier",8), command=lambda a=6,b=6: self.resize(a,b)) bsize7 = Button(rframe,text="8x8",font=("Courier",8), command=lambda a=8,b=8: self.resize(a,b)) bsize8 = Button(rframe,text="10x10",font=("Courier",8), command=lambda a=10,b=10: self.resize(a,b)) bsize1.pack(side=LEFT,fill=X,expand=1) bsize2.pack(side=LEFT,fill=X,expand=1) bsize3.pack(side=LEFT,fill=X,expand=1) bsize4.pack(side=LEFT,fill=X,expand=1) bsize5.pack(side=LEFT,fill=X,expand=1) bsize6.pack(side=LEFT,fill=X,expand=1) bsize7.pack(side=LEFT,fill=X,expand=1) bsize8.pack(side=LEFT,fill=X,expand=1) rframe.pack(side=TOP,fill=X,expand=1) Label(self.root,text="",font=("Arial",1)).pack(side=TOP,pady=0) cframe = Frame(self.root) breset = Button(cframe,text="Reset",font=("Arial",16), command=self.reset) bmix = Button(cframe,text="Mix",font=("Arial",16,"bold"), command=self.mix) bquit = Button(cframe,text="Quit",font=("Arial",16), command=self.quit) breset.pack(side=LEFT,expand=1,fill=X) bmix.pack(side=LEFT,expand=1,fill=X) bquit.pack(side=LEFT,expand=0,fill=BOTH) cframe.pack(side=BOTTOM,expand=1,fill=X) self.output = Label(self.root,text="",font=("Arial",1),fg="#1010ff") self.output.pack(side=BOTTOM) self.build(nx,ny) def build(self,nx,ny): self.nx, self.ny = nx,ny self.cellsize = SIZE/max(nx,ny) self.numcells = nx*ny self.cells = [0]*self.numcells self.occupant = [0]*self.numcells self.empty = self.numcells-1 self.makecells() self.busy = 0 self.ANIMATE = 1 self.DELAY = 50 self.output.config(text="") def makecells(self): self.frame = Frame(self.root,width=self.nx*self.cellsize+7, height=self.ny*self.cellsize+7,relief=GROOVE,border=3) textsize=18 if self.cellsize<60: textsize=14 if self.cellsize>90: textsize=32 for i in range(self.numcells-1): self.occupant[i] = i xc,yc = i%self.nx,i/self.nx x,y = self.cellsize*(i%self.nx),self.cellsize*(i/self.nx) self.cells[i] = Label(self.frame,text=str(i+1),relief=GROOVE, font=("Arial",textsize), bg=col(xc,yc,self.nx,self.ny)) self.cells[i].place(x=x,y=y,anchor=NW,width=self.cellsize, height=self.cellsize) # find out which element was clicked self.cells[i].bind("",lambda event, num=i:self.leftclick(num)) self.occupant[self.empty] = self.empty self.frame.pack(side=TOP,padx=5) self.root.update() self.PLAYING = 0 def reset(self): for i in range(self.numcells-1): self.occupant[i] = i x,y = self.cellsize*(i%self.nx),self.cellsize*(i/self.nx) self.cells[i].place(x=x,y=y,anchor=NW,width=self.cellsize, height=self.cellsize) self.occupant[self.empty] = self.empty self.solved() self.output.config(text="") self.PLAYING = 0 def resize(self,x,y): self.frame.destroy() self.build(x,y) def quit(self): self.root.destroy() ####################################################################### def solved(self): n1,n0=0,0 for i in range(self.numcells): if self.occupant[i] == i: n1+=1 else: n0+=1 self.root.title("richtig: "+str(n1)+" / falsch: "+str(n0)) return n0==0 # cell n was clicked def leftclick(self,n): if self.busy: return if n == self.empty: return self.busy = 1 c = self.occupant.index(n) e = self.occupant.index(self.empty) cy,cx = divmod(c,self.nx) ey,ex = divmod(e,self.nx) if cx==ex: if cy>ey: todo = range(cy,ey,-1) direct = (0,-1) else: todo = range(cy,ey,+1) direct = (0,1) for i in range(len(todo)): todo[i]=ex+self.nx*todo[i] self.process(todo,direct) if cy==ey: if cx>ex: todo = range(cx,ex,-1) direct = (-1,0) else: todo = range(cx,ex,+1) direct = (1,0) for i in range(len(todo)): todo[i]=todo[i]+ey*self.nx self.process(todo,direct) r = self.solved() if r==1: if self.PLAYING==1: # after mixing only self.output.config(text="BRAVO, alles richtig!",font=("Arial",24)) self.PLAYING=0 else: self.output.config(text="",font=("Arial",1)) self.busy = 0 # shift cells at place_list by direction vector def process(self,place_list,direct): cell_list = place_list[:] for i in range(len(cell_list)): cell_list[i] = self.occupant[place_list[i]] y,x = divmod(place_list[0],self.nx) # coordinate of first place x,y = x*self.cellsize,y*self.cellsize dx,dy = direct[0]*self.cellsize,direct[1]*self.cellsize e = self.occupant.index(self.empty) for p in range(len(place_list)-1,-1,-1): self.occupant[place_list[p]],self.occupant[e] =\ self.empty,self.occupant[place_list[p]] e = place_list[p] if self.ANIMATE: steps = [0.2,0.4,0.6,0.8,1] else: steps = [1] for s in steps: x0,y0 = x+int(s*dx),y+int(s*dy) for c in cell_list: self.cells[c].place(x=x0,y=y0) x0 += dx y0 += dy if self.ANIMATE: self.root.after(self.DELAY) self.root.update() ######################################################### def mix(self,n=0): self.ANIMATE = 0 if n==0: n=4*self.numcells z = 0 while z