# Schachspiel



## Xym13 (14. Sep 2012)

Hallo zusammen,

ich versuche gerade ein Schachspiel zu programmieren, habe allerdings noch Schwierigkeiten mit dem Aufbau der Klassen.

Ich hatte mir folgendes gedacht:
Erstmal gibt es eine Hauptklasse, wo das Spiel startet, das Spielfeld gezeichnet wird und die Züge gemacht werden.

Dann gibt es eine Klasse Figur, in der die X, Y Koordinten gespeichert sind.
Für jeden Figurentyp gibt es dann auch noch eine Klasse(Bauer, Läufer, usw) die alle von der Klasse Figur abgeleitet sind.
In den Figurentyp klassen sollen dann die Figuren gezeichnet werden und auch die Möglichen Züge angezeigt werden.

Alle Figuren wollte ich dann in der Hauptklasse in einem Array speichern:

```
Figuren [][] spielfeld = new Figuren[8][8];
```

1. Bin ich mir sicher, ob der Aufbau der Klassen so richtig ist.
2. Weiß ich auch nicht genau, wie ich dann über das Array spielfeld an die Methoden in den Figurentypenklassen komme und die X und Y Koordinate auslese bzw. ändere.


----------



## kaetzacoatl (14. Sep 2012)

```
if(spielfeld[x][y] != null && spielfeld[x][y].canMove(mouse.x,mouse.y))
spielfeld[mouse.x][mouse.y] = spielfeld[x][y];
```
So würd ich des machen.


----------



## Xym13 (14. Sep 2012)

Und wie soll ich dann unterscheiden, welche Figur bewegt werden soll?


----------



## Marco13 (14. Sep 2012)

Man könnte da mit einem Einzeiler antworten a la
spielfeld[x][y].machWas();
oder mehrere Seiten lang über Schach, Programmierung und Schachprogrammierung referieren - oder gleich sagen "Lies' dir http://chessprogramming.wikispaces.com durch und sag' bescheid, wenn du fertig bist  ). Eine genauere Eingrenzung der Frage könnte helfen.


----------



## kaetzacoatl (14. Sep 2012)

1. Du wartest, dass die Maus gedrückt wird
2. Du wartest, bis die Maus wieder gedrükt wird
3. Du kontrollierst, ob die ausgewählte Figur(1)
    auf das ausgewählte Feld(2) kann
4. Du setzt die Koordinaten der Figur neu


----------



## Firephoenix (14. Sep 2012)

Um mal eine Etage höher zu gehen:


> Erstmal gibt es eine Hauptklasse, wo das Spiel startet, das Spielfeld gezeichnet wird und die Züge gemacht werden.



Mach aus 3 Verantwortlichkeiten (starten, zeichnen, ziehen) möglichst 3 Klassen, sonst hast du irgendwann Nudelsalat bzw Spaghettiecode  zumindest falls noch mehr Anforderungen dazukommen sollten.

Für Abfragen ob eine bestimmte Figur auf ein Feld ziehen kann könnte man das Strategy-Pattern verwenden. Will man wissen ob eine Figur x auf ein Feld ziehen kann könnte man sich dann von Figur x die Strategy besorgen die das Bewegungsmuster beschreibt und die dann fragen ob ein Zug von x1,y1 auf x2,y2 erlaubt ist.
(Strategy pattern - Wikipedia, the free encyclopedia)

Solange bis das Model (die Logik) steht, könnte man die Ausgabe auch rein per Konsole machen, damit spart man sich anfangs viel zeichensalat und kann später entscheiden was man zum zeichnen verwendet (Awt, Swing, Slick2d, irgendwelches fancy-3d zeugs?).
Möglich zur Ausgabe wäre z.B. eine Schachnotation:
Schachnotation ? Wikipedia

Gruß


----------



## Xym13 (14. Sep 2012)

Schonmal vielen Dank bis hierhin! Sind echt hilfreiche Links.

Mein Problem im Moment liegt bei den ganzen Klassen.

Wenn ich ein Array vom Typ Figuren habe, wie soll ich dann in den Klassen Bauern, Turm usw. die Variablen ändern oder Methoden aufrufen.

Denn hiermit:

```
spielfeld[x][y].move();
```

Wird ja eine Methode aus der Klasse Figuren aufgerufen, obwohl ich gerne in den Bauern, Turm usw. Klassen die Methoden schreiben will, weil ich dann genau weiß um welche Figur es sich handelt.

Ist das möglich? Oder muss ich dann in der Klasse Figuren zwischen den Figurtypen unterscheiden und dann entscheiden, wohin die Figur geht?


----------



## nillehammer (14. Sep 2012)

Kurze Antwort. Dein Dilemma entsteht, weil Du Informationen unglücklich einsortiert hast. Deswegen meine etwas längliche Antwort auf Deine sehr wichtige erste Frage:


> 1. Bin ich mir sicher, ob der Aufbau der Klassen so richtig ist.


Ich glaube, er ist etwas unglücklich. Der Charme der Objektorientierung ist, dass man (nicht immer, aber oft) Beobachtungen der realen Welt fast eins zu eins auf Code mappen kann. Was gibt es also in einem realen Schachspiel?
- Ein Schachbrett
- Auf diesem Schachbrett Spielfelder
- Auf diesen Spielfeldern Figuren
- Von diesen Figuren spezielle Ausprägungen (Bauer, Turm, Dame etc.)
Nimm diese Begriffe, dann hast Du bereits Deine Klassen. In der Richtung hast Du ja schon angefangen, aber evtl. nicht ganz richtig.

Jetzt geht's weiter. Du hast Deine Klassen(-Rümpfe), aber die sind noch leer. Was für Eigenschaften sollen Deine Klassen haben? Und was möchtest Du mit Instanzen dieser Klassen tun? Das sind dann zwar schon Programmtechnische Fragen, die sich aber aus der realen Welt beantworten lassen:

Ein Schachbrett hat 8x8 Spielfelder. Wie bildet man das am besten ab? Hier evtl. zweidimensionaler Array von Spielfeldern als Instanzvariable von Schachbrett.

Auf einem Spielfeld kann eine Figur stehen, also am besten eine Instanzvariable des Typs Figur.

Eine Figur hat eine Farbe (schwarz oder weiß)

Die Frage, welche Eigenschaft wohin, kann schon etwas schwieriger sein. Du hast Dich bspw. entschieden, dass eine Figur eine x und eine y-Koordinate haben soll. Kann man so machen. Aber ich denke genau andersrum, dass ein Spielfeld wissen muss, ob auf ihm eine Figur steht oder nicht. Die Figur braucht diese Information garnicht. Diese Änderung dürfte es Dir schon leichter machen.

Und zur Frage nach dem move(). Es wäre denkbar, die move-Methode in der Klasse Figur (abstrakt) zu definieren und in den Subklassen Bauer, Dame etc. ensprechend zu überschreiben. Ich glaube aber, dass die Methode move() bei der Figur schlecht aufgehoben ist. Wenn Du mal darüber nachdenkst, was alles an Informationen benötigt wird, um zu ermitteln, wo eine Figur überall hin bewegt werden kann, dann wirst Du feststelen, dass einzig das Schachbrett über alle diese Informationen verfügt.


----------



## Marco13 (14. Sep 2012)

nillehammer hat gesagt.:


> Wenn Du mal darüber nachdenkst, was alles an Informationen benötigt wird, um zu ermitteln, wo eine Figur überall hin bewegt werden kann, dann wirst Du feststelen, dass einzig das Schachbrett über alle diese Informationen verfügt.



Das würde ich so unterschreiben. Eine Figur alleine kann das nicht wissen (außer "indirekt", indem sie DOCH wieder auf das Brett bzw. Felder zugreifen kann - das kann man machen, aber ich wüßte kaum, was es hier nützen sollte).

Das Brett alleine reicht aber auch nicht, man braucht noch ein paar mehr Informationen. Ganz pragmatisch (auch wenn man's leicht vergessen könnte) wären die en passant und Rochadenzüge. 

Es ist aber viel elementarer: Um rauszufinden, ob ein Zug gültig ist (egal, welche Figur wo hin) muss man auf jeden Fall prüfen, ob NACH dem Zug der eigene König im Schach stehen würde. Dazu müssen alle möglichen Züge übrprüft werden, die der Gegner NACH dem eigenen Zug machen könnte. Kurz: Die Berechnung der gültigen Züge und der ganzen Regeln ist so kompliziert und alles hängt so sehr zusammen, dass man da für bestimmte Dinge nicht unbedingt die Objektorientierungs-Keule auspacken sollte. 

Selbst das mit den abstrakten Basisklasse "Figur" und den konkreten Ausprägungen verliert ein bißchen an Reiz, wenn man sich überlegt, wie gering der Nutzen ist ... und die Wahrscheinlichkeit, dass später noch weiter Figuren-Arten dazukommen  

Aber es würde natürlich vieles "intuitiver" und und ggf. auch einfacher machen, deswegen kann man für das, was man ohnehin machen muss natürlich bis zu einem gewissen Grad pragmatische Objektorientierung verwenden (solange man keine Engine schreiben will - da ginge es dann nur noch um effizientestes bit-Gefrickel). 

Eine Möglichkeit wäre also sowas wie

```
class Engine
{
    private Board board;

    public List<Move> getAllPossibleMoves(Piece piece) { .. }
}
```
mit den oben angedeuteten Ausschmückungen, wo aber schon an einer ziemlich "mächtigen" Stelle alle Regeln und Zustände zusammenlaufen.


----------



## nillehammer (17. Sep 2012)

Richtig, an einzuhaltende Post-Conditions (eigener König darf nach Zug nicht im Schach sein), sowie kompliziertere Züge (En passant, Rochade) hatte ich garnicht gedacht. Nicht nur deswegen drängt sich eine extra Entscheidungsinstanz auf. Man sollte die Datenhaltungsklassen (wie z.B. Schachbrett) grundsätzlich nicht mit Logik überfrachten.


----------

