All pastes #2075607 Raw Edit

Miscellany

public text v1 · immutable
#2075607 ·published 2011-06-06 15:01 UTC
rendered paste body
public class Sudoku {
    int[][] field;                  // zweidimensionales Array für das Spielfeld.
    boolean[][] filledFromStart;    // Korrespondierendes Array, welches angibt,
                                    // ob ein Feld schon von Anfang an gefüllt ist.
    int line, column;               // Variablen für die aktuelle Zeile und Spalte.
    boolean finished;               // Gibt an, ob wir fertig sind

    public static void main(String[] args) {
        int[][] initialState = new int[9][9];

        // Fülle das Array für die Startfelder, leere Felder bleiben auf 0 gesetzt.
        initialState[0][0] = 8;
        initialState[0][2] = 9;
        initialState[0][3] = 2;
        initialState[0][8] = 3;
        initialState[1][0] = 7;
        initialState[1][4] = 9;
        initialState[1][5] = 3;
        initialState[2][4] = 6;
        initialState[2][5] = 1;
        initialState[3][0] = 1;
        initialState[3][2] = 4;
        initialState[3][7] = 8;
        initialState[4][2] = 3;
        initialState[4][6] = 2;
        initialState[5][1] = 6;
        initialState[5][6] = 3;
        initialState[5][8] = 4;
        initialState[6][3] = 4;
        initialState[6][4] = 5;
        initialState[7][4] = 8;
        initialState[7][5] = 2;
        initialState[7][8] = 7;
        initialState[8][0] = 3;
        initialState[8][5] = 7;
        initialState[8][6] = 4;
        initialState[8][8] = 9;

        // Erzeuge die Sudoku-Instanz und löse das Sudoku
        Sudoku sudoku = new Sudoku(initialState);
        sudoku.solveSudoku();
    }

    /**
     * Konstruktor zum Erstellen eines Sudokus mit der initiellen Belegung
     * im übergebenen Array initialState. Leere Felder sind mit 0 zu belegen.
     */
    public Sudoku(int[][] initialState) {
        field = new int[9][9];                 // initialisiere die Arrays
        filledFromStart = new boolean[9][9];

        // Initialisiere das Spielfeld mit dem Ausgangsstatus
        for (int i=0; i<9; i++) {
            for (int j=0; j<9; j++) {
                field[i][j] = initialState[i][j];
                filledFromStart[i][j] = (initialState[i][j] != 0); // leeres Feld = 0
            }
        }
    }

    /**
     * Lösung durch Backtracking
     */
    public void solveSudoku() {
        finished = false;
        line = column = 0;                    // Beginne in der linken oberen Ecke
        if (filledFromStart[line][column])    // Wenn dieses Feld bereits gefüllt war
            nextFreeField();                  // gehe zum nächsten freien Feld

        while (!finished) {
            // Wenn im aktuellen Feld noch nicht alle Ziffern ausprobiert wurden
            // probiere die nächsthöhere Ziffer und, wenn keine Bedingung verletzt
            // ist, gehe zum nächsten freien Feld weiter

            for(int k = field[line][column]; k<10; k++) {
              field[line][column] = k;
              if (conditionsOK(line, column)) {
                break;
              }

            // ansonsten lösche dieses Feld und gehe zurück zum letzten Feld
            // (das kein Startfeld war)

            else {
                field[line][column] = 0;
                lastFreeField();
              }
            }
        }

        // Gib die Lösung aus
        outputSolution();
    }

    /**
     * Gibt an, ob die Eintragung im Feld (i, j) alle Bedingungen erfüllt.
     */
    private boolean conditionsOK(int i, int j) {
        boolean ok = true;
        // Erste Bedingung: keine doppelte Zahl in Zeile i

        for(int k=0; k < 9; k++) {
          if (field[i][k] == field[i][j]) ok = false;
        }

        // Zweite Bedingung: keine doppelte Zahl in Spalte j

        for(int k=0; k < 9; k++) {
          if (field[k][j] == field[i][j]) ok = false;
        }

        // Dritte Bedingung: keine doppelte Zahl im 3x3 Quadrat, das (i, j) enthält

        int top = i - (i % 3);
        int left = j - (j % 3);
        for(int k = top; k < 3; k++) {
          for(int l = left; l < 3; l++) {
            if(field[k][l] == field[i][j] && ( k != i || l != j )) ok = false;
          }
        }

        return ok;
    }

    /**
     * Gehe zum nächsten freien Feld
     */
    private void nextFreeField() {
        column++;
        if (column > 8) {
            column = 0;
            line++;
        }
        if (line > 8)
            finished = true;
        else if (filledFromStart[line][column])
            nextFreeField();
    }

    /**
     * Gehe zurück zum letzten Feld, das nicht zu Beginn gefüllt war
     */
    private void lastFreeField() {
        column--;
        if (column < 0) {
            column = 8;
            line--;
        }
        if (filledFromStart[line][column])
            lastFreeField();
    }

    /**
     * Gib die Lösung aus
     */
    private void outputSolution() {
        System.out.println();
        for (int i=0; i<9; i++) {
            for (int j=0; j<9; j++) {
                System.out.print(" " + field[i][j]);
            }
            System.out.println();
        }
    }
}