簡體   English   中英

為什么我的 Tkinter Game of Life 實現逐漸變慢?

[英]Why does my Tkinter Game of Life Implementation slow down progressively?

編輯:

對於將來遇到此問題的任何人:

檢查您是否有創建 object 實例的代碼塊,並在詢問類似內容之前先將其刪除。

** 問題開始:**

我想用 Tkinter 來實現康威的生命游戲。 我的代碼似乎確實有效,但每次我啟動應用程序時,它都會變慢,直到 canvas 每秒更新一次。

我已經研究過類似的問題,但這里的問題是,在每一個問題中,人們不斷創建矩形,這顯然會導致幀速率問題,但我在我的實現中改變了它(我用 ROWS*COLS 矩形初始化 canvas ,然后只改變它們的顏色)。

負責更新 canvas 的主要 function 是“startConway()” - function。 如您所見,我嘗試測量時間 (t0,t1,t2) 以查看是否有一個 for 循環導致問題,但即使 canvas 變慢,時間幾乎保持不變並且始終低於 20 毫秒。

關於 Tkinter 有什么我不知道的地方阻礙了我的進步嗎? 還是我的方法遠遠慢? 哪里可以改進?

如果您想嘗試一下,只需復制代碼,然后運行它。 在 canvas 上,單擊一些像素,然后最后開始 Conway 游戲,單擊黑色像素。

提前致謝。

這是代碼:

import tkinter as tk
import numpy as np
import time
import random
import copy
import math

# Set number of rows and columns
ROWS = 10
COLS = 10
ANIMATION_DELAY = 50
NEIGHBOUR_SEARCH_DELAY = 0
BORDER_PROB = 0.2
ITERATIONS_CONWAY = 1000

# Create a grid of None to store the references to the tiles
cells = [[None for _ in range(ROWS)] for _ in range(COLS)]

class Cell:

    def __init__(self, col, row):
        self.col = col
        self.row = row
        self.rect = None
        self.text = None
        createRectangle(self,"","","")
        # extras for A_Star:
        self.cost_g = 0
        self.cost = 0
        self.parent = None
        self.dist_to_neighbours = []
    
    def equals(self,cell):
        return (self.col == cell.col and self.row == cell.row)
    
    def changeText(self,txt,color):
        c.itemconfig(self.text,text=txt,fill=color)
        
    def changeRect(self,color):
        c.itemconfig(self.rect, fill=color)
    
    def toString(self):
        return str(self.col) + "|" + str(self.row)
    
    # extras for A_Star:
    def getDist(self,cell):
        return 1
    
def callback2(event):
    # Calculate column and row number
    col = int(event.x/col_width)
    row = int(event.y/row_height)
    clicked_cell = cells[col][row]
    # If the tile is not filled, create a rectangle
    if not c.itemcget(clicked_cell.rect,"fill") == "black":
        clicked_cell.changeRect("black")
    else:
            startConway(ITERATIONS_CONWAY)

def startConway(iteration):
    
    if iteration == 0:
        return
    
    alive = np.zeros([COLS,ROWS])
    
    t0 = time.time()
    
    for row in range(ROWS):
        for col in range(COLS):
            current_cell = cells[col][row]
            neighbours = getAliveNeighbours(current_cell)
            isAlive = c.itemcget(current_cell.rect,"fill") == "black"
            
            willSurvive = isAlive and (neighbours == 2 or neighbours == 3)
            willResurrect = not isAlive and neighbours == 3
            
            if willSurvive or willResurrect:
                alive[col][row] = 1
            else:
                alive[col][row] = 0
            
    t1 = time.time()
    
    for row in range(ROWS):
        for col in range(COLS):
            current_cell = cells[col][row]
            isAlive = alive[col][row]
            
            if isAlive:
                current_cell.changeRect("black")
            else:
                current_cell.changeRect("white")
                
    t2 = time.time()
    
    root.after(ANIMATION_DELAY,startConway,iteration-1)
       
    total = t1-t0
    
    print("neighbour Loop: ", t1-t0)
    print("draw Loop: ", t2-t1)
    print("----------------------")
    
def getAliveNeighbours(coord):
    count = 0
    
    upper_left = Cell(coord.col - 1,coord.row - 1) 
    neighbours = []
    for row in range(3):
        for col in range(3):
            new_col = (upper_left.col + col) % COLS
            new_row = (upper_left.row + row) % ROWS
            
            isStartingCell = (row == 1 and col == 1)
            isAlive = c.itemcget(cells[new_col][new_row].rect,"fill") == "black"
            
            if not isStartingCell and isAlive:
                count = count + 1
                
    return count

def createRectangle(cell,rect_color,txt,text_color):
        cell.rect = c.create_rectangle(cell.col*col_width, cell.row*row_height, (cell.col+1)*col_width, (cell.row+1)*row_height, fill=rect_color)
        cell.text = c.create_text(((cell.col*col_width + (cell.col+1)*col_width)/2, (cell.row*row_height + (cell.row+1)*row_height)/2), text=txt, fill=text_color)

def initializeCanvas(hasBorder):
    for row in range(ROWS):
        for col in range(COLS):
            cells[col][row] = Cell(col,row)
            if hasBorder and (row == 0 or col == 0 or col == COLS-1 or row == ROWS-1):
                cells[col][row].changeRect("black")
                
root = tk.Tk()

c = tk.Canvas(root, width=500, height=500, borderwidth=5, background='white')
c.pack()
c.bind("<Button-1>", callback2)
c.update()

col_width = c.winfo_width()/COLS
row_height = c.winfo_height()/ROWS

initializeCanvas(False)
            
root.mainloop()

每次調用getAliveNeighbors時,都會創建一個新的Cell實例。 這會在 canvas 上創建一個新矩形。 您每 50 毫秒調用此 function 100 次(10 行乘以 10 列)。 因此,您每秒鍾都在創建 2,000 個新矩形。

一旦您在 canvas 上獲得數萬個對象,canvas 就會出現已知的性能問題,這將以每秒 2,000 個矩形的速度很快發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM