[Java] Brainstorming: Schach

WhiZZler

Chancentod²
ID: 85586
L
6 Mai 2006
588
32
begrüße!

zum abschluss des java kurses müssen wir in einer gruppe ein projekt schreiben.. wir haben uns auf schach geeinigt.. das programm soll einfach spiele mit 2 spielern ermöglichen.. also keine ki oder der gleichen..

ich bin grade am überlegen, wie man das ganze am geschicktesten aufbauen könnte..
momentan habe ich folgenden ansatz:

- Start klasse mit der main methode:
hier findet hauptsächlich nur die datenhaltung statt.. ich wollte einen zweidimensionalen array mit dem schachfeld erstellen.. dass man über die "koordinaten" die jeweiligen felder abfragen kann, ob dort ein stein steht

- Figuren klasse:
eine allgemeine klasse, die grundsätzliche attribute wie besitzer und ähnliches sowie methoden, die für alle figuren benötigt werden beinhaltet

- Bauer, König, Dame, usw. Klassen
attribute, die für den jeweiligen typ gelten und hauptsächlich eine methode, die ermitteln kann, auf welche felder die jeweilige figur gehen kann

- Spielfeld klasse:
die verarbeitung, wenn ein zug ausgeführt wurde.. außerdem kann überprüft werden, ob ein spieler schach matt ist.. an sich wäre es eigentlich sinniger, die datenhaltung dann auch hier rein zu machen.. hmm.. nuja..

- Listener klasse:
die eventverarbeitung halt

- gui klasse:
alles was mit der oberfläche an sich zu tun hat


an sich ist die einteilung denke ich nicht ganz verkehrt.. das problem, das ich sehe ist allerdings, dass das mit dem array, in dem gespeichert wird, auf welchem feld welche figur ist, schwierig werden würde, da die objekte der spielfiguren ja alle von nem anderen typ sind.. sonst könnte man den array einfach vom typ figur erzeugen.. irgendwie steig ich nid so ganz dahinter, wie man das idealerweise lösen könnte ;) man könnte natürlich alles in die figuren klasse packen, aber mir gefällt die aufteilung nach art des spielsteins besser..

bin für denkansätze jeder art dankbar! falls jemand nen ganz anderen ansatz hat ist der auch willkommen ;)

danke im vorraus,
mfg
whizzler
 
Zuletzt bearbeitet:
und was hindert dich daran die einzelnen Figuren einfach von der Klasse Figur abzuleiten? Dann kannst du auch dein Array von Figuren nehmen.
 
- Start klasse mit der main methode:
hier findet hauptsächlich nur die datenhaltung statt.. ich wollte einen zweidimensionalen array mit dem schachfeld erstellen.. dass man über die "koordinaten" die jeweiligen felder abfragen kann, ob dort ein stein steht
also die Datenhaltung findet i.R. nicht in der Main statt, sondern in den nötigen Klassen, die dafür zuständig sind. Zb eine Spielfeld-Klasse.

- Figuren klasse:
eine allgemeine klasse, die grundsätzliche attribute wie besitzer und ähnliches sowie methoden, die für alle figuren benötigt werden beinhaltet

- Bauer, König, Dame, usw. Klassen
attribute, die für den jeweiligen typ gelten und hauptsächlich eine methode, die ermitteln kann, auf welche felder die jeweilige figur gehen kann
Ist eine gute Idee ;)
Sofern Bauer von Figur ableitet usw.

- Spielfeld klasse:
die verarbeitung, wenn ein zug ausgeführt wurde.. außerdem kann überprüft werden, ob ein spieler schach matt ist.. an sich wäre es eigentlich sinniger, die datenhaltung dann auch hier rein zu machen.. hmm.. nuja..
jup, die Haltung gehört hier hin.
Aber im Prinzip beinhaltet das Spielfeld ja fast das ganze Spiel, vllt könnte man das Spielfeld dann noch besser kapseln, mit einer getPlayer()-Methode die ein Spieler-Objekt zurückliefert und in dieser Methode überprüft wird ob der Spieler Schachmatt ist:
PHP:
public class Spielfeld {
  // ...
  public Player getPlayer(int player) {
    return new Player(player, this);
  }
}

public class  Player {
  // ...
  public Player(int player, Spielfeld s){
    // ...
  }

  public boolean isSchachmatt() {
    // nutzt das Spielfeld-Objekt ;)
  }
}

- Listener klasse:
die eventverarbeitung halt
ja, aber als Denkanstoß, auch das Spielfeld könnte Listener implementieren ;)
Man muss ja nicht dauerhaft überprüfen ob ein Spieler schachmatt ist, wenn jemand einen Zug macht, könnte das Spielfeld das ja selbst einmal pro Zug prüfen und bei Bedarf den Schachmacht-Listener triggern ;)

an sich ist die einteilung denke ich nicht ganz verkehrt..
ihr solltet auch da auf jedenfall viel Mühe geben.
Bei unseren letzten Uni-Projekt habe ich den Klassen-Aufbau über 4 Tage geplant, danach musste nur noch stupide implementiert wurden, der Großteil der anderen Gruppen musste danach nochmal einiges umwerfen oder musste an hunderten Stellen noch tausende Methoden einfügen.

das problem, das ich sehe ist allerdings, dass das mit dem array, in dem gespeichert wird, auf welchem feld welche figur ist, schwierig werden würde, da die objekte der spielfiguren ja alle von nem anderen typ sind.. sonst könnte man den array einfach vom typ figur erzeugen..
verfolg doch mal meinen Ansatz oben von der abstrakten Spielfigur ;)
 
also keine ki oder der gleichen..
Schade :( ... den interessanten Teil weglassen :biggrin:

Die Figur auf alle Fälle - wie schon angesprochen - abstract machen und die konkreten Figuren dann davon ableiten. Somit kannst du das Spielbrett mit Figuren füllen und diese alle einheitlich ansprechen.
Die konkrete Implementierung von moveAllowed() wird sich dann schon wehren, wenn du z.B. versuchst, mit dem Springer nur ein Feld vorwärts zu gehen.

Frage is, ob - wie ice-breaker vorschlägt - das Spielfeld alles erledigt, oder - alternativ eine Klasse einführen, die das Spielbrett erzeugt und die Spiellogik abwickelt, also dass einer nach dem anderen zieht, Schachmatt prüft und ggf. das Spiel beendet.
Bildlich vorgestellt wäre die Frage, ob du ein Holzbrett als Spielfeld hast oder einen Schachcomputer, wo du nur noch die Figuren draufstellen musst.

Zum Thema Schach-setzen:
Bei einem "dummen" Spielbrett könnte checkInChess() normale Methode sein, die ausgehend von ihren Figuren prüft, ob der König im Schach steht.
Übernimmt das Spielbrett die Spiellogik, müsste die Methode statisch sein, um ein anderes Spielbrett mit veränderten Figuren auf die Schach-Situation zu prüfen.
Grund: Es ist notwendig, Schach einen Zug in die Zukunft gesehen festzustellen, um ungültige Züge auszuschließen. Es könnte ja z.B. ein Turm einen bestimmten Zug nicht ausführen dürfen, weil er sonst eine Linie gegnerische Dame -> eigner König öffnet.

Alternativ erledigt das eine Teilmethode von moveAllowed() moveOpensChessSituation(). Is aber sicherlich aufwändiger zu implementieren.
 
wow! vielen dank für die schnelle und ausführlichen antworten!

ich hatte mir schon überlegt, ob ich die figuren klasse abstrakt machen soll.. den gedanken hab ich dann aber verworfen, weil ich fälschlicherweise angenommen habe, dass in einer abstrakten klasse nur abstrakte methoden stehen können.. nachdem ich den irrtum nach einem blick in mein java buch beseitigt habe ist die klasse jetzt abstrakt.. so richtige objektorientierung ist schon was feines :D

was IceBreaker mit den getPlayer() sachen gemeint hat hab ich allerdings nicht so ganz verstanden :/

ansonsten müsste es denke ich schon passen, wenn man nur eine Spielfeld klasse hat.. es sollen wirklich nur die grundfunktionen abgedeckt werden.. deswegen wird das wohl nicht zu groß werden..

@theHacker:
eine "naive" checkInChess() methode ist für unsere zwecke wohl vollkommen ausreichend.. der rest wäre wohl zu komplex.. eventuell mach ich mich da dann mal selber dran, wenn ich später mal zeit und lust habe, aber für das projekt an sich wäre das wohl zu viel des guten..
mein ansatz war es, nach jedem zug neu zu ermitteln, welche figur wohin gehen kann.. daraus mach ich dann für jeden spieler nen vektor, mit den feldern, die er insgesamt erreichen kann.. und wenn der gegnerische könig in jedem fall auf einem dieser felder steht, dann ist man logischerweise schach matt.. gleichzeitig würde ich auch auf normales schach prüfen..

mensch.. mir brennt es schon voll unter den fingern.. würde am liebsten jetzt anfangen zu coden, aber die anderen in meiner gruppe müssen erst noch die gui machen, sonst ist das nid das wahre, wenn man kein "richtiges" ergebnis sieht :D ich würde die gui ja selber machen, aber die müssen halt auch was machen, sonst bekommen se den schein nid

edit:
achja.. das schachbrett wollte ich natürlich in einem grid layout machen.. aber wie mach ich es am besten, dass ich bei nem klick jedes einzelne feld eindeutig referenzieren kann? ich wüsste nur, wie ich es mit buttons machen würde, aber das sieht dann halt extrem bescheiden aus.. mir reichts, wenn ihr mir nen schlagwort nennt, dann les ich es selber nach..
 
Zuletzt bearbeitet:
Also ich wuerde es so machen dass jede Figur Klasse seine eigenen Bewegungsmoeglichkeiten kennt (Liste mit relativen koordinaten des Ziels) und dann kann man die eigentlichen instanzen abfragen welche Felder im konkreten Zug moeglich sind, dann kannst du diese Zuege Vorschlagen (highlight) und es wird ultra simpel ein schach zu erkennen (foreach figur foreach move check is enemy king).
 
Also ich wuerde es so machen dass jede Figur Klasse seine eigenen Bewegungsmoeglichkeiten kennt (Liste mit relativen koordinaten des Ziels) und dann kann man die eigentlichen instanzen abfragen welche Felder im konkreten Zug moeglich sind, dann kannst du diese Zuege Vorschlagen (highlight) und es wird ultra simpel ein schach zu erkennen (foreach figur foreach move check is enemy king).

ziemlich genau so hab ich geplant.. in der figur klasse steht der methoden kopf der abstrakten klasse public abstract int[] possibleMoves().. diese wird dann von den jeweiligen unterklassen mit inhalt gefüllt.. hier wird dann eben mit schleifen (bei dame, läufer, turm) überprüft, bis wohin die figur gehen kann, oder eben die einzelnen felder, die theoretisch begehbar sind überprüft (beim bauer sind es ja maximal 3, bei könig und springer jeweils maximal 4).. das mit dem highlight war auch fest eingeplant!

hat jemand noch nen vorschlag, wie man bei klicks am besten auf die einzelnen felder referenzieren kann? hatte es im vorrigen post genauer erklärt, was ich damit meine
 
Wird dann eigentlich an einer GUI gespielt oder soll das Spiel netzwerkfähig sein?
 
Spiellogik in eine Klasse kapseln und dann die GUI actions auf die funktionen in der logik mappen, dann is es auch ned schwer das per netzwerk zu machen, ob ein event vom GUI kommt oder vom netzwerk wird einfach abstrahiert ^^
 
*rauskram*

das was snyke schreibt war mir als absolutem java neuling irgendwie zu hoch :D

ich habe jetzt eine recht einfache gui erstellt.. das schachbrett ist ein grid layout und die einzelnen felder sind jeweils JLabels mit der entsprechenden hintergrundfarbe (schwarz/weiß) und dem icon der figuren (sofern vorhanden..)

ich habe die JLabels bei einem MouseListener registriert.. mein problem ist jetzt, herauszufinden, welches label geklickt wurde.. spiele jetzt schon seit einiger zeit mit den einzelnen methoden rum und im netz hab ich auch nix hilfreiches gefunden..

ich habe nur die lösung gefunden, den labels mit setName(); einen namen im stil von 1_4 (sind dann die koordinaten).. wenn ich dann getSource(); auf den MouseEvent anwende, und das ausgeben lasse bekomme ich eine ausgabe wie diese:
javax.swing.JLabel[1_4,375,285,75x57,alignmentX=0.0,alignmentY=0.0,border=, usw ... ]

hier stehen jetzt an erster stelle die koordinaten.. mit diesen könnte man dann weiter arbeiten.. aber irgendwie kommt mir diese lösung eher suboptimal vor.. hat jemand einen besseren ansatz?
 
Die richtige Lösung is mal wieder Ableiten ;)

Leite JLabel ab. Das neue JChessLabel kriegt im Konstruktor zusätzlich die Koordinaten. Dann hast du sie, wenn das Event eintritt.
 
Zuletzt bearbeitet:
ah.. an so ne lösung hatte ich gar nicht gedacht..

ich habe ne klasse JChessLabel erstellt, die die klasse JLabel erweitert.. (so hatte ich dich zumindest verstanden ;) ) und die beiden attribute xCoor und yCoor eingefügt, die im konstruktor gesetzt werden und die erzeugung der labels dementsprechend angepasst..

ich weiß jetzt aber nicht, wie ich in meiner MouseClicked darauf zugreifen kann.. ich habe es mit e.getSource().xCoor versucht, allerdings bekomme ich da nen fehler..

ich hab dich wohl falsch verstanden oder irgendwo nen denkfehler ;)
 
ich habe es mit e.getSource().xCoor versucht, allerdings bekomme ich da nen fehler..
Perfekt das Problem geschildert :roll:

Aber ich weiß zum Glück auch so, dass nur der Getter fehlt und der Fehler ein "cannot access private member" is. Die Eigenschaften sind (sollten!) private, d.h. du kannst nicht so einfach draufzugreifen. Drum n öffentlichen Getter für die Variablen machen und fertig.
 
Perfekt das Problem geschildert :roll:

sorry.. aber du hast recht.. ich sollte es mittlerweile besser wissen ;)

ich komm irgendwie nich dahinter.. habe jetzt so ziemlich alles probiert, was mir eingefallen ist..

JChessLabel label = e.getSource();
-> liefert mir: Type mismatch: cannot convert from Object to JChessLabel

int[] coors = e.getSource().getCoors;
-> liefert mir: The method getCoors() is undefined for the type Object
der kopf der getCoors sieht folgendermaßen aus:
public int[] getCoors()

also dachte ich mir, dass irgendwie mit dem objekt, das getSource() liefert irgendwas nicht stimmt..
e.getSource() instanceof JChessLabel liefert mir allerdings true.. :-?
 
Mach einen expliziten Cast auf die gewünschte Klasse. getSource() liefert nunmal Object und das kannst du nicht brauchen, weil es die gewünschten Methoden nicht hat.

Und Tipp: Schreib richtig, wenn du den Code mal warten willst. Oder was denkt sich einer, der "getCoors" liest? :LOL: getCoords() ;)
 
Mach einen expliziten Cast auf die gewünschte Klasse. getSource() liefert nunmal Object und das kannst du nicht brauchen, weil es die gewünschten Methoden nicht hat.


ah.. daran hatte ich nicht gedacht.. an sowas denkt man aber auch nicht, wenn man vom unsauberen php kommt :D

theHacker schrieb:
Und Tipp: Schreib richtig, wenn du den Code mal warten willst. Oder was denkt sich einer, der "getCoors" liest? :LOL: getCoords() ;)

alles klar, chef! :D

danke dir!

kann dich leider nicht bewerten.