2016-11-13 91 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,精彩的答案。感谢您的时间伴侣。 –