2016-11-13 2 views
3

Also las ich über Conways Spiel des Lebens und versuchte, es mit PyGame zu implementieren.Conways Spiel des Lebens in PyGame

Ich habe versucht, es objektorientiert zu machen. Die Art und Weise, wie es funktioniert, ist, dass ich eine Liste von Zellen-Instanzen habe, die dann überprüfen, wie viele Nachbarn sie haben und dann entweder am Leben bleiben oder sterben, basierend auf ihren Nachbarn. Dann wiederholt sich der Vorgang.

Das Problem ist, dass, wenn ich es mit einigen bekannten Startmuster (z. B. im unten stehenden Code (CELL_MAP)) es funktioniert nicht so, wie es sollte.

Ich las den Code immer und immer wieder und ich verstehe nicht wirklich, was ich hier vermisse. Ich habe den ganzen Code unten gepostet, weil ich nicht weiß, wo mein Fehler ist, aber ich würde es sehr schätzen, wenn mir jemand in die richtige Richtung zeigen würde.

Vielen Dank im Voraus!

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

versuchen Sie setzen 'cell.render (Bildschirm) cell.checkNeighbours (CELL_LIST) cell.breed()' alle in der gleichen for-Schleife. Sieht das besser aus? – rassar

Antwort

2

Ich habe keine Pygame installiert, so dass ich Ihren Code nicht ausführen kann. Der Fehler, der den Fehler verursacht, besteht jedoch darin, dass Sie die Nachbarschaftszahl einer Zelle nicht auf Null zurücksetzen, nachdem Sie festgestellt haben, ob sie in der nächsten Generation aktiv oder inaktiv ist. In jeder Generation wird also der neue Nachbarzähler jeder Zelle zu dem vorherigen akkumulierten Nachbarzähler addiert. Sie sollten das wahrscheinlich in der .breed Methode zurücksetzen.

Hier ist eine kompaktere Version dieser Methode:

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

Ich habe noch ein paar Kommentare über Ihren Code.

Ihre checkNeighbours Methode ist extrem ineffizient: für jede Zelle scannt es das gesamte Raster auf der Suche nach den Nachbarn einer Zelle! Eine einfache Alternative besteht darin, Ihre Zellen in einer 2D-Liste zu speichern, damit Sie schnell die Nachbarn einer Zelle finden können.


Hier ist ein kompakter Art und Weise Ihre CELL_LIST als das, was Ihr Code zur Zeit zu bauen tut:

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

Hier ist das gleiche wie ein Liste Verständnis:

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

Aber wie gesagt früher ist es wahrscheinlich eine gute Idee, CELL_LIST eine 2D-Liste zu machen:

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

Ihre CELL_MAP ist kein bequemer Weg, Lebensmuster in Ihr Programm zu setzen, aber ich denke, es ist für Testzwecke ist ok. Werfen Sie einen Blick auf this answer Ich schrieb Anfang dieses Monats für eine Alternative.

Schließlich sollten Sie Ihrem Programm die Möglichkeit geben, das gemeinsame RLE format zu lesen, das von vielen Lebenprogrammen verwendet wird.

Sie können auch gerne diese mäßig effiziente Version, die ich geschrieben habe, die Numpy verwendet: numpy_life.py. Wie die andere Version, die ich verlinkt habe, zeigt sie die Ausgabe im Linux-Terminal an, aber beide Versionen sollten leicht an pygame oder ein anderes GUI-Framework angepasst werden können.

+0

Vielen Dank, ich wusste, dass es etwas so einfaches sein musste. Und danke für Ihre Kommentare über den Code, der definitiv hilft, meinen Stil der Codierung zu verfeinern – sorh

+0

@PM 2Ring, wunderbare Antwort.Vielen Dank für Ihre Zeit Kumpel. –

Verwandte Themen