# Sprung aus einer Schleife ohne break



## pschuer97 (22. Dez 2014)

```
class Feld
{
  char feld[][];  //zweidimensionales Array vom Typ char, stellt Spielfeld dar
  Feld()
  {
    feld = new char [6][7];   //Standardmaße: 6x7
  }
  void setzen(int spielernummer, int spaltennummer)   //setzt einen Spielstein von Spieler 1 oder 2 (wird durch Parameter "int spielernummer" angegeben) in einer Spalte nach Wahl des Spielers
  if(spielernummer==1)
    {
      if(findeFreiesFeld(spaltennummer)!=-1)
      {
        feld[findeFreiesFeld(spaltennummer)][spaltennummer-1]='1';
        gibFeld();
      }
      else
      {
        System.out.println("Diese Spalte ist bereits voll.");
      }
    }
    else
    {
      if(findeFreiesFeld(spaltennummer)!=-1)
      {
        feld[findeFreiesFeld(spaltennummer)][spaltennummer-1]='2';
        gibFeld();
      }
      else
      {
        System.out.println("Diese Spalte ist bereits voll.");
      }
    }
  }
  int findeFreiesFeld(int spaltennummer) 
  {
    int z=5;
    while(feld[z][spaltennummer]!='%')
    {
      z--;
      if (z==-1)
      {
        break;
      }
    }
    return z;
  }
}
```
Ich möchte ein Vier-gewinnt-Spiel als Konsolenapplikation erstellen, und habe eine Frage zum Abbruch
der oben beschriebenen Methode int findeFreiesFeld().

int findeFreiesFeld() soll in einer Spalte des Feldes, welche durch ein Parameter festgelegt wird, 
das tiefste freie Feld suchen. Gibt es kein freies Feld (bzw. ist der Index [0][spaltennummer] nicht frei
gibt die Methode -1 zurück.
Gibt die Methode -1 zurück, so macht setzen() nichts und gibt eine entsprechende Fehlermeldung aus.

Nun habe ich bereits probiert, eine Abfrage in while-Schleife zu schreiben, ob z bereits -1 ist (s.o.). Wenn ja müsste die Schleife abgebrochen werden, im Beispiel oben mit "break".

Jetzt lautet meine Frage: gibt es vielleicht noch Alternativen zu "break" zwecks Abbruch?
Ich habe nämlich mal irgendwo gelesen, dass "break" eine etwas unschöne Variante zum Sprung aus einer Schleife ist.

Oben ist die (bisher einzige) Klasse Feld aufgelistet. Falls es irgendwie relevant ist: ich verwende die Entwicklungsumgebung BlueJ unter Windows 7.

Vielen Dank im Voraus!


----------



## Flown (22. Dez 2014)

So ich hätte da so und so Verbesserungsvorschläge im Allgemeinen:

- Man verwendet englische Bezeichnungen.
- Keine Copy&Paste verwenden (vor allem in setzen(...))
- Verwende Konstanten
- Verwende Informationhiding (setze Felder private und wenn du sie benötigst greif mit getter/setter darauf zu)

Zu deiner Schleife: Verwende doch eine Zählschleife (for)

Dann sieht dein Programm dann so aus:


```
class Field {
  public static final int ROWS = 6;
  public static final int COLUMNS = 7;
  
  private char field[][];
  
  Field() {
    field = new char[ROWS][COLUMNS];
  }
  
  void move(int player, int column) {
    int row = getEmptyRow(column);
    if (row != -1) {
      field[row][column - 1] = Character.forDigit(player, 10);
      // getField()
    } else {
      System.out.println("Diese Spalte ist bereits voll.");
    }
  }
  
  int getEmptyRow(int column) {
    for (int i = field.length - 1; i >= 0; i--) {
      if (field[i][column] != '%') {
        return i;
      }
    }
    return -1;
  }
}
```


----------



## pschuer97 (22. Dez 2014)

Guten Morgen, erstmal schönen Dank für die schnelle Antwort, ich hätte da trotzdem noch ein paar Rückfragen:

-das Informationhiding predigt mir mein Lehrer auch immer. Aber was ist der Witz dabei, bzw. warum ist es besser als der public-Modifikator?

-warum die Konstanten?

-was meinst du mit "copy and paste" ? Das if und else anweisung quasi gleich sind ? wenn ja warum ist das ein problem?


----------



## Flown (22. Dez 2014)

Information hiding kannst du hier nachlesen. Keiner sollte die internen Datenstrukturen kennen, sondern über definierte Schnittstellen (APIs) auf deine Objekte zugreifen. Einfach Google für die Vor- und Nachteile befragen.

Wie du oben in deinem Code kommentiert hast, sind 6x7 Felder "Standard". Also sind es Konstanten und sollten auch als solche Deklariert werden, damit auch andere Klassen mit diesen Arbeiten könnten. Außerdem bieten sie dir eine Übersicht und sind nicht mitten im Code versteckt!

Zu Copy&Paste:

```
if(spielernummer==1)
{
if(findeFreiesFeld(spaltennummer)!=-1)
{
feld[findeFreiesFeld(spaltennummer)][spaltennummer-1]='1';
gibFeld();
}
else
{
System.out.println("Diese Spalte ist bereits voll.");
}
}
else
{
if(findeFreiesFeld(spaltennummer)!=-1)
{
feld[findeFreiesFeld(spaltennummer)][spaltennummer-1]='2';
gibFeld();
}
else
{
System.out.println("Diese Spalte ist bereits voll.");
}
}
```

Das sind zwei gleiche Blöcke die sich nur in der Zuweisung des Feldes unterscheiden. Wenn du es im if-Zweig änderst und im else-Zweig vergisst zu ändern, dann hast du ein Wartbarkeitsproblem und Inkonsistenzen, usw.

Also sowas sollte man vermeiden.

Bei mehr Fragen, her damit!


----------



## pschuer97 (23. Dez 2014)

Eine hätte ich tatsächlich noch: woher kommt die Methode forDigit(int, int) sowie die Objektreferenz davor in deinem  ersten Listing in Zeile 14?


----------



## Flown (23. Dez 2014)

Character ist die Objektwrapper-Klasse für den char Typ. Sie ist definiert in java.lang und somit standardmäßig eingebunden. Die Methode ist eine statische und somit muss man die Klasse nicht instanziert werden.


----------



## pschuer97 (31. Dez 2014)

```
int findeFreiesFeld(int spaltennummer)   
  {
     int z=5;
     while(feld[z][spaltennummer]!='%')
     {
       z--;
       if (z==-1)
       {
         break;
       }
     }
     return z; 
  }
```
Es gibt noch ein winziges Problem mit der bereits oben beschriebenen Methode int findeFreiesFeld(int).
Auch wenn bereits das unterste Feld einer Zeile belegt ist, gibt die Methode hartnäckig 5 zurück. Hat irgendjemand eine Idee warum? Also ich habe sie jetzt zum dritten Mal mit dem BlueJ-Debugger untersucht und finde nur folgendes: die while-Schleife, in welcher die Variable z angepasst werden soll, wird sofort verlassen, d.h. nicht einmal durchlaufen.
Ist da irgendetwas falsch geschrieben?


----------

