Scala - Zweidimensionale IndexedSeq statt Arrays

Esteba

Lt. Junior Grade
Registriert
März 2013
Beiträge
279
Ich entwickle für ein Uni-Projekt an einem kleinen Spiel in Scala. Dabei versuche ich, das ganze möglichst funktional zu implementieren. Der GameState soll keine expliziten Zustandsänderungen zulassen, um zu verhindern dass gleichzeitige Zugriffe von zwei Spielern zu Inkonsistenzen oder sogar Deadlocks führen. Stattdessen soll bei jedem Zug ein neuer GameState aus dem alten erzeugt werden.

Da der GameState auch das Spielfeld, ein zweidimensionales Gitter, umfasst, benötige ich einen Ersatz für die Arrays aus Java. IndexedSeq scheint die dafür vorgesehene Collection zu sein.


Erste Frage: Muss der Typ des Spielfelds IndexedSeq[IndexedSeq[Int]] sein, weil es zweidimensional ist, oder sollte ich eine einzelne Liste verwenden? Muss ich mir dann selber merken, wieviele Spalten eine Zeile lang ist? (Ich habe gesehen, dass es zumindest auch eine Methode fill() mit zwei Parametern gibt, die eine zweidimensionale IndexedSeq erzeugt.)

Zweite Frage: Wie ändere ich eine einzelne Zelle des Spielfelds, sprich, wie erzeuge ich eine neue IndexedSeq aus einer alten, bei der nur der Wert an einem bestimmten Index ersetzt wird? Ich war eigentlich davon überzeugt, dass es dafür einen Operator bzw. eine Methode geben muss, so wie man mit "alteMap + (key,value)" eine neue Map mit zusätzlichem Schlüssel-Werte-Paar erzeugen kann. Ich konnte aber bei Google beim besten Willen nichts dergleichen finden... Nur hinten an die Liste anhängen ist kein Problem...

Ergibt das, was ich machen will, so vielleicht gar keinen Sinn? Oder muss ich mir tatsächlich selbst eine Funktion schreiben, die eine IndexSeq mit den Werten aus einer anderen IndexedSeq initialisiert (und das Element an Index x abändert)?
 
Musste im Studium ein Spiel in Scala bauen, bei welchem ich ein 3D-Feld benötigte.

Einfache Lösung: Nutze nur eine einzige IndexedSeq und lasse das mit dem Verschachteln. Dann brauchst du nur eine Methode, welche die Koordinaten auf den Index umrechnet. Nicht, dass es auch anders ginge, aber das macht eigentlich alles einfacher statt komplizierter (vorausgesetzt, dein Spielfeld ist rechteckig oder folgt einer anderen einfachen Struktur). Wenn du beispielsweise ein quadratisches Spielfeld mit der Seitenlänge n hast, dann kommst du an den Index mit y * n + x. Bei einem 3D-Würfel wäre es entsprechend x + y * n + z * n^2. Hat aber nichts mit Scala zu tun, würde ich auch in Java etc. so machen. Wichtig ist nur, dass du eine IndexedSeq nimmst, da dort der Zugriff auf beliebige Elemente in konstanter Zeit ausgeführt wird. Vector ist ganz gut dafür geeignet.

Zu deiner zweiten Frage: die Methode updated macht genau das.

def updated(index: Int, elem: A): IndexedSeq[A]
 
Zuletzt bearbeitet:
Ich hab es jetzt genau so gelöst, mit einer einfachen IndexedSeq und einer Umrechnung der Koordinaten.
Vielen Dank für die Antwort, hat mir wirklich sehr geholfen!
 
Zurück
Oben