2D-Liste

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.
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

Hallo!

Ich stehe mal wieder vor einem Problem:
Ich muss eine Art Karte abbilden koennen. Diese besteht aus n mal m Feldern und ist immer rechteckig. Jedes Feld soll durch ein Zeichen dargestellt werden, und am Ende soll diese Karte in einer Datei gespeichert werden. Da diese Karte jedoch zur Laufzeit erstellt wird, weiss ich nie, wie hoch und breit sie werden wird. Ich dachte daran, das Ganze in einer Liste mit mehreren Unterlisten darzustellen, z.B. so (fuer 8 mal 6 Felder):

Code: Alles auswählen

width = 8
height = 6
karte = [[" " for i in xrange(width)] for i in xrange(height)]
Der Benutzer befindet sich am Anfang an einem bestimmten Punkt. Jetzt gibt er ein, dass er sich z.B. nach rechts bewegen will. Dann soll kontrolliert werden, ob rechts der aktuellen Position schon ein Feld existiert, und wenn nein, soll eines erstellt werden. Außerdem soll bei einer Bewegung die aktuelle Position auf das aktuelle Feld gesetzt werden, so dass der Benutzer das aktuelle Feld modifizieren kann (eine Eigenschaft, wie z.B. das Symbol aendern). Irgendwann sollen die entstandenen Daten dann in eine Datei als Plaintext geschrieben werden (nicht benutzte Felder als Leerzeichen, so dass alles exakt untereinander ist).

Mir fehlt nun komplett die Idee, wie ich das angehen koennte.

Ich wuerde mich riesig freuen, wenn mir jemand helfen koennte.

Liebe Grueße
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann würde ich keine Liste nehmen, sondern ein Dictionary. Als Schlüssel verwendest du dann die Koordinaten: (x, y). Ob ein Schlüssel existiert kannst du dann mit der "has_key"-Methode abfangen oder du benutze Exceptions. Letzteres macht es ein wenig übersichtlicher.
Das Leben ist wie ein Tennisball.
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

EyDu hat geschrieben:Dann würde ich keine Liste nehmen, sondern ein Dictionary. Als Schlüssel verwendest du dann die Koordinaten: (x, y). Ob ein Schlüssel existiert kannst du dann mit der "has_key"-Methode abfangen oder du benutze Exceptions. Letzteres macht es ein wenig übersichtlicher.
Das hatte ich mir auch schon gedacht.
Aber wie stelle ich die Karte daen in der Karte gut da?
Wie kriege ich mit halbwegs gutem Code raus, wo ich anfangen muss zu schreiben usw?
Kann mir eventuell jemand etwas Code posten?
Waere sehr nett

Liebe Grueße
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

roschi hat geschrieben:Aber wie stelle ich die Karte daen in der Karte gut da?
Wie kriege ich mit halbwegs gutem Code raus, wo ich anfangen muss zu schreiben usw?
Kann mir eventuell jemand etwas Code posten?
Könntest du das noch etwas präzisieren, die Fragen ergeben für mich gerade keinen Sinn. Am besten mit mehr als fünf Worten. Vorzugsweise mit mehreren gut strukturierten Sätzen ;-)

Meinst du mit Schreiben, wie du die Karte dann in eine Datei bekommst? Dazu speicherst du dir jeweils den kleinsten und den größten x-Wert, das selbe natürlich noch mit den y-Werten. Dann gehst du einfach jeden möglichen Index durch und schaust was du schreiben musst.

Als Implementierung würde ich eine Klasse schreiben, welche entweder von "dict" erbt oder die Karte als Dictionary hält. Darauf kann man sich dann einige komfortable Methoden zusammenbauen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

EyDu hat geschrieben:
roschi hat geschrieben:Aber wie stelle ich die Karte daen in der Karte gut da?
Wie kriege ich mit halbwegs gutem Code raus, wo ich anfangen muss zu schreiben usw?
Kann mir eventuell jemand etwas Code posten?
Könntest du das noch etwas präzisieren, die Fragen ergeben für mich gerade keinen Sinn. Am besten mit mehr als fünf Worten. Vorzugsweise mit mehreren gut strukturierten Sätzen ;-)
Oh je :) Man sollte vielleicht doch nicht telefonieren, und nebenbei nachdenken (oder es versuchen) und gleichzeitig Posten.
Tut mir leid, ich erklaer es richtig:
EyDu hat geschrieben:Meinst du mit Schreiben, wie du die Karte dann in eine Datei bekommst? Dazu speicherst du dir jeweils den kleinsten und den größten x-Wert, das selbe natürlich noch mit den y-Werten. Dann gehst du einfach jeden möglichen Index durch und schaust was du schreiben musst.

Als Implementierung würde ich eine Klasse schreiben, welche entweder von "dict" erbt oder die Karte als Dictionary hält. Darauf kann man sich dann einige komfortable Methoden zusammenbauen.
Genau das habe ich auch schon gedacht, aber geht es nicht noch ein bisschen schoener? Moeglich waere es zwar, aber irgendwie kommt mir das ein bisschen umstaendlich vor. Ich werde es wohl so machen. Ich dachte nur, es gibt eine huebschere Methode, die ich nur noch nicht kenne :-).

Ich danke vielmals!

Falls ich noch auf weitere Probleme stoßen sollte, werde ich es euch wissen lassen.

Liebe Grueße und vielen dank nochmals!
roschi


PS: Schon 200 Beitraege! Kam mir gar nicht soviel vor :-).
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Was ist denn daran nicht schön? Auch beim Speichern einer Karte, welche du durch verschachtelte Listen repräsentierst, musst du du jedes Feld einmal anfassen. Durch Dictionaries sparst du dir das Programmieren von einigen Verwaltungsvorgängen. Wenn du die Schnittstelle der Klasse gut schreibst, dann wird man kein Unterschied merken, ob man auf Listen oder auf einem Dictionary arbeitet.
Das Leben ist wie ein Tennisball.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Ist dein Hauptproblem jetzt, alles in eine Datei zu speichern oder die Struktur einer solchen Karte an sich? Du sprichst ja von beidem. Wenn es nur darum geht, irgendwie die Struktur abzuspeichern, kannst du einfach pickle benutzen. Ansonsten musst du dir ein eigenes Format (wie von EyDu beschrieben) ausdenken oder aber die Logik irgendwie in XML/JSON/YAML abbilden.

Ich würde selbst nicht von dict erben (Ist eine Karte wirklich ein Dictionary bzw. ein Namensraum oder doch mehr?), sondern mit einer Field Klasse beginnen. Ich habe für meinen Tetris Klon Tetrix0r (der schon ganz schön angestaubt ist, aber nunja) soetwas gemacht samt allem drum und dran. Ist nicht das Musterbeispiel für klaren und gut strukturierten Code, aber kannst du dir ja mal anschauen. Such einfach im Forum danach.

dict.has_key ist übringens deprecated. Man sollte "key in dict" benutzen.
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

EyDu hat geschrieben:Was ist denn daran nicht schön? Auch beim Speichern einer Karte, welche du durch verschachtelte Listen repräsentierst, musst du du jedes Feld einmal anfassen. Durch Dictionaries sparst du dir das Programmieren von einigen Verwaltungsvorgängen. Wenn du die Schnittstelle der Klasse gut schreibst, dann wird man kein Unterschied merken, ob man auf Listen oder auf einem Dictionary arbeitet.
Stimmt schon, aber es sieht schon ein wenig lustig aus die Eintraege so zu zerstueckeln :-).
str1442 hat geschrieben:Ist dein Hauptproblem jetzt, alles in eine Datei zu speichern oder die Struktur einer solchen Karte an sich? Du sprichst ja von beidem. Wenn es nur darum geht, irgendwie die Struktur abzuspeichern, kannst du einfach pickle benutzen. Ansonsten musst du dir ein eigenes Format (wie von EyDu beschrieben) ausdenken oder aber die Logik irgendwie in XML/JSON/YAML abbilden.
Ich sprach von beidem. Ich moechte die Karte dann richtig in eine Datei schreiben, als ASCI-Grafik.
str1442 hat geschrieben:Ich würde selbst nicht von dict erben (Ist eine Karte wirklich ein Dictionary bzw. ein Namensraum oder doch mehr?), sondern mit einer Field Klasse beginnen. Ich habe für meinen Tetris Klon Tetrix0r (der schon ganz schön angestaubt ist, aber nunja) soetwas gemacht samt allem drum und dran. Ist nicht das Musterbeispiel für klaren und gut strukturierten Code, aber kannst du dir ja mal anschauen. Such einfach im Forum danach.
Ich hab mir das Tetris frueher schonmal angeschaut, aber schon wieder alle Details vergessen :-(. Ich habe die Struktur jetzt so, wie von EyDu vorgeschlagen wurde: eine Klasse, die ein Dictionary besitzt, welches die koordinaten als key und das jeweilige symbol als value enthaelt. Jetzt implementiere ich das Schreiben in eine Datei - mal sehen.

Liebe Grueße
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Code: Alles auswählen

from random import randrange

# Initialisierung
breite, hoehe = 20, 12
karte = [["_" for i in xrange(breite)] for i in xrange(hoehe)]
# Zufallsbefüllung
for i in xrange(40):
    x, y = randrange(breite), randrange(hoehe)
    karte[y][x] = "x"
# Karte speichern
datei = open("karte.txt","w")
for zeile in karte:
    datei.write("".join(zeile)+"\n")
datei.close()
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Zur Initialisierung:

Code: Alles auswählen

karte = [['_'] * breite] * hoehe
Grüße... Heiko
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
BlackJack

@bwbg: Keine gute Idee:

Code: Alles auswählen

In [3]: karte = [['_'] * 10] * 5

In [4]: karte[1][3] = '*'

In [5]: karte
Out[5]:
[['_', '_', '_', '*', '_', '_', '_', '_', '_', '_'],
 ['_', '_', '_', '*', '_', '_', '_', '_', '_', '_'],
 ['_', '_', '_', '*', '_', '_', '_', '_', '_', '_'],
 ['_', '_', '_', '*', '_', '_', '_', '_', '_', '_'],
 ['_', '_', '_', '*', '_', '_', '_', '_', '_', '_']]
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Zusammen

BlackJack hat einmal etwas vorgestellt, welches ich schon mehrfach erfolgreich eingesetzt habe:
http://www.python-forum.de/post-105266.html#105266

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

BlackJack hat geschrieben:@bwbg: Keine gute Idee:
(...)
Ist auch irgendwie logisch. Danke für die Info.

Grüße... Heiko
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hier ist mein Vorschlag:

Code: Alles auswählen

class VirtualMap(object):
    def __init__(self, default=None):
        self.fields = {}
        self.default = default
    
    def __getitem__(self, coord):
        return self.fields.get(coord, self.default)
    
    def __setitem__(self, coord, value):
        self.fields[coord] = value
    
    @property
    def minx(self): return min(x for x, y in self.fields.iterkeys())
    
    @property
    def maxx(self): return max(x for x, y in self.fields.iterkeys())
    
    @property
    def width(self): return self.maxx - self.minx + 1

    @property
    def miny(self): return min(y for x, y in self.fields.iterkeys())

    @property
    def maxy(self): return max(y for x, y in self.fields.iterkeys())
    
    @property
    def height(self): return self.maxy - self.miny + 1
    
    def __str__(self):
        minx, maxx, miny, maxy = self.minx, self.maxx, self.miny, self.maxy
        return "%s-%s, %s-%s\n%s" % (minx, maxx, miny, maxy,
            "\n".join(" ".join(self[x, y] or " " 
                for x in range(minx, maxx + 1))
                    for y in range(miny, maxy + 1)))
Stefan
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo sma

Ich finde dein Vorschlag interessant. Um besser zu verstehen was dabei genau abläuft könntest du bitte ein kleines Anwendungsbeispiel für eine 2D-Liste mit der Dimesion x=10 und y=10 zeigen, welche man mit:

Code: Alles auswählen

virtual_map = VirtualMap()
print virtual_map
auf die Konsole ausgeben kann.

Danke für deine Bemühung. Sorry für die eventuell naive Frage.

Gruss wuf :wink:
Take it easy Mates!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Im Prinzip smas __str__-Methode:

Code: Alles auswählen

v = VirtualMap(" ")
#fill map here
for y in range (10):
    for x in range(10):
        v[x,y] = "x" if (x+y)%2 else "o"

for y in range(v.miny, v.miny + v.height):
    for x in range(v.minx, v.minx +v .width):
        print v[x, y],
    print
ungetestet.
Zuletzt geändert von EyDu am Sonntag 21. Juni 2009, 10:37, insgesamt 1-mal geändert.
Das Leben ist wie ein Tennisball.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Was kann ich, was nicht auch du ausprobieren könntest?

Code: Alles auswählen

>>> m = VirtualMap('.')
>>> m[0,0] = m[9,9] = 'x'
>>> print m
0-9, 0-9
x . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . x
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo sma und EyDu

Danke für eure Antworten. Beides funktioniert.
sma hat geschrieben:Was kann ich, was nicht auch du ausprobieren könntest?
Wenn ich es nicht versucht hätte würde ich dich auch nicht fragen!

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

Hallo!

Hier hat sich ja waehrend meiner Abwesenheit viel um die Frage gedreht, wie ich sehe :-).

Mein jetziger Stand:
Der Mapper funktioniert soweit.
Den Code der Map-Klasse findet ihr hier: http://paste.pocoo.org/show/125687/

Verwendet wird das Ganze dann z.B. so:

Code: Alles auswählen

# liste der verschiedenen himmelsrichtungen,
# ihren positionsaenderung auf den achsen
# und den Gegenrichtungen
# (die in dem beispiel aber nicht gebraucht werden)
DIRECTIONS = {"n":(0, 1, "s"),
              "o":(1, 0, "w"),
              "s":(0, -1, "n"),
              "w":(-1, 0, "o"),
              "no":(1, 1, "sw"),
              "so":(1, -1, "nw"),
              "sw":(-1, -1, "no"),
              "nw":(-1, 1, "so")}
# benutzung der klasse
map = Map()
current_cords = (0, 0)
# beispiel fuer norden:
direction = "n"
new_cords = (current_cords[0] + DIRECTIONS[direction][0],
             current_cords[1] + DIRECTIONS[direction][1])
# ...
# hier werden im orginialscript noch informationen
# gespeichert, damit die aktion wieder rueckgaengig
# gemacht werden kann.
# ...
current_cords = new_cords
map.write_field(current_cords, DEFAULT_SYMBOL)
# karte in datei schreiben
map.write_into_file("map.txt")
Der Benutzer kann sich nun (in einem Spiel) durch die Himmelsrichtungen bewegen, und eine Funktion im Script wird dabei aufgerufen, die die Aenderungen dann in die Karte eintraegt. Nun habe ich allerdings noch ein grundsaetzliches Problem:
Der Spieler geht z.B. folgenden Weg: norden, nordem, norden, osten, sueden, sueden, sueden.
Man wuerde nun in der karte das hier sehen:

Code: Alles auswählen

##
##
##
##
Keiner weiß nun, ob er nicht vielleicht immer zwischen Westen und Osten gewechselt hat, da man keine Verbindungen zwischen den einzelnen Feldern sieht.
Hat vielleicht jemand einen Vorschlag, wie ich diese Verbindungen noch mit in die Karte schreiben koennte? Mir wuerde ein Beispielcode sehr helfen.

lg und vielen Dank fuer die Hilfe
roschi

[edit]
Typo im Code gefixt.
[/edit]
Zuletzt geändert von roschi am Montag 29. Juni 2009, 23:25, insgesamt 1-mal geändert.
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Du könntest die Rauten ersetzen z.B. durch Buchstaben N, S, O, W, wobei der Buchstabe jeweils angibt, aus welcher Richtung das Feld belegt wurde.
Antworten