1 | package eu.hsrw.tr.prog.vl.arrays; |
---|
2 | |
---|
3 | import java.util.Arrays; |
---|
4 | |
---|
5 | public class SudokuSolverLogic extends SudokuHelper { |
---|
6 | |
---|
7 | /** |
---|
8 | * Löscht eine Zahl aus dem Array mit den möglichen Zahlen. Ausgehend von |
---|
9 | * einer Zelle, die mit der Zahl belegt wird, werden die Zeile, die Spalte |
---|
10 | * und der Block bereinigt. |
---|
11 | * |
---|
12 | * @param m |
---|
13 | * Array mit den möglichen Zahlen für jede Zelle |
---|
14 | * @param zeile |
---|
15 | * Zeile der aktuellen Zelle |
---|
16 | * @param spalte |
---|
17 | * Spalte der aktuellen Zelle |
---|
18 | * @param zahl |
---|
19 | * Zahl, die für die aktuelle gefunden wurde und daher gelöscht |
---|
20 | * werden muss |
---|
21 | */ |
---|
22 | public static void loescheZahl(boolean[][][] m, int zeile, int spalte, int zahl) { |
---|
23 | // Feststellen in welchem Block wir eigentlich sind -> wir benötigen die |
---|
24 | // kleinste Zeile und die kleinste Spalte dieses Blocks als Offset |
---|
25 | int offsetZ = (zeile / 3) * 3; |
---|
26 | int offsetS = (spalte / 3) * 3; |
---|
27 | |
---|
28 | for (int i = 0; i < m.length; i++) { |
---|
29 | loopCount++; |
---|
30 | |
---|
31 | // lösche aus Zeile |
---|
32 | m[zeile][i][zahl] = false; |
---|
33 | // lösche aus Spalte |
---|
34 | m[i][spalte][zahl] = false; |
---|
35 | // lösche aus Block |
---|
36 | m[offsetZ + i / 3][offsetS + i % 3][zahl] = false; |
---|
37 | } |
---|
38 | // Zelle selbst komplett löschen |
---|
39 | Arrays.fill(m[zeile][spalte], false); |
---|
40 | } |
---|
41 | |
---|
42 | // Prüft, ob bestimmte Zahl Single in der gegebenen Zeile ist |
---|
43 | // Falls ja: Liefert die Spalte, falls nein: -1 |
---|
44 | public static boolean sucheSingleInZeile(boolean[][][] m, int zeile, int zahl) { |
---|
45 | int zaehler = 0; |
---|
46 | |
---|
47 | // suche diese Zahl in der Zeile, |
---|
48 | // i läuft über die Spalten |
---|
49 | for (int i = 0; i < 9; i++) { |
---|
50 | loopCount++; |
---|
51 | |
---|
52 | if (m[zeile][i][zahl]) { |
---|
53 | zaehler++; |
---|
54 | } |
---|
55 | } |
---|
56 | |
---|
57 | return (zaehler == 1); |
---|
58 | } |
---|
59 | |
---|
60 | // Prüft, ob bestimmte Zahl Single in der gegebenen Spalte ist |
---|
61 | // Falls ja: Liefert die Zeile, falls nein: -1 |
---|
62 | public static boolean sucheSingleInSpalte(boolean[][][] m, int spalte, int zahl) { |
---|
63 | int zaehler = 0; |
---|
64 | |
---|
65 | // suche diese Zahl in der Spalte, |
---|
66 | // i läuft über die Zeilen |
---|
67 | for (int i = 0; i < 9; i++) { |
---|
68 | loopCount++; |
---|
69 | |
---|
70 | if (m[i][spalte][zahl]) { |
---|
71 | zaehler++; |
---|
72 | } |
---|
73 | } |
---|
74 | |
---|
75 | return (zaehler == 1); |
---|
76 | } |
---|
77 | |
---|
78 | // Prüft, ob bestimmte Zahl Single in dem gegebenen Block ist |
---|
79 | // Falls ja: Liefert die Position, falls nein: -1 |
---|
80 | public static boolean sucheSingleInBlock(boolean[][][] m, int zeile, int spalte, int zahl) { |
---|
81 | int minZeile = (zeile / 3) * 3; |
---|
82 | int minSpalte = (spalte / 3) * 3; |
---|
83 | |
---|
84 | int zaehler = 0; |
---|
85 | |
---|
86 | for (int i = minZeile; i < minZeile + 3; i++) { |
---|
87 | for (int j = minSpalte; j < minSpalte + 3; j++) { |
---|
88 | loopCount++; |
---|
89 | |
---|
90 | if (m[i][j][zahl]) { |
---|
91 | zaehler++; |
---|
92 | } |
---|
93 | } |
---|
94 | } |
---|
95 | |
---|
96 | return (zaehler == 1); |
---|
97 | } |
---|
98 | |
---|
99 | |
---|
100 | public static void solve(int[][] a) { |
---|
101 | boolean[][][] moeglich = new boolean[9][9][10]; |
---|
102 | // erstmal ist jede Zahl in jeder Zelle möglich |
---|
103 | for (int i = 0; i < 9; i++) { |
---|
104 | for (int j = 0; j < 9; j++) { |
---|
105 | Arrays.fill(moeglich[i][j], true); |
---|
106 | } |
---|
107 | } |
---|
108 | |
---|
109 | // alle Zellen durchgehen und die Vorbelegungen aus den Möglichkeiten löschen |
---|
110 | for (int z = 0; z < 9; z++) { |
---|
111 | for (int s = 0; s < 9; s++) { |
---|
112 | if (a[z][s] < 0) { |
---|
113 | loescheZahl(moeglich, z, s, -a[z][s]); |
---|
114 | } |
---|
115 | } |
---|
116 | } |
---|
117 | |
---|
118 | // alle Singles im Sudoku setzen |
---|
119 | boolean single = false; |
---|
120 | do { |
---|
121 | single = false; |
---|
122 | for (int z = 0; z < 9; z++) { |
---|
123 | for (int s = 0; s < 9; s++) { |
---|
124 | for (int zahl = 1; zahl <= 9; zahl++) { |
---|
125 | loopCount++; |
---|
126 | |
---|
127 | // ist die Zahl für dieses Feld möglich und gibt es Singles? |
---|
128 | if (moeglich[z][s][zahl] |
---|
129 | && (sucheSingleInZeile(moeglich, z, zahl) |
---|
130 | || sucheSingleInSpalte(moeglich, s, zahl) |
---|
131 | || sucheSingleInBlock(moeglich, z, s, zahl))) { |
---|
132 | |
---|
133 | single = true; |
---|
134 | // Sudoku setzen |
---|
135 | a[z][s] = -zahl; |
---|
136 | |
---|
137 | // Möglichkeiten bereinigen |
---|
138 | loescheZahl(moeglich, z, s, zahl); |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
142 | } |
---|
143 | // Kontrollausgabe |
---|
144 | /**/ |
---|
145 | for (int i = 0; i < 9; i++) { |
---|
146 | for (int j = 0; j < 9; j++) { |
---|
147 | for (int k = 1; k <= 9; k++) { |
---|
148 | System.out.print(moeglich[i][j][k] ? k : "-"); |
---|
149 | } |
---|
150 | System.out.print(" "); |
---|
151 | } |
---|
152 | System.out.println(); |
---|
153 | } |
---|
154 | |
---|
155 | System.out.println("*************************************************************************************************"); |
---|
156 | /**/ |
---|
157 | } while (single); |
---|
158 | } |
---|
159 | |
---|
160 | public static void main(String[] args) { |
---|
161 | |
---|
162 | int[][] sudoku = parseSudokuString(SudokuPuzzles.sExtreme2); |
---|
163 | |
---|
164 | printSudoku(sudoku); |
---|
165 | |
---|
166 | solve(sudoku); |
---|
167 | |
---|
168 | printSudoku(sudoku); |
---|
169 | |
---|
170 | SudokuSolverBF.solve(sudoku); |
---|
171 | |
---|
172 | printSudoku(sudoku); |
---|
173 | } |
---|
174 | } |
---|