# Vier Gewinnt Spiel Programmiertipp



## ClassiCBond (25. Mai 2016)

Hallo liebe Forumgemeinde,

ich besuche im Moment in meinem 3.Semester meine erste Programmiervorlesung. Mir wurde das Projekt "VIER GEWINNT" zugeteilt, jedoch hänge ich schon seit geraumer Zeit an einem kleinen Problem hinsichtlich meines geschriebenen Vier Gewinnt Programms für Java (unter Eclipse).

Meine Aufgabe ist es ein Programm zu schreiben, dass das Spiel "Vier Gewinnt" verkörpert und darstellt. Das Grundprogramm steht, jedoch hänge ich an zwei Punkten und komme nicht weiter:

1) In meinem Vier Gewinnt Programm soll nach jedem Zug abgeprüft werden, ob vier "Steine" nebeneinander in der Tabelle sind. Ich muss sowohl horizontal, vertikal als auch diagonal abprüfen. Die Horizontale und Vertikale funktioniert mit meinem Programm (Zeile 146-158). Die Diagonale (Zeile 160-164) funktioniert mit dem derzeitigen Programm-Code nicht. Mir ist bewusst, dass ich für die Diagonal zwei Befehle brauche, da sowohl eine aufsteigend als auch eine absteigende Reihe abgeprüft werden soll. In meinem bisherigen Programm habe ich nur die aufsteigende Reihe, aber leider erkennt Java es noch nicht an. 
Meine Idee war, dass das Programm abprüft ob z.B. im Feld 1/1, 2/2, 3/3, 4/4 ein Stein liegt. Bin ich hier auf der richtigen Fährte?

2) Mein zweiter Hänger ist, dass wenn ein Spieler gewonnen hat, abgefragt werden soll, ob man das Spiel "Weiterspielen" oder "Beenden" will. Die Beenden-Variante funktioniert in meinem Code (Zeile 174). Unter "Weiterspielen" versteht mein Professor, dass das Spielfeld kommt geleert wird und quasi von Anfang an neu startet. Dies funktioniert leider noch nicht (Zeile 176-180). Leider ist mir aus der Vorlesung und nach der Suche im www kein Befehl bekannt, der das Programm komplett neu startet.

Ich hoffe, dass vielleicht jemand von euch mir weiterhelfen oder einen Tipp zur Lösung meiner Probleme geben kann! Ich würde mich darüber sehr freuen 

Gruß,
ClassiCBond

Hier ist der Auszug zu der Gewinnbedingung (Horizontal/Vertikal/Diagonal) und dem "Weiterspielen/Beenden": 


```
private static void Gewinnbedingung()
    {
          boolean a=false;
          int s;
          if (SpielerEins == true)
          {
              s=1;
          }
          else
          {
              s=2;
          }
         
          for(int i=0;i<=2;i++)                       <---------------- Horizontale
              for(int j=0;j<=6;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i+1] [j]==s && SpielFeld [i+2] [j] ==s && SpielFeld [i+3] [j] ==s)
              {a=true;}
              }
             
                 
        for(int i=0;i<=5;i++)                       <---------------- Vertikale
              for(int j=0;j<=3;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i] [j+1]==s && SpielFeld [i] [j+2] ==s && SpielFeld [i] [j+3] ==s)
              {a=true;}
              }
             
             
              for(int i=0;i<=2;i++)             <----HILFE  <-------------- Diagonal Aufsteigend
                  for(int j=0;j<=3;j++)
                  {if(SpielFeld [i] [j]==s && SpielFeld [i+1] [j+1]==s && SpielFeld [i+2] [j+2] ==s && SpielFeld [i+3] [j+3] ==s)
                  {a=true;}
                  }
             
              if (a==true)
              {
                  System.out.println ("Gewonnen hat Spieler " + s );
                  String EingabeEnde = Input.readString("Weiterspielen (0) oder Beenden (1)");
                  int Eingabe = Integer.parseInt(EingabeEnde) ;
                  if (Eingabe== 1)
                     
                  {
                    System.exit(0);
                  }
                  else if (Eingabe==0)
                  {

                    SpielFeldAusgeben();         <-----HILFE  <--------- Hier ist "Weiterspielen"
                  }
              }
    }
```



Hier das komplette Programm:

```
public class VIERGewinnt
{
    static int[][] SpielFeld = new int[6][7]; // 6 Zeilen, 7 Spalten
    static int Zeilen = SpielFeld.length;
    static int Spalten = 7;

    static int[] spalteFuellstand = new int[7];

    static boolean SpielerEins = true;

    static int Spalte = 0;
    static int ZeilenCounter;
    static int SpaltenCounter;


    private static void SpielFeldAusgeben()
    {
        // Ausgabe des Spielfelds
       


        System.out.println("|   |   |   |   |   |   |   |");
        System.out.println("| 1 | 2 | 3 | 4 | 5 | 6 | 7 |");
        System.out.println("|___|___|___|___|___|___|___|");

        for (  ZeilenCounter = 0; ZeilenCounter < Zeilen; ZeilenCounter++)
        {
            System.out.println("|   |   |   |   |   |   |   |");

            for ( SpaltenCounter = 0; SpaltenCounter < Spalten; SpaltenCounter++)
            {

                if (SpielFeld[ZeilenCounter][SpaltenCounter] == 0)
                {
                    System.out.print("| " + " " + " ");
                } // end of if

                else
               
                    if (SpielFeld[ZeilenCounter][SpaltenCounter] == 1)
                {
                    System.out.print("| " + "X" + " ");
                } // end of if-else

                else
                   
                    if (SpielFeld[ZeilenCounter][SpaltenCounter] == 2)
                {
                    System.out.print("| " + "O" + " ");
                } // end of if-else

            } // end of for

            System.out.print("|");
            System.out.println();
            System.out.println("|___|___|___|___|___|___|___|");
        } // end of for
   
        System.out.println();
    }
     // end of private static void SpielFeldAusgeben

    private static void Spielerwechsel()
    {
        // Spielerwechsel
        if (SpielerEins == true)
        {
            SpielerEins = false;
        } // end of if
        else
        {
            SpielerEins = true;
        } // end of if-else

    } // end of private static void Spielerwechsel

    private static void Spalteneingabe() {

        // Spalteneingabe durch Spieler eins oder zwei
        try{
        int Spieler;
        Spalte = 0;
        String EingabeA;
       
        if (SpielerEins == true)
        {
            EingabeA = Input.readString("Spieler 1: Bitte Spaltennummer angeben: ");
        } // end of if
        else
        {
            EingabeA = Input.readString("Spieler 2: Bitte Spaltennummer angeben: ");
        } // end of if-else

        // Prüfen der Eingabe auf einen Wert zwischen 1 und 7
        Spalte = Integer.parseInt(EingabeA);
        }catch(Exception ex)
        {
            //System.out.println("Bitte Zahl zwischen 1 und 7 eingeben");   
        }
       
        if (Spalte < 1 || Spalte > 7)
        {
            System.out.println();
            System.out.println("Achtung! Die eingegebene Spaltennummer muss zwischen 1 und 7 liegen!");
            Spalteneingabe();
        }
        else
           
            if (spalteFuellstand[Spalte - 1] > 5)
        {
            System.out.println("Spalte voll!!!!");
            Spalteneingabe();
        }
        else
        {
            spalteFuellstand[Spalte - 1]++;
        }
    }

    private static void Spielzug()
    {

        if (SpielerEins == true)
        {
            SpielFeld[6 - spalteFuellstand[Spalte - 1]][Spalte - 1] = 1;
        } // end of if
        else {
            SpielFeld[6 - spalteFuellstand[Spalte - 1]][Spalte - 1] = 2;
        } // end of if-else
    }// end of private static void Spielzug
   
    private static void Gewinnbedingung()
    {
          boolean a=false;
          int s;
          if (SpielerEins == true)
          {
              s=1;
          }
          else
          {
              s=2;
          }
         
          for(int i=0;i<=2;i++)
              for(int j=0;j<=6;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i+1] [j]==s && SpielFeld [i+2] [j] ==s && SpielFeld [i+3] [j] ==s)
              {a=true;}
              }
             
                 
        for(int i=0;i<=5;i++)
              for(int j=0;j<=3;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i] [j+1]==s && SpielFeld [i] [j+2] ==s && SpielFeld [i] [j+3] ==s)
              {a=true;}
              }
             
             
              for(int i=0;i<=2;i++)
                  for(int j=0;j<=3;j++)
                  {if(SpielFeld [i] [j]==s && SpielFeld [i+1] [j+1]==s && SpielFeld [i+2] [j+2] ==s && SpielFeld [i+3] [j+3] ==s)
                  {a=true;}
                  }
             
              if (a==true)
              {
                  System.out.println ("Gewonnen hat Spieler " + s );
                  String EingabeEnde = Input.readString("Weiterspielen (0) oder Beenden (1)");
                  int Eingabe = Integer.parseInt(EingabeEnde) ;
                  if (Eingabe== 1)
                     
                  {
                    System.exit(0);
                  }
                  else if (Eingabe==0)
                  {

                    SpielFeldAusgeben();
                  }
              }
    }
   
    public static void main(String[] args)
    {
        while (true)
        {
            Spalteneingabe();
            Spielzug();
            SpielFeldAusgeben();
            Gewinnbedingung();
            Spielerwechsel();

        }
    }
}
```


----------



## Jardcore (25. Mai 2016)

Jardcore hat gesagt.:


> Du prüfst einfach bei jedem Zug wie weit du von einer 3er Reihe weg bist. Und wenn dein Zähler == 3 ist hast du gewonnen.


Ich zitiere mich mal selber  Hier ein Auszug aus einer Ähnlichen Frage zu der Gewinnbedingung bei XXO
Du musst nicht bei jedem Zug alles Prüfen, du musst bei einem Zug nur prüfen was in direkter Umgebung ist. Das heißt du hast maximal eine doppelte Schleife die 9 Felder prüft.


----------



## ClassiCBond (25. Mai 2016)

Vielen Dank Jardcore für deine schnelle Antwort
Ich muss leider sagen, ich versteh nicht ganz was du meinst und bin wohl noch zu unerfahren, was das Umsetzen von Programmen angeht.

In meiner Diagonal-Abprüfung habe ich es mir so überlegt, dass er z.B. am Feld [0][0] anfängt und dann [1][1] -> [2][2] -> [3][3] anschaut, ob dort von demselben Spieler schon etwas liegt. Die Vorgehensweise habe ich bei der Horizontalen und Vertikalen auch verwendet, nur dass er eben dort entweder nur die Zeile oder Spalte entlang geht und nicht Zeile und Spalte erhöht.
Gibt es vielleicht eine Möglichkeit mit dieser Idee das Diagonale-Abprüfen fortzusetzen?
Bzw. kannst du/jemand anders mir sagen, warum das so (noch) nicht funktioniert?


----------



## Jardcore (26. Mai 2016)

Was haben die beiden Felder [ A ][ B ] denn gemeinsam? Ja genau, sie sind gleich, das heißt du kannst auch einfach nur eine Schleife benutzten. Hier mal in deinem Programmierstil:

```
for(int i=0; i<=2; i++) {
    if(SpielFeld[i][i]==s && SpielFeld[i+1][i+1]==s && SpielFeld[i+2][i+2] ==s && SpielFeld[i+3][i+3] ==s) {
        a=true;
    }
}
```

Zum Stil:
In Java werden Variablen in CamelCase geschrieben, also spielFeld. Grundsätzlich sollte man Magic Number vermeiden.
Variablen sollten darüber hinaus eindeutige Namen haben.
Was ist "a" was ist "s", das sieht man auf den ersten Blick nicht.
Außerdem ist Java objektorientiert. Das heißt du hättest auch eine Spieler Klasse erstellen können und dieser Attribute verpassen können, z.B. ein Token, was in deinem Fall aktuell ein int darstellt.
Um CodeCopy oder unleserliche If-Bedinungen zu vermeiden kannst du auch zusätzliche Methoden einführen.

```
private boolean checkWinner(Player player) {
    int fieldSize = 2;
    for(int i = 0; i <= fieldSize; i++) {
        if(spielFeld[i][i] == player.getToken() &&
           spielFeld[i+1][i+1] == player.getToken() &&
           spielFeld[i+2][i+2] == player.getToken() &&
           spielFeld[i+3][i+3] == player.getToken()) {
           return true;
        }
    }
    return false;
}
```


```
public class Player {
    private int token;
    public Player(int token){
        this.token = token;
    }

    public int getToken() {
        return this.token;
    }
}
```


----------



## ClassiCBond (26. Mai 2016)

Danke erneut für deine Hilfe!

Ich habe deinen Programmcode anstelle meines eingefügt, doch leider ignoriert Java immer noch diese Gewinnbedingung (egal wo ich diagonal starte).
Dein Vorschlag, dass [i ] und [j] in diesem Fall übereinstimmen hast du recht. Was wäre aber im Fall, dass der Start "Stein" in [2] [1] liegt? Nun wären [i ] und [j] nicht mehr identisch.
Im Moment stehe ich leider immer noch auf dem Schlauch...

Nach diesem Spielzug sollte Java eigentlich die Diagonale erkennen.

```
Spieler 1: Bitte Spaltennummer angeben: 5

|_1_|_2_|_3_|_4_|_5_|_6_|_7_|
|___|___|___|___|___|___|___|
|___|___|___|___|___|___|___|
|___|___|___|___|_X_|___|___|
|___|___|___|_X_|_O_|___|___|
|___|___|_X_|_X_|_O_|___|___|
|___|_X_|_O_|_O_|_O_|___|_X_|

Spieler 2: Bitte Spaltennummer angeben:
```

Hier erkennt Java z.B. die Horizontale-Gewinnbedingung:


```
Spieler 1: Bitte Spaltennummer angeben: 4
|_1_|_2_|_3_|_4_|_5_|_6_|_7_|
|___|___|___|___|___|___|___|
|___|___|___|___|___|___|___|
|___|___|___|___|___|___|___|
|___|___|___|___|___|___|___|
|_O_|_O_|_O_|___|___|___|___|
|_X_|_X_|_X_|_X_|___|___|___|

Gewonnen hat Spieler 1
Weiterspielen (0) oder Beenden (1)
```

Hier die abgeänderte Variante mit deinem Vorschlag:


```
private static void Gewinnbedingung()
    {
          boolean a=false;
          int s;
          if (SpielerEins == true)
          {
              s=1;
          }
          else
          {
              s=2;
          }
       
          for(int i=0;i<=2;i++)                 //Horizontale Gewinnbedingung
              for(int j=0;j<=6;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i+1] [j]==s && SpielFeld [i+2] [j] ==s && SpielFeld [i+3] [j] ==s)
              {a=true;}
              }
           
               
        for(int i=0;i<=5;i++)                   //Vertikale Gewinnbedingung
              for(int j=0;j<=3;j++)
              {if(SpielFeld [i] [j]==s && SpielFeld [i] [j+1]==s && SpielFeld [i] [j+2] ==s && SpielFeld [i] [j+3] ==s)
              {a=true;}
              }
           
           
        for(int i=0; i<=2; i++)       //<------Diagonal
        {
            if(SpielFeld [i] [i]==s && SpielFeld [i+1] [i+1]==s && SpielFeld [i+2] [i+2] ==s && SpielFeld [i+3] [i+3] ==s) {
                a=true;
            }
     
        }
```


Und bzgl. dem Stil, muss ich leider sagen, dass mir diese Begriffe/Variante gar nichts sagen/sagt. Wir programmieren erst seit einem Monat mit Java und sind noch nicht tief genug eingedrungen bzw. wurde es uns noch nicht so weit eingeführt. Sorry also, dass ich damit nichts anfangen kann.


----------



## ClassiCBond (29. Mai 2016)

Hat vielleicht noch jemand einen anderen Tipp oder Lösungsvorschlag zur Lösung des Problems mit der Diagonalen oder muss Jardcores Antwort die korrekte Lösung für meinen Programmcode sein?!
Ich habe die Antwort von Jardcore schon oft ausprobiert, auch mit veränderten Bedingung, aber leider hat noch keine Idee oder Abänderung des Programms/der Methode zum Erfolg geführt  Falls jemand noch eine Idee hat, wäre ich sehr dankbar darüber.


----------



## Cromewell (29. Mai 2016)

ClassiCBond hat gesagt.:


> for(int i=0;i<=2;i++)                 //Horizontale Gewinnbedingung
> for(int j=0;j<=6;j++)
> {if(SpielFeld _ [j]==s && SpielFeld [i+1] [j]==s && SpielFeld [i+2] [j] ==s && SpielFeld [i+3] [j] ==s)
> {a=true;}
> ...


Ich gucks mir gerade durch. Hier hast du auf jeden Fall die Kommentare falsch herum - vertikal ist horizontal und anders herum 
Jetzt gucke ich mir mal die Dioagonale-Bedinung an.


----------



## Cromewell (29. Mai 2016)

```
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 4; j++){
        if(SpielFeld[i][j] == s && SpielFeld[i+1][j+1] == s && SpielFeld[i+2][j+2] == s && SpielFeld[i+3][j+3] == s) {
            a=true;
        }
    }
}
```
Ich kann es leider nicht testen (shame on me), aber eigentlich müsste das gehen. 
So bekommst du diese Art von  Diagonalen raus (alle, die von oben-links nach unten-rechts gehen):
|_1_|_2_|_3_|_4_|_5_|_6_|_7_|
|_a_|___|___|___|___|___|___|
|___|_a_|___|___|___|___|___|
|___|___|_a_|___|___|___|___|
|___|___|___|_a_|___|___|___|
|___|___|___|___|___|___|___|
|___|___|___|___|___|___|___|
Das Ganze muss also noch mal für die von-oben-rechts-nach-unten-links-Diagonale implementiert werden oder erweitert.


----------



## Cromewell (29. Mai 2016)

Also eigentlich so:

```
for(int i = 0; i < 3; i++){
    for(int j = 6; j > 2; j--){
        if(SpielFeld[i][j] == s && SpielFeld[i+1][j-1] == s && SpielFeld[i+2][j-2] == s && SpielFeld[i+3][j-3] == s) {
            a=true;
        }
    }
}
```


----------



## Cromewell (29. Mai 2016)

Habs gerade mal getestet - funktioniert


----------



## ClassiCBond (29. Mai 2016)

Vielen lieben Danke Cromewell für deine Hilfe! Jetzt funktioniert es einwandfrei 

Nochmals Danke für alle Antworten zu meinem Thema!


----------



## Cromewell (29. Mai 2016)

Supi  Kein Problem ^^


----------

