Pseudo-Labyrinth

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Randomtheories
User
Beiträge: 2
Registriert: Freitag 11. März 2011, 10:25

Hallo zusammen,

lerne gerade Python und habe mir als erste hinreichend komplexe Aufgabe die Programmierung einer Art von Labyrinth vorgenommen. Ich weiß, Code dazu, wie man Labyrinthe programmiert gibt es zu Hauf, aber ich wollte es selber versuchen, um mehr praktische Erfahrung mit Python zu sammeln.

Hier erstmal mein Pseudocode:

Code: Alles auswählen

1. erstelle ein 20 x 20 Felder großes Array
2 .setze eine "Mauer" auf zehn zufällige Felder
3. gehe alle felder durch und prüfe die um sie herum liegenden Felder darauf, ob kein weiteres Feld an sie grenzt (lege Kandidaten für neue Mauerfelder fest)
4. aus den Kandidaten für jedes Mauerstück wähle einen aus und füge ihn der Liste hinzu, welche die Mauerstücke enhält
5. führe Schritt 4&5 solange aus, bis kein Mauerfeld mehr Kandidaten aufweist
Ich habe erst die wichtigen Methoden (bis auf 5) implementiert und es hat auch soweit funktionert. Jetzt habe ich die Methoden und Attribute in einer Klasse "maze" zusammengefasst und es funktioniert nichts mehr. Da ich das erste Mal mit Klassen arbeite bin ich etwas überfordert zu sehen, wo ich überall fehler gemacht habe. Ich hoffe, dass ihr mir sagen könnt, wo meine Fehler liegen. Ich freue mich außerdem auch über allgemeine Hinweise, wie ich meinen Code besser und eleganter gestalten kann.

Vielen Dank schonmal für's Lesen. Hier ist mein Code soweit:

Code: Alles auswählen

import random
class maze:
    def __init__(self):
        self.grid = [(x, y) for x in range(20) for y in range(20)]
        self.walls = random.sample(self.grid, 10)
       
    #find neighboring available squares
    def findneighs(self, coo, coos):
        neighs = []
        for x in range(-1, 2):
            for y in range(-1, 2):
                if (coo[0]+x, coo[1]+y) not in coos:            
                    neighs.append((coo[0]+x, coo[1]+y))
        return neighs
Der Code hier läuft jetzt, aber ich bin mir nicht sicher, ob er richtig ist. Auf jeden Fall ist er häßlich.

Code: Alles auswählen

    #Appends one new wall to all existing walls
    def buildwalls(self):
        dummy = []
        for wall in self.walls:
            dummy.append(self.buildwall(wall))
        for x in dummy:
            if x not in self.walls:
                self.walls.append(x)

    #Builds one next to an existing wall
    def buildwall(self, wall):    
        candidates = []
        if len(findneighs(wall, self.walls)) > 7:
            for neighbor in findneighs(wall, self.walls):
                if len(findneighs(neighbor, self.walls)) > 7:
                    candidates.append(neighbor)                
        if len(candidates) > 0:
            return random.sample(candidates, 1)[0]
        else:
            return []

    #Show the maze
    def printmaze(self):
        someGrid = []
        for i in range(20):
            someGrid.append(20*['o'])
        for wall in self.walls:
            someGrid[wall[0]][wall[1]] = 'x'
        print someGrid

    def countwalls(self):
        print len(walls)
edit: hab jetzt noch mal zwei kleine Änderungen vorgenommen, damit der Code überhaupt läuft. Die "Walls"-Methode hat jetzt eine zusätzliche Schleife, ist aber nicht wirklich fertig. Außerdem habe ich noch zwei Testmethoden hinzugefügt: printmaze stellt das maze als liste dar und countwalls gibt an, ob die walls-methode überhaupt funktioniert (tut sie derzeit noch nicht...)
BlackJack

@Randomtheories: Klassennamen werden per Konvention in "MixedCase" geschrieben, also in diesem Falle `Maze`.

Extrem unelegant finde ich die Abkürzungen. Bei ``def findneighs(self, coo, coos)`` weiss ich nicht ob ich lachen oder weinen soll. Die "Methode" ist auch gar keine Methode sondern eine Funktion. Sie benötigt so wie sie da steht weder die Klasse noch das Exemplar eines `Maze`. Also entweder umschreiben, als Funktion heraus ziehen, oder zumindest eine `staticmethod()` daraus machen, um zu dokumentieren, dass das Absicht ist.

An einigen Stellen kann man "list comprehensions" einsetzen. Andererseits sieht es auch danach aus, als wenn einige Listen durch `set`\s ersetzt werden könnten.

``random.sample(candidates, 1)[0]`` ist eine ziemlich umständliche Art um ``random.choice(candidates)`` zu schreiben.

In `buildwall()` rufst Du ``findneighs(wall, self.walls)`` zweimal auf. Es wäre wohl effizienter das nur einmal zu tun und das Ergebnis an einen Namen zu binden.

Methoden die nur dem Aufbau des `Maze` dienen und nie vom Benutzer von aussen aufgerufen werden sollten, könnte man noch mit einem führenden Unterstrich versehen, um das zu dokumentieren.

Deine Beschreibung vom Algorithmus passt nicht so ganz zur Implementierung: Du legst gar kein 20×20 Array an.
Antworten