2017-06-02 3 views
1

Dies ist ein Codeschnipsel aus Conways Spiel des Lebens mit Python. Es ist ziemlich simpel, um zu überprüfen, ob es funktioniert - und das nicht. Kann nicht herausfinden, warum, aber soweit ich das beurteilen kann, ist es etwas mit der Aktualisierung.(Closed) Conways Game of Life wird nicht korrekt aktualisiert (Python)

Würde schätzen jede Eingabe, warum es aktualisiert, wie es funktioniert:

Gif in pygame (gleichen Code): http://imgur.com/6US3Nje nicht korrekt Aktualisierung: http://imgur.com/9gubzAF

import pprint,random 
#here we make the initial board, 6x6 
board = [] 
for y in range (6): 
    row = [] 
    for x in range (6): 
     row.append(random.randint(0,1)) 
    board.append(row) 
#and display it 
pprint.pprint(board) 

#this function counts the neighbours for each cell 
def neighbours(x,y): 
    counter = 0 
    neighbours = \ 
    [(x-1,y+1),(x,y+1),(x+1,y+1),\ 
    (x-1,y),   (x+1,y),\ 
    (x-1,y-1),(x,y-1),(x+1,y-1)] 
    for n in neighbours: 
     a, b = n 
     try: 
      counter += board[a][b] 
     except: 
      pass 
#printed out the counter to check if it counted correctly (it does, as far as I could tell) 
    if x == 4 and y == 4: 
     print(counter) 
    return counter 

#function to make a new board based off the old one - basically, the updater. 
#here's where the problem might lie - but for the life of me I cannot tell where and why. 
def new(board): 
    new_board = [] 
    for y in range(6): 
     new_row = [] 
     for x in range(6): 
      n = neighbours(x,y) 
      oldcell = board[x][y] 
      #everything is set up to be according to the rules 
      #(if dead(0) can only come alive with 3 alive cells 
      #(if alive(1) can continue to live with exactly 2 or 3 live neighbours 
      if oldcell == 0: 
       newcell = 0 
       if n == 3: 
        newcell = 1 
      elif oldcell == 1: 
       newcell = 1 
       if n > 3 or n < 2: 
        newcell = 0 
      new_row.append(newcell) 
     new_board.append(new_row) 
    return new_board 

#displaying the board for 6 instances 
for i in range (6): 
    nboard = new(board) 
    board = nboard 
    pprint.pprint(board) 

Vielen Dank im Voraus!

+1

Nicht sicher, was das Problem ist, aber Sie könnten diese innere Logik zu 'newcell = int (n in (2, 3)) vereinfachen, wenn oldcell sonst int (n == 3)' –

+0

@tobias_k Diese Art der Vereinfachung ist wirklich nur gut in einem Wettbewerb, wo Sie anhand der Anzahl der im Code verwendeten Anweisungen beurteilt werden könnten. In fast allen anderen Fällen ist die Erweiterung der Logik, wie sie das OP gemacht hat, für Lesbarkeits- und Debugging-Zwecke viel besser. – Xirema

+1

@Xirema Ich denke, das ist eine Frage der Meinung. Wenn ich diese Zeile sehe, lese ich "newcell ist am Leben, wenn es zwei oder drei Nachbarn gibt, wenn die alte Zelle lebt, ansonsten wenn es genau drei Nachbarn gibt", die IMHO ist viel einfacher zu begreifen als diese 8 Zeilen verschachtelten if/sonst. Aber wie gesagt, es ist eine Frage der persönlichen Vorliebe. –

Antwort

2

Sie mischen Zeilen und Spalten in Ihren Schleifen und transponieren so effektiv die gesamte Matrix mit jeder neuen Karte. Die Schleifen sollen wie folgt aussehen:

for x in range(6): 
    new_row = [] 
    for y in range(6): 
     ... 

Auch könnte der Großteil Ihrer if/else Logik in der Schleife zu einer einzigen Zeile vereinfacht werden. Ob das leichter zu lesen und zu verstehen ist oder nicht, entscheiden Sie selbst.

def new(board): 
    new_board = [] 
    for x in range(6): 
     new_row = [] 
     for y in range(6): 
      n = neighbours(x,y) 
      oldcell = board[x][y] 
      newcell = int(n in (2, 3)) if oldcell else int(n == 3) 
      new_row.append(newcell) 
     new_board.append(new_row) 
    return new_board 

Wie bereits erwähnt in comments, gibt es ein zweites (wenn auch weniger offensichtlich) Problem: Während Ihr try/except all Off-Board-Indizes überspringen war eine nette Idee, es nicht zum Beispiel verfängt für x = 0, wie [-1] ist ein legaler Index in Python (Indizierung des letzten Elements in der Sequenz), so dass Ihre Platine zwei der vier Kanten "wrap around". Stattdessen sollten Sie explizit nach den Grenzen des Boards suchen. Wenn Sie möchten, können Sie diese andere ‚Spaß‘ machen Einzeiler:

def neighbours(x,y): 
    return sum(board[a][b] for a in (x-1,x,x+1) for b in (y-1,y,y+1) 
       if (a,b) != (x,y) and 0 <= a < len(board) and 0 <= b < len(board[a])) 

Natürlich können Sie auch Ihre Schleife halten und nur die try/except für die if Prüfung ersetzen.

+0

Vielen Dank! Jetzt funktioniert alles wie es soll.So viel Kummer von so einer kleinen Sache) – Alfr

+1

Was die Vereinfachung betrifft, werde ich das im Hinterkopf behalten - es ist überraschenderweise einfacher zu lesen als das, was ich normalerweise komponiere. Verständnis wird manches mit Übung) – Alfr

+0

Für den Umbruch habe ich das so gemacht (denn, so spaßig wie der One-Liner aussieht, ich habe ein paar Probleme damit meinen Verstand zu umspielen was da abgeht): wenn a == - 1 oder b == -1: weiter vor dem try/except. (kann nicht herausfinden, wie man hier den Code formatiert: C) – Alfr

Verwandte Themen