# Schleife warten lassen



## FightClb (4. Feb 2010)

Hallo, ich sitze zur Zeit an folgendem Projekt für meine Fachrarbeit:

[project.SUDOKU]
   [package.controller]
      SudokuController(SudokuManager,SudokuView).java 
      SudokuFieldController(SudokuField,SudokuFieldView).java
   [package.model]
      SudokuCell(int row, int column).java
      SudokuField(int size).java
      SudokuManager.java
   [package.sudoku]
      Main.java >>erstellt: SudokuManager();SudokuView(SudokuManager);SudokuController(SudokuManager,SudokuView);
   [package.utilities]
      SudokuChecker.java
      SudokuGenerator.java
      SudokuSolver.java //alles static, dient nur für die Methoden
   [package.view]
      SudokuFieldView(SudokuField).java
      SudokuView(SudokuManager).java

Zu erweiternde Funktion:
    Schrittweises Lösen (Anzeigen des SudokuFeldes) während der Methoden.

Problem:
    Wie kann ich die Schleife der statischen Methode solveSudokuBruteForce warten lassen und währenddessen die Anzeige erneuern.

Projekt:
RapidShare: 1-CLICK Web hosting - Easy Filehosting

QuellCode:
Methode SolveBruteForce:

```
private static void solveBruteForce(int size, SudokuField sudokuField, boolean stepByStep) {
        //Vorbereitungen treffen
        Stack freeCells = getFreeCells(size, sudokuField);
        Stack increasedCells = new Stack();
        Stack solvedSudokus = new Stack();
        SudokuCell currentSudokuCell;
        //Alle Zellen auf den Mindestwert setzen
        while (!freeCells.isEmpty()) {
            currentSudokuCell = (SudokuCell) freeCells.peek();
            increasedCells.push(freeCells.pop());
            currentSudokuCell.setValue(1);
        }
        while (!increasedCells.isEmpty()) {
            freeCells.push(increasedCells.pop());
        }
        //Alle Möglichen Kombinationen durchgehen
        while (!freeCells.isEmpty()) {
            boolean newValue = false;
            //Die aktuelle Zelle hat ihren Maximalwert erreicht, also soll die nächste Zelle auch erhöht werden.
            while (!newValue) {
                currentSudokuCell = (SudokuCell) freeCells.peek();
                if (currentSudokuCell.getValue() < 9 && !freeCells.isEmpty()) {
                    currentSudokuCell.incValue();
                    newValue = true;
                } else {
                    currentSudokuCell.setValue(1);
                    increasedCells.push(freeCells.pop());
                }
            }
            // Alle Zellen wieder auf den 1. Stapel setzen
            while (!increasedCells.isEmpty()) {
                freeCells.push(increasedCells.pop());
            }

            if(stepByStep){
                sudokuField.refresh();
                //Warten lassen
            }
            if (SudokuChecker.isValidSudoku(size, sudokuField)) {
                return;
            }
        }
        return;
    }
```


----------



## Steev (4. Feb 2010)

Ich würde das mit Threads machen. Einen für´s Rechnen und einen für´s Rendern.
In dem Stufe-für-Stufe Modus würde ich dann die Berechnung nur einmal pro Sekunde (oder so) aufrufen.

[Java]
public class YourClass implements Runnable {
  public YourClass() {
    new Thread(this).start();
  }
  ...
  public void run() {
    while(true) {
      if (stepByStep) {
        if (System.currentTimeNano() - oldTimer > yourWaitNano) {
          yourCalculationMethode();
        }
      } else {
        yourCalculationMethode();
      }

      // Repaint your Panel
      repaint();
      try {
        Thread.sleep(60);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  ...
}[/Java]


----------



## FightClb (4. Feb 2010)

Könnte mir das bitte jemand genauer erläutern, wie ich das Sudoku-Spiel, dass ich nach dem MVC-Prinzip entwickelt habe, jetzt in Threads umschreiben kann? Muss ich dazu den gesamten Aufbau umschreiben, oder muss ich nur die Klassen an der Stelle x erstellen?
Die einzige Arbeit, die ich bisher mit Threads gemacht habe, war bei der Entwicklung von Handyspielen, allerdings kann ich keine der bisher gemachten Erfahrungen auf das aktuelle Projekt anwenden.


----------



## FightClb (5. Feb 2010)

Dieses Thema wurde bereits im Anfänger Board gelöst, bitte Schließen/Löschen (ich hab den Thread unregistriert erstellt), danke.


----------



## Steev (5. Feb 2010)

Und, hat sich dein Problem jetzt erledigt?


----------



## FightClb (6. Feb 2010)

ja, die ActionListener des controlers sollten statt einer Methode auszuführen einen Thread starten, der die Methode durchzuführt, um eine sofortige Aktualisierung der View zu ermöglichen


----------



## Steev (6. Feb 2010)

Ich finde diese Methode nicht so toll, weil dann X neue Objekte (Thread-Objekte) erstellt werden. Man kann es natürlich erstmal so lassen, in diesem Ausmaß ist das ja nicht so schlimm.

Vieleicht solltest du dir für die Zukunft einmal Thread-Pools ansehen...


----------



## FightClb (6. Feb 2010)

ich lasse bei der Initialisierung (im Konstruktor) den Thread erstellen.
Der Thread wird dann vom ActionListener gestartet und am Ende des Threads ist die Methode this.teminate() implementiert.
Das einzige wo ich im moment in Zwiespalt ist, ist das folgende:

Während ja nun der Thread das Sudoku löst, gibt es ein boolean stepByStep der entweder an oder aus ist.
Wenn er an ist, ist alles prima, man sieht was geschieht.
Wenn er aber aus ist, gibt es 2 Möglichkeiten:

 -entweder ich lasse das view immerwieder aktualisieren (die neuen Button-Namen setzen)
 -oder ich lasse das view (aus performance-gründen, die bei einem extrem schweren 16x16 sudoku vorhanden sind) nicht aktualisieren.

Wenn ich es aber nicht aktualisieren lasse (wie in der aktuellen Version), dann erkennt man gar nicht, dass das Programm arbeitet. Ich könnte natürlich ein Pop-Up erscheinen lassen "bitte warten" und wenn man auf abbrechen klickt, wird der Thread (sudokuControllerThread) beendet. Wäre das eine sinnvolle lösung?
Eine weitere Möglichkeit wäre im Controller folgendes einzuführen:


```
if(model.isStepByStep()){
     Thread.start();
}else{
      <<Methoden die auch im Thread sind>>
}
```

Das würde bedeuten, dass Programm ohne auswählen der stepByStep-Option angehalten wird, bis die Lösung des Sudokus (oder Rückgabe, dass es keine Lösung gibt) erfolgt ist.

Ich möchte an der Stelle nochmal unterstreichen, dass es nur Sinn des Programms ist, die in einer Facharbeit vorgestellten Lösungsalgorithmen zu präsentieren. Daher kommt es nicht darauf an, den Spielspaß, sondern die Effektivität der Anwendung zu erhöhen.


----------



## Steev (6. Feb 2010)

Hmm,

ich mache das eigendlich immer so, dass man, wenn das Programm arbeitet, jegliche Eingabe blockt und unten in der Statusleiste des Fensters ein beschäftigt-Icon animiert.


----------

