Ich möchte Spielfiguren verschiendener Typen auf einem Spielfeld platzieren. Als Beispiel kann man sich ein Schachbrett mit Schachfiguren vorstellen.
Die Idee ist, die Spielfiguren als Objekte zu modellieren. Verschiedene Spielfiguren sind dabei Instanzen verschiedener Klassen. Das Spielfeld ist ein rechteckiges Feld. Auf jedem Feld kann maximal eine Spielfigur stehen.
Folgender Ansatz zur Modellierung würde mir gefallen. Es gibt Objekte der Klassen A, B, C usw. Instanzen der Klassen sollen in einem Array ar (edit) mit numerischen Indizes (/edit) gespeichert werden.
Wie kann man den obigen Ansatz in CSharp darstellen? Die Elemente eines Arrays in CSharp haben meines Wissens immer genau einen Typ. Sowas wie ar(0,0) = new(A); /* eckige Klammern sind im BB-Code nicht erlaubt */ ar(1,1) = new(B); ... geht wohl nicht. Gibt es hier einen (eleganten) Lösungsansatz? Wenn ja, welcher Typ hat das Array, und wie erkenne ich ob a) ein Objekt auf den ar(x,y) steht und b) aus welcher Klasse das Objekt stammt
Ich hoffe ich konnte die Idee klar darstellen. Wenn nicht bitte fragen :-)
Du hast (mindestens) zwei Möglichkeiten: 1) Listen vom Typ object 2) Generische Listen
Beispiel Typ object:
class Spielfeld { ArrayList _map = new ArrayList(); public Spielfeld() { for (int y = 0; y < 8; y++) { _map.Add(new ArrayList()); for (int x = 0; x < 8; x++) ((ArrayList)_map[y]).Add(null); } }
public object GetAt(int x, int y) { return ((ArrayList)_map[y])[x]; }
public void Test() { object t = GetAt(10, 10); if (t is Figur1) // Mach was mit ((Figur1)t) ; } } class Figur1 { } class Figur2 { } class Figur3 { }
Beispiel für Generische Listen:
class Spielfeld { List<List<Figur>> _map = new List<List<Figur>>(); public Spielfeld() { for (int y = 0; y < 8; y++) { _map.Add(new List<Figur>()); for (int x = 0; x < 8; x++) _map[y].Add(null); } }
public Figur GetAt(int x, int y) { return _map[y][x]; }
public void Test() { Figur t = GetAt(10, 10); if (t is Figur1) // Mach was mit ((Figur1)t) ; } } class Figur1 : Figur { } class Figur2 : Figur { } class Figur { }
Das „t is Figur1“ würde ich vermeiden und stattdessen in der Basisklasse von den Subklassen zu implementierende abstrakte Methoden definieren, welche eine solche Unterscheidung unnötig machen.
@DaSpors: Dankesehr schonmal. Mit gefällt in Variante 1 die Idee mit Arraylists gut, und der Hinweis auf den Zugriff in der Funktion GetAt() ist prima, ich hätte an dieser Stelle wohl länger geknobelt. Dafür gibts eine positive Bewertung :-)
Die Klasse Figur sollte abstract sein. Statt GetAt kann ein Indexer (this[x,y]) verwendet werden. Wenn die Größe des Spielfeldes konstant und bekannt ist (wie beim Schach) wäre ein jagged Array eine effiziente Alternative zur List<List<T>>.
"Mit gefällt in Variante 1 die Idee mit Arraylists gut". Das ist aber die Steinzeitvariante die mit Objekt Orientierung nur wenig am Hut hat. Variante 2 (mit der Basisklasse) ist aufgrund von Polymorphie die enzig zu verwendende. Vergiss die ArrayList (außer du arbeitest mit .net 1.0 ;)
In Java würde ich ein Interface "Figur" definieren und alle Spielfiguren müßten das Interface implementieren. In Java kann man Collections von Interfaces bauen.
interface Figur {...}
public class Dame implements Figur {}
public class Bauer implements Figur {}
List<? extends Figur> feld = new ArrayList<? extends Figur> ();
Da C# stark von Java übernommen hat, würde ich davon ausgehen, dass C# das auch kann. Ich kann es nur gerade nicht prüfen.
Ja C# kann das. In den bisherigen Antworten wurde statt dem Interface eine abstrakte Klasse verwendet. Dies hat den Vorteil dass darin bereits ein "Template" definiert werden kann das für alle Spielfiguren gleich ist.