ubuntuusers.de

[Python] zweidimensionales Array selektiv auslesen

Status: Gelöst | Ubuntu-Version: Kubuntu 6.06 (Dapper Drake)
Antworten |

Jasmin Team-Icon

Avatar von Jasmin

Anmeldungsdatum:
4. Juni 2006

Beiträge: 463

Sorry für den Titel, mir ist irgendwie nicht viel eingefallen.

Ich hab heute angefangen, mir mal Python anzusehen. Und um besser vergleichen zu können, will ich mal mein 'Game of Life' auch in Python schreiben.

Was mir jetzt Kopfzerbrechen bereitet: Ich habe ein zweidimensionales Array, wo sich an einem bestimmten Punkt entweder ein . oder eine # befindet. Wenn sich dort eine # befindet, will ich rausfinden, wieviele Nachbar-# es dazu gibt.
Versucht habe ich, beispielsweise den Punkt links neben dem gerade zu testenden Punkt zu prüfen, indem ich matrix[x-1][y] überprüfe, dummerweise gibt das eine Fehlermeldung, auch wenn ich das in eine if-Abfrage stecke, die erst ausgeführt wird, wenn x-1 >= 0 wäre. Also so beispielsweise:

if i+1 <= rows and j-1 >= 0:
	if matrix[i+1][j-1] == '#':
		neighbours = neighbours + 1

Wie könnte ich das denn sonst machen? Ich nehme an, Python beschwert sich auch darüber, wenn die if-Abfrage garnicht ausgeführt wird. Irgendjemand eine Idee?

edit:
Das mit dem Fehler konnte ich beseitigen, aber irgendwie klappt das immer noch nicht so richtig, ich hänge mal den Quellcode an, das Problem liegt in der next_step Funktion irgendwie...

http://www.ubuntuusers.de/paste/2920/

edit2:
Ich bin vielleicht so blöd... hab nen Teil, den ich zum Testen reingemacht hab, nicht mehr rausgemacht... kein Wunder, dass das sponn.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4686

Wohnort: Berlin

Du arbeitest mit globalen Namen, das ist nicht gern gesehen. Damit macht man Programme letztendlich unübersichtlicher und Funktionen nicht nur von den Parametern, sondern von ihrer Umgebung abhängig. Vergiss am besten das Schlüsselwort global. Werte sollten Funktionen über Argumente betreten und über Rückgabewerte verlassen.

rows und cols sind auch nicht wirklich nötig, da diese Information auch in den Listen enthalten sind. Man kann die Aussmasse mit len(matrix) und len(matrix[0]) ermitteln.

Oft sind die Indizes auch gar nicht nötig. Man kann direkt über die Elemente in Containerobjekten in einer for Schleife iterieren. show_gamefield() kann man zum Beispiel so schreiben:

def show_gamefield(matrix):
    for row in matrix:
        print ''.join(row)

Wie man am Syntaxhighlighting erkennen kann, bindest Du den Namen von der map() Funktion in der fill() Funktion an eine Zeichenkette. Das ist zwar nicht verboten, sollte man aber nicht machen.

Die next_step() Funktion ist ziemlich lang und enthält viele ähnliche if Anweisungen die man in eine Schleife zusammenfassen könnte. Die Namen n2c und n2l werden nicht benutzt.

Das Zählen von lebenden Nachbarzellen kann man zum Beispiel so schreiben:

def count_neighbours(matrix, row, column):
    result = 0
    for i, j in ((row + row_delta, column + column_delta)
                 for row_delta in xrange(-1, 2)
                 for column_delta in xrange(-1, 2)
                 if not row_delta == column_delta == 0):
        try:
            if matrix[i][j] == '#':
                result += 1
        except IndexError:
            pass
    return result

Die Zeile new_matrix = matrix tut sicher nicht das was Du erwartest. Es wird keine Kopie angelegt, sondern lediglich das matrix Objekt zusätzlich an den Namen new_matrix gebunden. Der folgende Code operiert also ausschliesslich auf dem selben Objekt. Wenn Du anstelle des offenbar gewünschten Kopierens ein "leeres" Feld erzeugst, dann könnte next_step() so aussehen:

def next_step(matrix):
    rows = len(matrix)
    columns = len(matrix[0])
    new_matrix = [['.'] * columns for dummy in xrange(rows)]
    for i in xrange(rows):
        for j in xrange(columns):
            neighbours = count_neighbours(matrix, i, j)
            if ((matrix[i][j] == '#' and 2 <= neighbours <= 3)
                or (matrix[i][j] == '.' and neighbours == 3)):
                    new_matrix[i][j] = '#'
    return new_matrix

Jasmin Team-Icon

(Themenstarter)
Avatar von Jasmin

Anmeldungsdatum:
4. Juni 2006

Beiträge: 463

Eh, ja... das sagt mir im Moment noch nicht viel, zu dem Zeitpunkt konnte ich ja gerade erst zwei Stunden Python *grinst*

das mit der Zeile new_matrix = matrix hab ich schon geändert, weils nicht das gewünschte Ergebnis brachte 😉

trotzdem Danke für die Hilfe 😉

Antworten |