Frage

Ich brauche eine 2-Radius-Karte, die vom aktuellen Raum des Spielers in einem MUD gezeichnet wird, das ich in Python erstelle (oder mehr, wenn möglich).Räume sind als Container mit a eingerichtet self.exits = {'west':1, 'north':2} Dabei ist der Schlüssel die Richtung, in der sich der Wert (UID des angrenzenden Raums) befindet.Räume werden nur auf diese Weise verknüpft.Ein Spieler mit einem self.location von 0 könnte „n“ eingeben und sein Standort, basierend auf der obigen Variablen, wäre dann 2 und an den Inhalt dieses Raums würde die UID des Spielers angehängt.

Daher möchte ich eine Karte anzeigen lassen, die basierend auf der obigen Variablen wie folgt aussieht, wobei „u“ der aktuelle Standort des Spielers ist.

    [ ]
     |
[ ]-[u]

Ich habe es erreicht Das Teil, da dies nur ein Radius von 1 ist.Hier ist ein kleiner (für die Veröffentlichung hier stark veränderter) Ausschnitt davon, wie ich das gemacht habe, und Sie werden sehen, warum ich poste, da es sich um schlechten Code handelt.

mloc = '[u]'
mn = '   '
mw = '   '
spn= ' '
spw= ' '
for Exit in room.exits.keys():
  if Exit == 'north':
    mn = '[ ]'
    spn = '|'
  if Exit == 'west': 
    mw = '[ ]-'
# player.hear() is our function for printing a line to the player's screen
player.hear('    '+mn)
player.hear('     '+sp)
player.hear(mw+mloc)

In meinem Wahnsinn habe ich es geschafft, dass dies mit allen 8 verschiedenen Richtungen (Diagonalen und ohne Einbeziehung von oben und unten) funktioniert.Aber ich muss dann die Räume, die ich gerade mit meinem ersten für Schleife analysiert habe, anschließe und dann diese zeichnen und dann alles ausrichten und dann die Überlappung der (sp) Aces wie '' oder 'berücksichtigen. | ' Wenn es Wege gibt, die sich gegenseitig überqueren.Diese kleine Aufgabe wurde sofort zu einem Albtraum und es dauerte bis zu 200 Zeilen, bis ich fertig war.

Eine weitere Hürde ist, dass ich nur Zeile für Zeile drucken kann.Wenn die Karte also 50 Zeichen hoch ist, muss ich sie haben player.hear() auf 50 Zeilen, wogegen ich nichts dagegen habe.Denken Sie daran, bevor Sie eine Antwort posten.

Ich bin auch nicht wählerisch, was die Formatierung angeht.Ich möchte einfach nur eine „Karte auf einen Blick“, die den Spielern beim Reisen um die Welt hilft.

Danke Leute.Ich hoffe, ich habe genügend Informationen bereitgestellt.Lassen Sie es mich wissen, wenn nicht.(Hier ist ein Link zum gesamten (unvollendeten und SCHRECKLICHEN) Modul, auf das ich mich beziehe. Map.py

War es hilfreich?

Lösung

Dieser Code ist in ernsthaften Schwierigkeiten.Beginnen wir mit dem Design von Grund auf.Dies wird hoffentlich eine gute Lektion zum Entwerfen und Erstellen von Klassen und Datenstrukturen sein.

Zunächst sollten Sie Ihren Code um a organisieren Map Klasse, die dann Ihre Räume als Raster darstellt.Sie sollten nicht an „Raum 1“, „Raum 2“ usw. denken (was auf einer Karte sehr schwer zu verfolgen ist), sondern Räume anhand von Koordinaten betrachten.

Nun gibt es ein paar mögliche Features, die wir zu Beginn ignorieren, darunter, dass der Spieler nur die Räume sieht, die er besucht hat, dass der Spieler in der Mitte der Karte bleibt und diagonale Pfade.Wenn Sie sie möchten, können Sie sie später hinzufügen, sobald die Grundfunktionalität funktioniert.Im Moment streben wir etwas an, das in etwa so aussieht:

[ ]-[u] [ ] [ ]
 |
[ ]-[ ]-[ ] [ ]
     |
[ ]-[ ]-[ ] [ ]
 |
[ ]-[ ]-[ ]-[ ]

Das heißt, wir stellen es als Raster dar, in dem einige Räume miteinander verbunden sind und andere nicht.Lassen Sie uns jeden Raum über ein Koordinatenpaar verfügen, etwa so:

      0   1   2   3
   0 [ ]-[u] [ ] [ ]
      |
   1 [ ]-[ ]-[ ] [ ]
          |
   2 [ ]-[ ]-[ ] [ ]
      |
   3 [ ]-[ ]-[ ]-[ ]

Sei x oben und y seitlich.Oben links ist (0, 0), das mit [u] darin ist (0, 1).

Was sind nun die Bestandteile unseres Map Klasse?

  1. Kartenhöhe:ganze Zahl

  2. Kartenbreite:ganze Zahl)

  3. Spieler_x, Spieler_y:Koordinaten des Spielers

  4. Mögliche Pfade:eine Liste von Raumpaaren, zwischen denen wir wechseln können.Die obige Karte würde wie folgt dargestellt werden:

    [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (2, 1)),
     ((1, 0), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)), ((0, 2), (0, 3)),
     ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3), (3, 3))]
    

Beachten Sie, dass ich jedes Paar so angeordnet habe, dass das größere Tupel zuerst kommt (das ist später wichtig).

Nachdem wir nun unser Design haben, schreiben wir es auf Map Klasse!

Ich kann mir vier Methoden vorstellen, die wir wollen: print_map, move, und ein Initialisierer.Die Initialisierung ist einfach:Legen Sie einfach die vier oben aufgeführten Attribute fest:

class Map:
    def __init__(self, height, width, player_x, player_y, paths):
        self.height = height
        self.width = width
        self.x = player_x
        self.y = player_y
        self.paths = paths

Jetzt, move ist ganz einfach.Gegeben eine Richtung N/E/S/W:

    def move(self, direction):
        if direction == "n":
            if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                print "Cannot go north"
            else:
                self.y -= 1

Der move Die Funktion für „Norden“ prüft lediglich, ob es einen Weg zu dem Raum über dem Raum gibt, in dem wir uns befinden.

Nun zum interessantesten Teil:Drucken der Karte.Dies erreichen Sie, indem Sie eine Schleife über die Zeilen (0 bis self.height) und über die Spalten (0 bis self.width). (Notiz:Du kannst es nicht verwenden print In dieser Situation wird automatisch eine neue Zeile oder ein Leerzeichen nach der Zeichenfolge eingefügt.Stattdessen verwenden wir sys.stdout.write.

def print_map(self):
    for y in range(0, self.height):
        # print the yth row of rooms
        for x in range(0, self.width):
            if self.x == x and self.y == y:
                sys.stdout.write("[u]")  # this is the player's room
            else:
                sys.stdout.write("[ ]")  # empty room
            # now see whether there's a path to the next room
            if ((x, y), (x + 1, y)) in self.paths:
                sys.stdout.write("-")
            else:
                sys.stdout.write(" ")
        # now that we've written the rooms, draw paths to next row
        print  # newline
        for x in range(0, self.width):
            sys.stdout.write(" ")  # spaces for above room
            if ((x, y), (x, y + 1)) in self.paths:
                sys.stdout.write("|  ")
            else:
                sys.stdout.write("   ")
        print

Jetzt lasst uns alles zusammensetzen und ausprobieren.Hier ist der Code:

import sys

class Map:
    def __init__(self, height, width, player_x, player_y, paths):
        self.height = height
        self.width = width
        self.x = player_x
        self.y = player_y
        self.paths = paths

    def move(self, direction):
        if direction == "n":
            if ((self.x, self.y - 1), (self.x, self.y)) not in self.paths:
                print "Cannot go north"
            else:
                self.y -= 1
        if direction == "s":
            if ((self.x, self.y), (self.x, self.y + 1)) not in self.paths:
                print "Cannot go south"
            else:
                self.y += 1
        if direction == "e":
            if ((self.x, self.y), (self.x + 1, self.y)) not in self.paths:
                print "Cannot go east"
            else:
                self.x += 1
        if direction == "w":
            if ((self.x - 1, self.y), (self.x, self.y)) not in self.paths:
                print "Cannot go west"
            else:
                self.x -= 1

    def print_map(self):
        for y in range(0, self.height):
            # print the yth row of rooms
            for x in range(0, self.width):
                if self.x == x and self.y == y:
                    sys.stdout.write("[u]")  # this is the player's room
                else:
                    sys.stdout.write("[ ]")  # empty room
                # now see whether there's a path to the next room
                if ((x, y), (x + 1, y)) in self.paths:
                    sys.stdout.write("-")
                else:
                    sys.stdout.write(" ")
            # now that we've written the rooms, draw paths to next row
            print  # newline
            for x in range(0, self.width):
                sys.stdout.write(" ")  # spaces for above room
                if ((x, y), (x, y + 1)) in self.paths:
                    sys.stdout.write("|  ")
                else:
                    sys.stdout.write("   ")
            print


paths = [((0, 0), (1, 0)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1),
         (2, 1)), ((1, 1), (1, 2)), ((0, 2), (1, 2)), ((1, 2), (2, 2)),
         ((0, 2), (0, 3)), ((0, 3), (1, 3)), ((1, 3), (2, 3)), ((2, 3),
         (3, 3))]
m = Map(4, 4, 0, 0, paths)

while True:
    m.print_map()
    direction = raw_input("What direction do you want to move? [n/e/s/w] ")
    m.move(direction)

Beachten Sie, dass ich unten einen Abschnitt hinzugefügt habe, der eine Karte erstellt und es dem Spieler ermöglicht, sich darauf zu bewegen.So sieht es aus, wenn es läuft:

Davids-MacBook-Air:test dgrtwo$ python Map.py 
[u]-[ ] [ ] [ ] 
     |          
[ ] [ ]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] e
[ ]-[u] [ ] [ ] 
     |          
[ ] [ ]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] s
[ ]-[ ] [ ] [ ] 
     |          
[ ] [u]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] w
Cannot go west
[ ]-[ ] [ ] [ ] 
     |          
[ ] [u]-[ ] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

What direction do you want to move? [n/e/s/w] e
[ ]-[ ] [ ] [ ] 
     |          
[ ] [ ]-[u] [ ] 
     |          
[ ]-[ ]-[ ] [ ] 
 |              
[ ]-[ ]-[ ]-[ ] 

Es gibt viele Verbesserungen, die an diesem Code vorgenommen werden können (insbesondere die move Methode ist repetitiv), aber es ist ein guter Anfang.Versuchen Sie, die Karte im Format 20x20 zu erstellen, und Sie werden sehen, dass sie sich problemlos erweitern lässt.

voraussichtliche Ankunftszeit:Das sollte ich beachten print_map könnte in einer viel kürzeren Form umgeschrieben werden als etwa:

def print_map(self):
    for y in range(0, self.height):
        print "".join(["[%s]%s" %
                    ("u" if self.x == x and self.y == y else " ",
                     "-" if ((x, y), (x + 1, y)) in self.paths else " ")
                        for x in range(0, self.width)])
        print " " + "   ".join(["|" if ((x, y), (x, y + 1)) in self.paths
                              else " " for x in range(0, self.width)])

Aber das ist etwas intensiver.

Andere Tipps

Ich habe dies als Übung getan, wo die Räume und das Gitter "sich drucken".Ich füge dies zur Diskussion hinzu, da es einfacher sein kann, mit einem eventuellen größeren Gitter einfacher zu implementieren.

Die ASCII-Karte

generasacodicetagpre.

Jede Zelle in diesem Gitter ist drei um drei von drei Set von '+'-Zeichen.Vier Räume sind mit ID-Wert von 1 bis 4 implementiert. Verbindungen zwischen den Räumen sind als Schrägstriche, Backlaslashes und Rohre dargestellt.

Der Code

generasacodicetagpre.

Die Bewegungsroutine ist nicht implementiert, und für diese Darstellung zur Arbeit wird nur einzelne Zeichen-IDs gut angezeigt.

Die Vorteile dieses Systems:

    .
  • Einfach, Räume hinzuzufügen und zu entfernen, um sie zu entfernen
  • Die Definition eines Raumes ist menschlich lesbar
  • Die Ausgabefunktionen überladen generakodicetagcode und somit Räume und Raster "drucken" und dies könnte für zukünftige Debugging oder Anpassung an zukünftige Formate nützlich sein, z.als Zellen in einer HTML-Tabelle.

Koordinatenbasierte Karten haben viele Vorteile, aber wenn man bedenkt, dass viele Qualitätsschlamms eine traditionelle Raumwelt nutzen, und die Menschen haben Automascher für viele Schlamm- und Schlammkunden gemacht, es ist nicht aus der Frage, dass ein Automobil für einen Schlamm ohne Koordinaten. Sie müssen nur mit Kindern mit Fall mit Fall umgehen.

Sie können jedoch immer noch die Antwort von @ David-Robinson verwenden. Wenn Sie möchten, ist, dass ein Minimap auf dem Player grob zentriert ist, und aktualisieren Sie sie dynamisch mit den Exitdaten. Versuchen Sie nicht, eine Karte des gesamten Gebiets aufrechtzuerhalten; Durch dynamisches Aktualisieren vermeiden Sie einige geografische Konflikte.

Zum Schreiben der Karte an einen Schlammkunden, ist alles, was Sie tun müssen, ist alles, was Sie tun müssen, Ihre Kartenzeile ordnungsgemäß beabstandet und kündigen Sie sie mit einer neuen Zeile. Sie legen alle Kartenzeilen in eine Liste ein, sodass sie als eine einzige Gruppe von Zeilen gesendet wird (Sie möchten, dass einige andere Zeile nicht zwischen Zeilen der Karte eingefügt werden, wenn sie beispielsweise die Sockel ausgesendet werden), und jeder Schlamm-Client druckt es aus ordnungsgemäß (mit einem Monospace-Schriftart).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top