Dec-09-2016, 10:13 AM
@ Ofnuts..thanks for the clever idea… I would never have thought of that (and probably never will ;) as no textbook will teach you that.
@ Mekire…I guess I could implement that but the +/- 50 also corresponds to the size of the square (not speed). Next development might be asking for the size of the square first and use your idea to adjust these.
Question.. could I combine the bind_all commands in lines 37-40 (or 41-43) in a similar way?
Finally, I added a random generator of squares (press r), as I got lazy of creating them myself.
(Lines 47-60). Fun to watch
Hans
@ Mekire…I guess I could implement that but the +/- 50 also corresponds to the size of the square (not speed). Next development might be asking for the size of the square first and use your idea to adjust these.
Question.. could I combine the bind_all commands in lines 37-40 (or 41-43) in a similar way?
Finally, I added a random generator of squares (press r), as I got lazy of creating them myself.
(Lines 47-60). Fun to watch
Hans
#Any live cell with fewer than two live neighbours dies. #Any live cell with two or three live neighbours lives. #Any live cell with more than three live neighbours dies. #Any dead cell with exactly three live neighbours becomes a live cell. import time import random from tkinter import * window = Tk() window.title("Conway's Game of Life") canvas = Canvas(window, width=1200, height=900,bd=0, highlightthickness=0) canvas.pack() text_ = Text(window, height=3, width=30) text_.pack() text_.insert(END, "To MOVE use arrow keys. Press x to seed. r for random seeds. f to finish") ##################### VARIABLES ############################ keypressed = ""; SQident = 1; doublelist=[] Neigh=([-50,-50,-50,-50],[0,-50,0,-50],[+50,-50,+50,-50],[-50,0,-50,0],[+50,0,+50,0],[-50,+50,-50,+50],[0,+50,0,+50],[+50,+50,+50,+50]) #Neigh contains coordinates, NW,N,NW,W,E,SW,S,SE of square sq = canvas.create_rectangle(50, 50, 100, 100, fill="grey") moves={"Up":(0, -50),"Down":(0,50), "Left":(-50,0), "Right":(50,0)} def movesquare(event): # detect movement keys x,y=moves[event.keysym] canvas.move(SQident,x,y) def otherkey(event): #detect other keys pressed global SQident; global keypressed keypressed = event.keysym if keypressed == "x": # make new square if (canvas.coords(SQident)) not in doublelist: # prevent creating twice sq=canvas.create_rectangle((canvas.coords(SQident)), fill="grey") #new square created at previous position doublelist.append(canvas.coords(SQident)) SQident +=1 #new square identifier while 1: window.update() window.update_idletasks() canvas.bind_all("<KeyPress-Up>", movesquare) canvas.bind_all("<KeyPress-Down>", movesquare) canvas.bind_all("<KeyPress-Left>", movesquare) canvas.bind_all("<KeyPress-Right>", movesquare) canvas.bind_all("x", otherkey) canvas.bind_all("f", otherkey) canvas.bind_all("r", otherkey) if keypressed == "f": #finshed canvas.delete(SQident) break if keypressed == "r": #add random canvas.delete(SQident) for y in range(10): x1=(random.randint(0,13)+random.randint(0,13))*50 # between 0 and 24 * 50 = 0 - 1200 is width y1=(random.randint(0,9)+random.randint(0,9))*50 # between 0 and 18 * 50 = 0 - 900 is height x2=x1+50; y2=y1+50 sq = canvas.create_rectangle(x1, y1, x2, y2, fill="grey") for x in range(0,3): ra=random.randint(0,7) x1ne=(Neigh[ra][0]);y1ne=(Neigh[ra][1]);x2ne=(Neigh[ra][2]);y2ne=(Neigh[ra][3]) # create 3 random neighbors if (x1+x1ne,y1+y1ne,x2+x2ne,y2+y2ne) not in doublelist: # prevent creating twice sq = canvas.create_rectangle((x1+x1ne,y1+y1ne,x2+x2ne,y2+y2ne), fill="pink") doublelist.append((x1+x1ne,y1+y1ne,x2+x2ne,y2+y2ne)) break ############################## start animation ############################# numberofgenerations =0 ; color=0 colsel=["Light Pink","Pale Violet Red","Deep Pink","Medium Violet Red","Orchid","Medium Orchid","Medium Purple","Dark Violet","Blue Violet","Purple"] while numberofgenerations < 1000: window.update() window.update_idletasks() color +=1 if color == 10: color = 1 ##################### variables ######################################## livelist = canvas.find_all() #= list of al objectIDs on canvas createlist=[] #= newly created squares stored this list (coordinates are stored!) killlist=[] #= to be killed squares stored in this list (objectIDs are stored!) # Staying ALIVE OR DIE using Object IDs. Detecting number of neighbours. Store in killlist for live in livelist: # look in livelist for object identifier at position x and retrieve its coordinates x1=(canvas.coords(live)[0]); y1=(canvas.coords(live)[1]) x2=(canvas.coords(live)[2]); y2=(canvas.coords(live)[3]) # Count number of Neighbours (CN) by using overlap function (-1 as it includes object itself) CN=(len(canvas.find_overlapping(x1,y1,x2,y2))-1) if CN < 2: #dead too few neighbours killlist.append (canvas.find_enclosed(x1-10,y1-10,x2+10,y2+10)) # enclosed function gives Object ID square within enclosed. Enclosed needs wider coordinates # do nothing if CN==2 OR CN==3 (survive) if CN > 3: #dead too many neighbours killlist.append (canvas.find_enclosed(x1-10,y1-10,x2+10,y2+10)) # Detect wether neighbours empty (via enclosed/Encl) and count number of adjacent(via overlapping/Overl). for Ne in Neigh: Coo=[x1+Ne[0],y1+Ne[1],x2+Ne[2],y2+Ne[3]] # surrounding coordinates Overl=len(canvas.find_overlapping(x1+Ne[0],y1+Ne[1],x2+Ne[2],y2+Ne[3])) # Number of objects surrounding Encl=len(canvas.find_enclosed(x1+Ne[0]-10,y1+Ne[1]-10,x2+Ne[2]+10,y2+Ne[3]+10)) # enclosed coordinates:0 is empty; 1 is present if Encl != 1: # enclosed not 1 thus is field is empty. Possible new life if Overl == 3: # has 3 (overlapping) neighbours thus new life if Coo not in createlist: # prevent creating twice createlist.append (Coo) #Start creating for create in createlist: sq=canvas.create_rectangle(create, fill=(colsel[color])) #select coordinates from createlist #Start killlling for kill in killlist: canvas.delete(kill) # delete ObjectID #Slow down for TI in range(0,2): time.sleep(0.1) numberofgenerations +=1 mainloop()