# L-12 MCS 275 Mon 8 Feb 2010 : GUI to find path in maze from Tkinter import * from numpy import * from random import randint class FillSquares(): """ filling squares on canvas with mouse clicks """ def DrawBoundingBox(self): """ draws a bounding box on canvas """ x0 = self.mag; y0 = self.mag x1 = self.mag*self.rows+self.mag y1 = self.mag*self.cols+self.mag self.c.create_line(y0,x0,y0,x1,width=1) self.c.create_line(y0,x0,y1,x0,width=1) self.c.create_line(y1,x0,y1,x1,width=1) self.c.create_line(y0,x1,y1,x1,width=1) def BindMouseEvents(self): """ binds mouse events to the canvas """ self.c.bind("", self.ButtonPressed) self.c.bind("", self.ButtonReleased) self.c.bind("", self.EnteredWindow) self.c.bind("", self.ExitedWindow) self.c.bind("", self.MouseDragged) def __init__(self,wdw,r,c,d): """ the mouse is bound to the canvas a label displays mouse position """ wdw.title("make a labyrinth") self.mag = 10 # magnification factor self.rows = r # number of rows on canvas self.cols = c # number of columns on canvas self.delay = d # time unit to wait update self.go = False # state of the animation self.filled = zeros((r,c),int) self.c = Canvas(wdw,\ width=self.mag*self.cols+2*self.mag,\ height = self.mag*self.rows+2*self.mag,\ bg='white') self.c.grid(row=1,column=0,columnspan=3) # to display mouse position : self.MousePosition = StringVar() self.MousePosition.set("put mouse inside box to draw") self.positionLabel = Label(wdw, \ textvariable = self.MousePosition) self.positionLabel.grid(row=2,column=0,columnspan=3) # draw bounding box and bind mouse events self.DrawBoundingBox() self.BindMouseEvents() # three buttons for making the labyrinth self.b1 = Button(wdw,text='random',command=self.RandomFill) self.b1.grid(row=0,column=0,sticky=W+E) self.b2 = Button(wdw,text='revert',command=self.Revert) self.b2.grid(row=0,column=1,sticky=W+E) self.b3 = Button(wdw,text='clear',command=self.Clear) self.b3.grid(row=0,column=2,sticky=W+E) # two buttons for the animation self.b4 = Button(wdw,text='start',command=self.start) self.b4.grid(row=3,column=0,sticky=W+E) self.b5 = Button(wdw,text='stop',command=self.stop) self.b5.grid(row=3,column=1,sticky=W+E) # entry window for current position self.e = Entry(wdw) self.e.grid(row=3,column=2) def DrawRectangle(self,x,y): """ draws a green rectangle on canvas, with coordinates given at (x,y) by mouse """ x0 = y - y % self.mag y0 = x - x % self.mag x1 = x0 + self.mag y1 = y0 + self.mag i = x0/self.mag - 1 j = y0/self.mag - 1 name = '('+str(i)+','+str(j)+')' if self.filled[i,j] == 0: self.c.create_rectangle(y0,x0,y1,x1,fill="green",tags=name) self.filled[i,j] = -1 else: self.c.delete(name) self.filled[i,j] = 0 def RandomFill(self): """ fills the canvas with boxes placed at random """ for i in range(0,self.filled.shape[0]): for j in range(0,self.filled.shape[1]): name = '('+str(i)+','+str(j)+')' if randint(0,1) == 1: x0 = self.mag+i*self.mag; y0 = self.mag+j*self.mag x1 = x0 + self.mag; y1 = y0 + self.mag self.c.create_rectangle(y0,x0,y1,x1,fill="green",tags=name) self.filled[i,j] = -1 else: self.c.delete(name) self.filled[i,j] = 0 def Clear(self): """ clears the canvas """ self.c.delete(ALL) self.DrawBoundingBox() self.filled = zeros((self.rows,self.cols),int) def Revert(self): """ reverts the filling of the canvas """ for i in range(0,self.filled.shape[0]): for j in range(0,self.filled.shape[1]): name = '('+str(i)+','+str(j)+')' if self.filled[i,j] == -1: self.c.delete(name) self.filled[i,j] = 0 else: x0 = self.mag+i*self.mag; y0 = self.mag+j*self.mag x1 = x0 + self.mag; y1 = y0 + self.mag self.c.create_rectangle(y0,x0,y1,x1,fill="green",tags=name) self.filled[i,j] = -1 def ButtonPressed(self,event): """ display coordinates of button press """ self.MousePosition.set("currently at [ " + \ str(event.x) + ", " + str(event.y) + " ]" +\ " release to fill, or drag") def ButtonReleased(self,event): """ display coordinates of button release """ self.MousePosition.set("drawn at [ " + \ str(event.x) + ", " + str(event.y) + " ]" + \ " redo to clear") self.DrawRectangle(event.x,event.y) def EnteredWindow(self,event): """ display message that mouse entered window """ self.MousePosition.set("press mouse to give coordinates") def ExitedWindow(self,event): """ display message that mouse exited window """ self.MousePosition.set("put mouse inside box to draw") def MouseDragged(self,event): """ display coordinates of moving mouse """ self.MousePosition.set("dragging at [ " + \ str(event.x) + ", " + str(event.y) + " ]" + \ " release to draw") def animate(self,i,j,k): """ starts the search for a path """ self.filled[i,j] = k self.e.delete(0,END) self.e.insert(INSERT,'(i,j) = ('+str(i)+','+str(j)+')') x0 = (i+1)*self.mag; y0 = (j+1)*self.mag x1 = (i+2)*self.mag; y1 = (j+2)*self.mag self.c.create_rectangle(y0,x0,y1,x1,fill="red",tags='dot') self.c.after(self.delay) self.c.update() if self.go: if i == self.filled.shape[0] - 1 and j == self.filled.shape[1] - 1: return True # found the end else: b = False if self.go and i < self.filled.shape[0]-1: if self.filled[i+1,j] == 0 and self.go: b = self.animate(i+1,j,k+1) if not b and self.go: if j < self.filled.shape[1]-1: if self.filled[i,j+1] == 0 and self.go: b = self.animate(i,j+1,k+1) if not b and self.go and i > 0: if self.filled[i-1,j] == 0 and self.go: b = self.animate(i-1,j,k+1) if not b and self.go and j > 0: if self.filled[i,j-1] == 0 and self.go: b = self.animate(i,j-1,k+1) return b def start(self): """ starts the animation """ self.go = True b = self.animate(0,0,1) def stop(self): """ stops the animation """ self.go = False def main(): top = Tk() r = 50 #input('Give #rows : ') c = 100 #input('Give #columns : ') d = 50 #input('Give delay : ') # r = 20; c = 30 show = FillSquares(top,r,c,d) top.mainloop() if __name__ == "__main__": main()