Я новичок в программировании и пытаюсь сделать простую анимацию, чтобы лучше учиться.Я только что выучил python (все еще nooby) и начал изучать tkinter.Я пытаюсь сделать анимацию «Игры жизни Конвея», потому что она имеет очень простые принципы и выглядит круто.Мне удалось заставить мой код работать, но я действительно не понимаю, как.Дело в том, что метод после того, как я не могу понять, как он работает.
Часть кода, которую я не понимаю, - это метод, называемый start.Я действительно не понимаю, как «цикл завершен» может быть напечатан до того, как функция startloop возвращает None (что должно быть то же самое, что сказать, что анимация еще не остановилась)
import tkinter as tk
width = 1400
height = 600
dist = 5
drawlines = False
celstate = set()
numcol = width//dist
numrow = height//dist
def getdeadcells(setcells):
global celstate
deadcells = set()
for cell in setcells:
i, j = cell
list = [(i-1, j-1), (i, j-1), (i+1, j-1),
(i-1, j), (i+1, j), (i-1, j+1), (i, j+1), (i+1, j+1)]
for cel in list:
if cel not in celstate:
deadcells.add(cel)
return deadcells
def getnewstate():
def neight(cell):
i, j = cell
count = 0
list = [(i-1, j-1), (i, j-1), (i+1, j-1),
(i-1, j), (i+1, j), (i-1, j+1), (i, j+1), (i+1, j+1)]
for cel in list:
if cel in celstate:
count +=1
return count
global celstate, numcol, numrow
alivecells = celstate.copy()
deadcells = getdeadcells(alivecells)
newstate = set()
for cell in alivecells:
neigh = neight(cell)
if neigh == 2 or neigh == 3:
newstate.add(cell)
for cell in deadcells:
neigh = neight(cell)
if neigh == 3:
newstate.add(cell)
if newstate == celstate:
return None
else:
celstate = newstate
if len(newstate) == 0:
return ""
else:
return newstate
def getcords(x, y):
col = x//dist
row = y//dist
return (col, row)
class GUI():
def __init__(self, master, width, height, dist):
master.geometry("{}x{}".format(width, height))
master.bind("<Key>", self.start)
self.master = master
self.width = width
self.height = height
self.dist = dist
self.canvas = tk.Canvas(master, width=width, height=height)
self.canvas.pack(expand=True)
self.drawlimits(dist)
def start(self, event):
if event.keycode == 32 or event.keycode == 13:
def startloop():
newstate = getnewstate()
if newstate == None:
return None
elif newstate == "":
self.canvas.delete("rect")
return None
else:
self.canvas.delete("rect")
self.fillrects(list(newstate))
self.master.after(100, startloop)
startloop()
print("loop finished")
def drawlimits(self, dist):
if self.width % dist == 0 and self.height % dist == 0:
self.canvas.bind("<B1-Motion>", self.drawcells)
self.canvas.bind("<ButtonRelease-1>", self.drawcells)
self.canvas.bind("<B3-Motion>", self.killcell)
self.canvas.bind("<ButtonRelease-3>", self.killcell)
if drawlines:
xsteps = self.width/dist
ysteps = self.height/dist
for num in range(int(xsteps-1)):
self.canvas.create_line((num+1)*dist, 0, (num+1)*dist, self.height)
for num in range(int(ysteps-1)):
self.canvas.create_line(0, (num+1)*dist, self.width, (num+1)*dist)
def drawcells(self, event):
cell = getcords(event.x, event.y)
if cell not in celstate:
self.fillrects([cell])
celstate.add(cell)
def killcell(self, event):
cell = getcords(event.x, event.y)
if cell in celstate:
celstate.remove(cell)
col, row = cell
tag = "{},{}".format(col, row)
obj.canvas.delete(tag)
def fillrects(self, cords):
for gcords in cords:
col, row = gcords
tag = "{},{}".format(col,row)
dist = self.dist
self.canvas.create_rectangle(col*dist, row*dist, (col+1)*dist, (row+1)*dist,
fill="black", tags=(tag, "rect"))
root = tk.Tk()
obj = GUI(root, width, height, dist)
root.mainloop()
Код работает следующим образом: я сохраняю толькоклетки, которые живут в наборе celstate.Затем я нахожу мертвые ячейки, которые могли бы стать живыми и перебирать мертвые и живые клетки в
Если состояние ячейки совпадает с предыдущим или нет живых клеток: тогда функция getnewstate возвращает None.
В методе start я затем вызываю функцию getnewstate и отрисовываю ее содержимое до тех пор, пока celstate не вернет None (с функцией startloop, которая вызывает себя с помощью метода after).Я не понимаю, почему «цикл закончен» может быть напечатан, если startloop еще не остановился.Несмотря на то, что я не понимаю эту часть, код все еще работает как задумано, что только делает его более раздражающим для меня.Может кто-нибудь помочь прояснить, что происходит ??
- Переменная dist представляет размер ячейки в пикселях
- Вы можете нарисовать новые ячейки, используя левую кнопку мыши, или стереть существующие, используяправая кнопка.(Самое интересное, что вы можете сделать это, пока анимация еще продолжается)
Я уверен, что проблема возникает, потому что я не совсем понимаю, как работает основной цикл