# Dame



## Private Void (12. Sep 2010)

Ich bin bei einem meiner Vorhaben in Java (mal wieder) an einem Punkt angekommen, an dem mir einfach nichtr einfallen will, wie ich es umsetzen könnte.

Bei dem Brettspiel Dame besteht ja so eine Art "Schlagzwang". Bevor der Spieler einen Zug machen kann, muss also überprüft werden, ob er einen gegnerischen Stein überspringen kann, was er dann auch muss.
Hinzu kommt die Möglichkeit mehrer "Schmisse" in einem einzigen Zug.

Im Moment hab ich nur so überhaupt keinen Plan, wie ich das angehen soll.

Ich zeig am besten mal, wie weit ich "schon" bin.
Ich hoffe, ihr könnt mir meine oftmals evtl. etwas merkwürdige Namensgebung verzeihen ... und meine vielleicht etwas chaotische Art zu programmieren .

PS.: Die Farbwahl könnte ich evtl. ja auch nochmal überdenken.


```
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Hauptfenster extends JFrame{
    public static Hauptfenster frame;
    
    private JPanel contentPane = (JPanel) getContentPane();
    
    public Hauptfenster(){
        contentPane.setLayout(new BorderLayout());
        contentPane.add(new Spielbrett(), BorderLayout.CENTER);
        
        // ... etc.
    }
    
    public static void main(String[] args) {
        frame = new Hauptfenster();
        frame.setTitle("Dame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(800,800));
        frame.setVisible(true);
    }
}
```


```
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;

public class Spielbrett extends JPanel{
    private Feld[][] felder=new Feld[8][8];
    private int stein,xwert,ywert;
    private boolean amZug=true; // true: unterer Spieler am Zug - false: oberer Spieler am Zug
    
    public Spielbrett(){
        setLayout(new GridLayout(8,8));
        
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if((i+j)%2==1){
                    int a;
                    if(i<=2){
                        a=2;
                    }else if(i>=5){
                        a=1;
                    }else{
                        a=0;
                    }
                    felder[j][i]=new Feld(true,a);

                    final int x = j;
                    final int y = i;
                    
                    felder[j][i].addMouseListener(new MouseListener() {
                        
                        public void mouseReleased(MouseEvent e) {}
                        public void mousePressed(MouseEvent e) {}
                        public void mouseExited(MouseEvent e) {}
                        public void mouseEntered(MouseEvent e) {}
                        
                        public void mouseClicked(MouseEvent e) {
                            if(felder[x][y].getStein()==1 && amZug){
                                if(y-1>=0){
                                    demarkieren();
                                    if(x+1<8 && felder[x+1][y-1].getStein()==0){
                                        felder[x+1][y-1].setMarkiert(true);
                                    }
                                    if(x-1>=0 && felder[x-1][y-1].getStein()==0){
                                        felder[x-1][y-1].setMarkiert(true);
                                    }
                                    stein=1;
                                    xwert=x;
                                    ywert=y;
                                }
                            }else if(felder[x][y].getStein()==2 && !amZug){
                                if(y+1<8){
                                    demarkieren();
                                    if(x+1<8 && felder[x+1][y+1].getStein()==0){
                                        felder[x+1][y+1].setMarkiert(true);
                                    }
                                    if(x-1>=0 && felder[x-1][y+1].getStein()==0){
                                        felder[x-1][y+1].setMarkiert(true);
                                    }
                                    stein=2;
                                    xwert=x;
                                    ywert=y;
                                }
                            }else if(felder[x][y].getMarkiert()){
                                felder[x][y].setStein(stein);
                                felder[xwert][ywert].setStein(0);
                                demarkieren();
                                amZug=(amZug ? false:true);
                            }
                        }
                    });
                }else{
                    felder[j][i]=new Feld(false,0);
                }
                add(felder[j][i]);
            }
        }
    }

    /**            
     * Wahrscheinlich nicht die eleganteste Möglichkeit,
     * die Markierung zweier Felder aufzuheben!
     * Holzhammermethode eben ;)
     */
    private void demarkieren(){
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if(felder[i][j].getMarkiert()){
                    felder[i][j].setMarkiert(false);
                }
            }
        }
    }
}
```


```
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;

public class Feld extends JComponent{
    private boolean schwarz, markiert;
    private int stein;
    
    public Feld(boolean schwarz, int stein){
        this.schwarz=schwarz;
        this.stein=stein;
    }
    
    public void paint (Graphics g){
        Rectangle2D.Float rechteck = new Rectangle2D.Float(0,0,getWidth(),getHeight());

        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke((markiert ? 10:1)));
        if(schwarz){
            g2.setPaint(new Color(140,140,200));
        }else{
            g2.setPaint(new Color(200, 200, 220));    
        }
        g2.fill(rechteck);
        if(markiert) g2.setPaint(Color.BLACK);
        g2.draw(rechteck);
        
        if(stein!=0){
            Ellipse2D.Float kreis = new Ellipse2D.Float(getWidth()/10, getHeight()/10,
                    getWidth()*4/5, getHeight()*4/5);
            switch(stein){
                case 1:
                    g2.setPaint(new Color(60,60,60));
                    break;
                case 2:
                    g2.setPaint(new Color(210, 210, 210));
                    break;
            }
            g2.fill(kreis);
            g2.draw(kreis);
        }
    }
    
    public int getStein(){
        return stein;
    }
    
    public void setStein(int stein){
        this.stein=stein;
        repaint();
    }
    
    public boolean getMarkiert(){
        return markiert;
    }
    
    public void setMarkiert(boolean markieren){
        markiert=markieren;
        repaint();
    }
}
```


----------



## XHelp (12. Sep 2010)

Ohne jetzt genau den Code zu studieren:
Du hast ja ein Array von deinen Feldern. Vor jedem eigenem Zug musst du überprüfen, ob du in Schlagzwang stehst. Da du ja nicht um die Ecke springen kannst ist die Anzahl an möglichen Variationen klein. Falls du im Zugzwang bist machst du den Zug und überprüfst es erneut


----------



## Private Void (12. Sep 2010)

Ich muss ja das komplette Brett abfragen, ob sich zwei gegnerische Steine gegenüberstehen und das Feld hinter dem zu schlagenden Stein frei ist. Nach dem Zug muss ich dann eben für diesen speziellen Stein nochmal schaun, ob das wieder der Fall ist.

... ???:L

Etwa so:

```
for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
        if((amZug && felder[i][j].getStein()==1 &&
           j>1 && ((i>1 && felder[i-1][j-1].getStein()==2 && felder[i-2][j-2].getStein()==0) || 
                   (i<6 && felder[i+1][j-1].getStein()==2 && felder[i+2][j-2].getStein()==0)))
           ||
           (!amZug && felder[i][j].getStein()==2 &&
           j<6 && ((i>1 && felder[i-1][j+1].getStein()==1 && felder[i-2][j+2].getStein()==0) || 
                   (i<6 && felder[i+1][j+1].getStein()==1 && felder[i+2][j+2].getStein()==0))))
        {
            felder[i][j].setMarkiert(true);
        }
    }
}
```

Dann müsste ich doch noch einen boole'schen Marker einführen und ihn auf true setzen, wenn so ein Fall eintritt.
Beim Auswählen des Steins, den ich spielen will, muss ich in der Abrage noch hinzufügen, ob dieser Marker gesetzt ist und das Feld entsprechend markiert.

Die Koordinaten von dem Feld, auf dem der gegnerische Stein verschwindet, muss ich dann auch noch irgendwie unterbringen, und dass für den speziellen Stein nochmal kontrolliert wird, ob er einen weiteren Gegner überspringen kann.


----------



## Marco13 (12. Sep 2010)

Auch "_Ohne jetzt genau den Code zu studieren:_"

Wie groß willst du das denn aufziehen? Sowas wie Model-View-Controller würde sich vielleicht anbieten. Spätestens wenn du noch einen Computergegner (sprich eine KI) einbauen willst, wird das ziemlich murksig, wenn alles im GUI gemacht wird. 
Also auch wenn das vielleicht deine Konkrete Frage nicht beantwortet: Du könntest versuchen, ein paar Klassen und Interfaces zu machen 

```
interface Checkers { ... }
interface Player { ... }
interface Move { ... }
[/Java]
und insbesondere Letzteres könnte man verwenden, um eine Methode zu machen wie
[code=Java]
List<Move> getAllPossibleMoves() { ... }
```

Auf Basis dieser Liste dann im GUI irgendwelche Felder zu markieren wäre der zweite Schritt.
Nur ein Tipp, ganz unverbindlich.


----------



## XHelp (12. Sep 2010)

Was bewirkt dein Marker?
Ist lange her, wo ich Dame gespielt habe, aber kann es nicht passieren, dass man zwar im Schlagzwang ist, aber dennoch mehrere Möglichkeiten hat?
Nimmt dir den Rat von Marco zu Herzen, denn früher oder später wirst du Schwierigkeiten bekommen.


----------



## Private Void (12. Sep 2010)

Nach deinem Post, Marco, glaub ich so langsam, dass mir erstmal jemand beibringen muss, wie man grundsätzlich an die Programmierung von Spielen (oder auch allgemein von größerer und komplexerer Software) herangeht.

Denn scheints steckt da viel mehr dahinter als ich mir bisher immer vorgestellt hab.


----------



## Marco13 (12. Sep 2010)

Dazu kannst du dich mal bei diesem Benutzer melden, der kann dir das beibringen :joke:

Das ist nichts, was man auf einer halben Textseite zusammenfassend erklären kann, und was man dann "kann". Man lernt immer mehr dazu. Aber es gibt sicher einführende Tutorials zu OOP allgemein, oder zu Model-View-Controller. (Das ist speziell für Spiele zwar nicht zwingend der beste Ansatz, aber allgemein sollte man darauf achten, die eigentliche Programmlogik (Model) von der Präsentation (View, das GUI) zu trennen, und das wird mit diesem Modell erreicht).

Als unverbindlichen, nicht-bootcamp-mäßigen Ansatz hatte ... ARadauer glaub' ich ... mal sowas geschrieben wie: "Schreibe detailliert auf, was für ein Programm du schreiben willst. Die Substantive sind die Klassen. Die Verben sind die Methoden. Die Adjektive sind die Variablen."

Tatsächlich sollte man sich erst überlegen, woraus das Spiel besteht, und was man alles machen können will. Es hat (während der Planung, und auch später bei der Enwicklung) viele Vorteile, das ganze in Form von Interfaces zu beschreiben, weil die _genau das_ sind: Eine Definition, woraus das Spiel besteht (die Klassen bzw. Interfaces an sich) und was sie machen können (die Methoden). Wie "puristisch" man dabei vorgeht bleibt einem selbst überlassen. Wenn es um Autodidaktisches "Rumspielen" geht (nicht negativ gemeint) kann man auch gleich was mit Swing machen, wenn einen die Tatsache, dass man gleich etwas auf dem Bildschirm sieht, mehr motiviert als ein schönes UML-Diagramm


----------



## pl4gu33 (13. Sep 2010)

Private Void hat gesagt.:


> Nach deinem Post, Marco, glaub ich so langsam, dass mir erstmal jemand beibringen muss, wie man grundsätzlich an die Programmierung von Spielen (oder auch allgemein von größerer und komplexerer Software) herangeht.
> 
> Denn scheints steckt da viel mehr dahinter als ich mir bisher immer vorgestellt hab.



also ich Programmier auch öfters mal kleine Spiele etc. ich muss sagen wir mussten sowas auch im Studium schon über ein Semester z.b. hinweg mit mehreren Leuten Planen etc. klar, wenn man ein kleinen Spiel programmieren will ist das nicht die Welt und man versucht öfters mal drauf loszuprogrammieren,... aber im Endeffekt wär man mit nen bisschen Planung besser beraten,... man muss ja nicht für jede Sache Diagramme malen und Use Cases schreiben, aber allein schon sollte man wissen, was man will und was man beachten muss, welche Komplikationen auftreten können, etc.

die meisten meiner Programme/Spiele egal wie klein sie auch sind, versuche ich in 3 Schichten/Packages meistens eher 2 zu unterteilen 
also GUI, Applikation und Persistenz,... wobei die Persistenz nicht wirklich immer gebraucht wird. Dabei arbeite ich so, dass ich Daten vom GUI zur App- Schicht und von der App zur Persistenz gebe,... am Besten wär natürlich ein Interface dafür, dieses berücksichtige ich aber auch mal öfters net 

Weiterhin arbeite ich von der App- Schicht zur GUI mit Observern, wo ich dann schon nen kleinen "Bruch" mache, da ich mir dann die Daten, die angezeigt werden sollen im GUI mit Getter von der App- Schicht hole,... 

Die ganze Spiellogik,Daten versuche ich in der App- Schicht unter zu bringen, die GUI Schicht ist für die Anzeige und die Persistenzschicht um Daten irgendwo abzuspeichern,.... parallel dazu verwende ich eine Fabrikklasse, welche die ganzen Klassen erzeugt und miteinander bekannt macht z.b. für Observer etc. und eine Controllerklasse, die die Daten von den GUIs zur App schickt, diese Schnittstelle sollte sehr klein / austauschbar sein. Je nachdem wenn man z.b. nur eine Instanz haben will benutz ich auch gern Singleton.... 

ich hoffe ich hab dir etwas geholfen, ich bin da auch noch kein Fachmann drin eher Fortgeschritten, ich hab gut Ideen etc. bloss zweifel ich öfters an mir selbst, ob der Code von meinem Spiel jetzt eher gut oder schlecht ist,... ob man irgendwas besser machen kann etc.  und das aller wichtigste sind Kommentare


----------

