2016-11-13 90 views
3

因此,我閱讀了關於Conways遊戲的人生,並試圖用PyGame來實現它。Conways在PyGame中的生命遊戲

我試圖讓它面向對象。它的工作方式是我有一個單元實例列表,然後檢查它們有多少個鄰居,然後根據它們的鄰居保持活着或死亡。然後這個過程重演。

問題是,當我用一些已知的開始模式(例如在下面的代碼(CELL_MAP))中測試它時,它不會按照它應該的方式工作。

我一遍又一遍地讀了代碼,我沒有真正明白我在這裏錯過的東西。我發佈了下面的整個代碼,因爲我不知道我的錯誤在哪裏,但是如果有人會指出我正確的方向,我將非常感激。

在此先感謝!

import pygame 

class Cell: 
    def __init__(self, live, xcor, ycor): 
     self.alive = live 
     self.x = xcor 
     self.y = ycor 
     self.neighbours = 0 

def checkNeighbours(self, cellList): 
    for cell in cellList: 
     #left 
     if cell.x == self.x-1 and cell.y == self.y and cell.alive == True: 
      self.neighbours += 1   
     #right 
     elif cell.x == self.x+1 and cell.y == self.y and cell.alive == True: 
      self.neighbours += 1 
     #upleft 
     elif cell.x == self.x-1 and cell.y == self.y-1 and cell.alive == True: 
      self.neighbours += 1  
     #up 
     elif cell.x == self.x and cell.y == self.y-1 and cell.alive == True: 
      self.neighbours += 1 
     #upright 
     elif cell.x == self.x+1 and cell.y == self.y-1 and cell.alive == True: 
      self.neighbours += 1  
     #downleft 
     elif cell.x == self.x-1 and cell.y == self.y+1 and cell.alive == True: 
      self.neighbours += 1  
     #down 
     elif cell.x == self.x and cell.y == self.y+1 and cell.alive == True: 
      self.neighbours += 1 
     #downright 
     elif cell.x == self.x+1 and cell.y == self.y+1 and cell.alive == True: 
      self.neighbours += 1 

def breed(self): 
    if self.alive == False and self.neighbours == 3: 
     #dead cell ressurects if neighbours equals 3 
     self.alive = True 
    elif self.alive and self.neighbours < 2: 
     #die from loneliness 
     self.alive = False 
    elif self.alive and self.neighbours == 2: 
     #stay alive 
     pass 
    elif self.alive and self.neighbours == 3: 
     #stay alive 
     pass 
    elif self.alive and self.neighbours > 3: 
     #die from overpopulation 
     self.alive = False 

def render(self, display): 
    if self.alive: 
     pygame.draw.rect(display, (0,0,0), [self.x*10, self.y*10, 10, 10]) 
    elif self.alive == False: 
     pygame.draw.rect(display, (0,0,255), [self.x*10, self.y*10, 10, 10]) 




WID = 33 
HEI = 20    
CELL_MAP = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
      [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]] 

CELL_LIST = [] 

xc = -1 
yc = -1 
for yList in CELL_MAP: 
    yc += 1 
    for x in yList: 
     xc += 1 
     if x == 0: 
      #create dead cell 
      newCell = Cell(False, xc, yc) 
      CELL_LIST.append(newCell) 
     elif x == 1: 
      #create alive cell 
      newCell = Cell(True, xc, yc) 
      CELL_LIST.append(newCell) 
    xc = -1 



#pygame init 

pygame.init() 
(width, height) = (WID*10, HEI*10) 

pygame.display.set_caption('Game of Life') 

screen = pygame.display.set_mode((width, height)) 

#game loop 

def gameLoop(): 
    gameLoop = True 

    while gameLoop: 
     #check for exit 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       gameLoop = False 
       pygame.quit()    

     #render cells 
     for cell in CELL_LIST: 
      cell.render(screen)  

     #check neighbours 
     for cell in CELL_LIST: 
      cell.checkNeighbours(CELL_LIST) 

     pygame.display.flip() 

     #breed 
     for cell in CELL_LIST: 
      cell.breed() 

     pygame.time.wait(5) 

    quit() 

if __name__ == "__main__": 
    gameLoop() 
+0

嘗試將'cell.render(screen) cell.checkNeighbours(CELL_LIST) cell.breed()'all放在同一個循環中。這看起來更好嗎? – rassar

回答

2

我沒有安裝pygame,所以我無法運行您的代碼。但是,造成你的錯誤的錯誤是,你沒有確定在下一代中是否存活或死亡,你不會重置單元的鄰居數爲零。因此,在每一代中,每個小區的新鄰居數將被添加到先前的累積鄰居數。您應該可以在.breed方法中重置。

下面是方法的更緊湊版本:

def breed(self): 
    self.alive = self.neighbours == 3 or self.alive and self.neighbours == 2 
    self.neighbours = 0 

我對你的代碼的一些更多的評論。

您的checkNeighbours方法是非常效率效率低下:對於每個單元格,它會掃描整個網格尋找單元格的鄰居!一個簡單的選擇是將您的細胞存儲在二維列表中,以便快速找到細胞的鄰居。


這裏建立自己的CELL_LIST比一個更緊湊的方式你的代碼目前所做的:

CELL_LIST = [] 
for y, row in enumerate(CELL_MAP): 
    for x, v in enumerate(row): 
     CELL_LIST.append(Cell(v == 1, x, y)) 

這是同樣的事情作爲一個列表理解:

CELL_LIST = [Cell(bool(v), x, y) 
    for y, row in enumerate(CELL_MAP) 
     for x, v in enumerate(row) 
] 

但正如我所說早些時候,製作CELL_LIST一個2D列表可能是一個好主意:

cell_list = [[Cell(bool(v), x, y) for x, v in enumerate(row)] 
    for y, row in enumerate(CELL_MAP)] 

CELL_MAP是不要把生活模式到你的程序的便捷方式,但我想這是確定用於測試目的。看看我在本月早些時候寫出的替代方案this answer

最終,您應該讓程序能夠讀取許多生活程序使用的常見RLE format

您可能還想看看我寫的使用Numpy的中等效率版本:numpy_life.py。像我鏈接的其他版本一樣,它在Linux終端上顯示輸出,但兩個版本都應該很容易適應pygame或其他GUI框架。

+0

非常感謝,我知道它必須是如此簡單。並感謝您對代碼的評論,這絕對有助於我的編碼風格 – sorh

+0

@PM 2Ring,精彩的答案。感謝您的時間伴侶。 –