Sudoku je populární logická hra, jejímž cílem je na plochu 9x9 polí doplnit chybějící číslice 1-9 takovým způsobem, aby se žádná neopakovala vícekrát v žádném řádku, sloupci ani čtverci (plocha se skládá z devíti čtverců velikosti 3x3 pole).
Autorem hlavolamu je Howard Garns, který jej publikoval v roce 1979 (pod názvem Number place). Hra se stala populární nejprve v Japonsku (vydávána od roku 1984) pod názvem Suuji wa dokushin ni kagiru a v roce 2005 se stala známou na celém světě.
Jak řešit Sudoku?
Sudoku se obvykle luští za pomoci tzv. kandidátů, což jsou všechna čísla, která mohou být v daném poli umístěna (na začátku všechna čísla 1-9). Kandidáti jsou poté postupně eliminováni za pomoci více či méně složitých myšlenkových postupů a konstrukcí. V okamžiku, kdy zbyde pouze jeden kandidát, tak je řešením pro dané pole.
Základní pravidla
Pro prvotní eliminaci kandidátů poslouží základní pravidla Sudoku. V žádné řádce, sloupci ani skupině nesmí být žádné číslo vícekrát. Ačkoliv je tato strategie velmi jednoduchá, tak postačuje pro většinu jednoduchých Sudoku.
(Hidden) Singles
Singles jsou ta políčka, pro která existuje pouze jeden kandidát, který je jejich řešením. Hidden single je takový kandidát, který je jedinečný v rámci dané řádky, sloupce nebo skupiny, ale není v daném políčku osamocený. Přesto je díky základním pravidlům řešením tohoto políčka.
Naked pair
Pokud dvě políčka v rámci skupiny obsahují pouze totožnou dvojici kandidátů, pak žádné další pole v této skupině nesmí dané kandidáty obsahovat (pokud by tomu tak nebylo, tj. některý kandidát by byl řešením jiného pole, tak by nešlo původní políčka vyplnit). Tuto strategii lze analogicky použít pro trojice kandidátů a tři políčka, čtveřice a čtyři políčka a tak dále.
Pointing pairs, Pointing tripples (intersection removal)
Za předpokladu, že se některý kandidát vyskytuje vícekrát v rámci jednoho řádku nebo sloupce skupiny (ale ne v rámci více sloupců/řádků), tak jej můžeme odstranit z průsečíku tohoto řádku/sloupce v ostatních skupinách, kterými tento řádek/sloupec prochází.
Box/Line reduction (intersection removal)
Pokud předchozí postup obrátíme naruby, tak dostaname Box/Line reduction strategii. Mějme řádek nebo sloupec, který má určité kandidáty pouze v jedné skupině, pak můžeme tyto kandidáty vyškrtnout ze všech ostatních polí dané skupiny.
Strojové řešení a generování Sudoku
Při generování nového zadání je zapotřebí řešit Sudoku ve dvou rovinách. Tou první je ověření jednoznačnosti zadání, které provedeme pomocí backtrackingu. Backtracking je metoda organizovaných pokusů a omylů, při které zkusíme na dané pole vložit nějakou hodnotu a zkontrolujeme, jestli toto částečné řešení neodporuje pravidlům. Pokud je vše v pořádku, zkusíme to znovu u dalšího pole. V případě selhání se vrátíme na místo posledního omylu a opravíme jej novým pokusem. Tímto způsobem zaručeně najdeme všechna řešení, která zadání umožňuje. Nevýhodou je velká výpočetní náročnost tohoto postupu (ručně by se dala tato metoda aplikovat jen na velmi omezené podproblémy).
Druhou rovinou je ověření praktické řešitelnosti daného Sudoku. To provedeme pouze za pomoci lidmi použitelných technik, z nichž některé jsme uvedli výše. Tímto způsobem také můžeme snadno stanovit obtížnost řešení na základě počtu potřebných tahů nebo obtížnosti nutných strategií.
Generování zadání
V předchozích odstavcích jsme předpokládali existenci zadání, ale neuvedli jsme si, jakým způsobem jej lze získat. V praxi se používají především dva postupy. První z nich vygeneruje náhodné konzistentní úplné řešení Sudoku a postupně z něj odebírá vyplněná řešení jednotlivých polí. Takto postupuje tak dlouho, dokud má Sudoku jednoznačné řešení, případně dokud obtížnost řešení nepřesáhne nějaký práh.
Druhý přístup je zcela opačný. Algoritmus nejprve vygeneruje zadání, v němž je konzistentně vyplněno 17 polí (nejmenší známý počet polí, pro nějž bylo nalezeno zadání, které má unikátní řešení). Poté procedura postupně vyplňuje náhodná pole a kontroluje konzistenci zadání. V okamžiku, kdy má dané zadání pouze jedno řešení, jehož obtížnost nepřesáhne daný práh, procedura terminuje.
Kód
001.
/**
002.
* Resic Sudoku pomoci backtrackingu. Tato metoda nezjisti, jestli je dane
003.
* sudoku resitelne clovekem, ale zda-li ma dane zadani vubec reseni, pripadne
004.
* kolik takovychto reseni umoznuje (zjisti a vypise vsechna reseni).
005.
* @author Pavel Micka
006.
*/
007.
public
class
SudokuSolver {
008.
/**
009.
* Velikost ulohy == klasicke Sudoku 9*9, 3x vnitrni ctverec 3*3, kazde cislo
010.
* (1-9) pouze jednou v radku, sloupci i ctverci
011.
*/
012.
public
static
final
int
SUDOKU_SIZE =
9
;
013.
/**
014.
* Velikost vnitrnich ctvercu (3*3 dle beznych pravidel)
015.
*/
016.
public
static
final
int
SQUARE_SIZE =
3
;
017.
/**
018.
* Prazdne pole
019.
*/
020.
public
static
final
int
EMPTY =
0
;
021.
022.
/**
023.
* Vyresi zadane Sudoku pomoci backtrackingu (najde vsechna reseni)
024.
* @param array pole zadani
025.
*/
026.
public
static
void
solveSudoku(
int
[][] array) {
027.
if
(array.length != SUDOKU_SIZE)
throw
new
IllegalArgumentException(
"Pole ma mit velikost 9x9"
);
028.
029.
boolean
[][] fixed =
new
boolean
[SUDOKU_SIZE][SUDOKU_SIZE];
030.
for
(
int
i =
0
; i < array.length; i++) {
031.
if
(array[i].length != SUDOKU_SIZE)
throw
new
IllegalArgumentException(
"Pole ma mit velikost 9x9"
);
032.
for
(
int
j =
0
; j < array.length; j++) {
033.
if
(array[i][j] !=
0
) fixed[i][j] =
true
;
034.
035.
}
036.
}
037.
038.
//prejdeme na prvni nepredvyplnenou souradnici
039.
int
x = -
1
;
040.
int
y =
0
;
041.
do
{
042.
x = x +
1
;
//posun o souradnici dal
043.
boolean
overflow = x >= SUDOKU_SIZE;
//pretekl radek?
044.
if
(overflow) {
045.
x =
0
;
046.
y +=
1
;
047.
}
048.
}
while
(fixed[y][x]);
//dokud je pole zablokovane (soucasti zadani)
049.
050.
for
(
int
i =
1
; i <= SUDOKU_SIZE; i++) {
051.
solve(array, fixed, x, y, i);
052.
}
053.
}
054.
/**
055.
* Resi Sudoku
056.
* @param array pole reseni
057.
* @param fixed pole, ve kterem true znamena, ze jde o hodnotu ze zadani,
058.
* @false, ze jde o hodnotu resitele
059.
* @param x souradnice x, na kterou se bude pridavat dalsi hodnota
060.
* @param y souradnice y, na kterou se bude pridavat dalsi hodnota
061.
* @param value hodnota
062.
*/
063.
private
static
void
solve(
int
[][] array,
boolean
[][] fixed,
int
x,
int
y,
int
value) {
064.
if
(!checkConsistency(array, x, y, value))
return
;
//reseni neni konzistentni
065.
array[y][x] = value;
//set
066.
do
{
067.
x = x +
1
;
//posun o souradnici dal
068.
boolean
overflow = x >= SUDOKU_SIZE;
//pretekl radek?
069.
if
(overflow) {
070.
x =
0
;
071.
y +=
1
;
072.
if
(y == SUDOKU_SIZE) {
//pretekl sloupec...konec reseni
073.
printArray(array);
074.
return
;
075.
}
076.
}
077.
}
while
(fixed[y][x]);
//dokud je pole zablokovane (soucasti zadani)
078.
for
(
int
i =
1
; i <= SUDOKU_SIZE; i++) {
//backtrack
079.
solve(array, fixed, x, y, i);
080.
}
081.
array[y][x] = EMPTY;
//reset policka (aby neprekazelo pri backtracku)
082.
}
083.
/**
084.
* Zkontroluje, jestli je reseni stale korektni
085.
* @param array pole reseni
086.
* @param x x souradnice, na kterou je pridavana hodnota
087.
* @param y y souradnice, na kterou je pridavana hodnota
088.
* @param value hodnota
089.
* @return true - pokud je reseni konzistentni, false - pokud reseni neni konzistentni
090.
*/
091.
private
static
boolean
checkConsistency(
int
[][] array,
int
x,
int
y,
int
value) {
092.
//Sloupec
093.
for
(
int
i =
0
; i < array.length; i++) {
094.
if
(i != y && array[i][x] == value)
return
false
;
095.
}
096.
//radek
097.
for
(
int
i =
0
; i < array[y].length; i++) {
098.
if
(i != x && array[y][i] == value)
return
false
;
099.
}
100.
//ctverec
101.
int
vertical = y/SQUARE_SIZE;
//o kolikaty vertikalni ctverec se jedna
102.
int
horizontal = x/SQUARE_SIZE;
//o kolikaty horizontalni ctverec se jedna
103.
104.
for
(
int
i = vertical*SQUARE_SIZE; i < vertical*SQUARE_SIZE + SQUARE_SIZE; i++) {
105.
for
(
int
j = horizontal*SQUARE_SIZE; j < horizontal*SQUARE_SIZE + SQUARE_SIZE; j++) {
106.
if
(array[i][j] == value)
return
false
;
107.
}
108.
}
109.
return
true
;
110.
}
111.
/**
112.
* Vypise pole Sudoku
113.
* @param array pole sudoku
114.
*/
115.
private
static
void
printArray(
int
[][] array) {
116.
for
(
int
i =
0
; i < array.length; i++){
117.
for
(
int
j =
0
; j < array[i].length; j++) {
118.
System.out.print(array[i][j] +
"|"
);
119.
}
120.
System.out.println(
""
);
121.
}
122.
System.out.println(
""
);
123.
}
124.
}
001.
/**
002.
* Resicka sudoku vyuzivajici "lidske" strategie
003.
* @author Pavel Micka
004.
*/
005.
public
class
HumanizedSudokuSolver {
006.
private
SudokuField[][] sudoku;
007.
private
SudokuStrategy[] strategies;
008.
009.
/**
010.
* Zkonstruuje resicku pro zadane sudoku
011.
* @param setting zadani sudoku, 0 znaci prazdne pole
012.
* @param strategies pole strategii, ktere maji byt pouzity
013.
*/
014.
HumanizedSudokuSolver(
int
[][] setting, SudokuStrategy... strategies) {
015.
this
.strategies = strategies;
016.
sudoku =
new
SudokuField[setting.length][setting.length];
017.
for
(
int
i =
0
; i < setting.length; i++) {
018.
for
(
int
j =
0
; j < setting[i].length; j++) {
019.
if
(setting[i][j] ==
0
) {
020.
sudoku[i][j] =
new
SudokuField();
021.
}
else
{
022.
sudoku[i][j] =
new
SudokuField(setting[i][j]);
023.
}
024.
}
025.
}
026.
}
027.
/**
028.
* Vrati reseni sudoku
029.
* @return
030.
*/
031.
public
int
[][] solve() {
032.
boolean
succ;
033.
do
{
034.
succ =
false
;
035.
for
(SudokuStrategy s : strategies) {
036.
succ = s.solve(sudoku);
037.
if
(succ) {
038.
break
;
039.
}
040.
}
041.
}
while
(succ);
042.
043.
int
[][] solution =
new
int
[sudoku.length][sudoku.length];
044.
for
(
int
i =
0
; i < sudoku.length; i++) {
045.
for
(
int
j =
0
; j < sudoku.length; j++) {
046.
solution[i][j] = sudoku[i][j].getSolution();
047.
}
048.
}
049.
050.
return
solution;
051.
052.
053.
}
054.
055.
056.
057.
/**
058.
* Testovaci main metoda
059.
* Program vyresi, co umi, coz jsou s temito strategiemi cca. az pokrocila
060.
* Sudoku a vypise vysledek
061.
* @param args the command line arguments
062.
*/
063.
public
static
void
main(String[] args) {
064.
int
[][] setting = {
//MF DNES 23.8.2010, priloha leto
065.
{
0
,
0
,
4
,
0
,
3
,
6
,
9
,
2
,
7
},
066.
{
1
,
0
,
0
,
0
,
0
,
5
,
0
,
0
,
0
},
067.
{
0
,
0
,
0
,
2
,
0
,
0
,
0
,
0
,
4
},
068.
{
0
,
0
,
5
,
0
,
0
,
0
,
0
,
6
,
0
},
069.
{
6
,
4
,
0
,
0
,
0
,
0
,
0
,
8
,
5
},
070.
{
0
,
7
,
0
,
0
,
0
,
0
,
2
,
0
,
0
},
071.
{
5
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
},
072.
{
0
,
0
,
0
,
7
,
0
,
0
,
0
,
0
,
2
},
073.
{
4
,
3
,
7
,
9
,
2
,
0
,
5
,
0
,
0
}
074.
};
075.
SudokuStrategy[] s = {
new
OneInARowStrategy(),
new
OneInAColumnStrategy(),
new
OneInAGroupStrategy()};
076.
HumanizedSudokuSolver solver =
new
HumanizedSudokuSolver(setting, s);
077.
int
[][] solution = solver.solve();
078.
for
(
int
i =
0
; i < solution.length; i++) {
079.
for
(
int
j =
0
; j < solution.length; j++) {
080.
System.out.print(solution[i][j] +
" "
);
081.
}
082.
System.out.println(
""
);
083.
}
084.
}
085.
}
086.
087.
/**
088.
* Specifikuje metodu, kterou by mely mit vsechny strategie pro reseni Sudoku
089.
* @author Pavel Micka
090.
*/
091.
interface
SudokuStrategy {
092.
093.
/**
094.
* Provede jeden krok reseni Sudoku
095.
* @param sudoku pole obsahujici sudoku, 0 oznacuje prazdna mista
096.
* @return true pokud se povedlo krok provest, false v opacnem pripade
097.
*/
098.
public
boolean
solve(SudokuField[][] sudoku);
099.
}
100.
101.
/**
102.
* Strategie, ktera rika, ze v jednom radku smi byt dane cislo pouze jednou
103.
* @author Pavel Micka
104.
*/
105.
class
OneInARowStrategy
implements
SudokuStrategy {
106.
107.
public
boolean
solve(SudokuField[][] sudoku) {
108.
for
(
int
i =
0
; i < sudoku.length; i++) {
109.
for
(
int
j =
0
; j < sudoku[i].length; j++) {
110.
int
solution = sudoku[i][j].getSolution();
111.
if
(solution !=
0
) {
//pokud pole neni vyreseno
112.
for
(
int
k =
0
; k < sudoku[i].length; k++) {
//overme radku na kandidaty
113.
if
(sudoku[i][k].getSolution() ==
0
) {
//pokud dane pole neni vyreseno
114.
if
(sudoku[i][k].hasCandidate(solution)) {
//a pokud ma kandidata
115.
sudoku[i][k].removeCandidate(solution);
//tak kandidata odstranime
116.
System.out.println(
"OneInARow: Odstranuji kandidata "
+ solution
117.
+
" na souradnicich x: "
+ k +
" y: "
+ i);
118.
return
true
;
//a vratime uspech
119.
}
120.
}
121.
}
122.
}
123.
}
124.
}
125.
return
false
;
126.
}
127.
}
128.
129.
/**
130.
* Strategie, ktera rika, ze v jednom sloupci smi byt dane cislo pouze jednou
131.
* @author Pavel Micka
132.
*/
133.
class
OneInAColumnStrategy
implements
SudokuStrategy {
134.
135.
public
boolean
solve(SudokuField[][] sudoku) {
136.
for
(
int
i =
0
; i < sudoku.length; i++) {
137.
for
(
int
j =
0
; j < sudoku[i].length; j++) {
138.
int
solution = sudoku[j][i].getSolution();
139.
if
(solution !=
0
) {
//pokud pole neni vyreseno
140.
for
(
int
k =
0
; k < sudoku.length; k++) {
//overme sloupec na kandidaty
141.
if
(sudoku[k][i].getSolution() ==
0
) {
//pokud dane pole neni vyreseno
142.
if
(sudoku[k][i].hasCandidate(solution)) {
//a pokud ma kandidata
143.
sudoku[k][i].removeCandidate(solution);
//tak kandidata odstranime
144.
System.out.println(
"OneInAColumn: Odstranuji kandidata "
+ solution
145.
+
" na souradnicich x: "
+ i +
" y: "
+ k);
146.
return
true
;
//a vratime uspech
147.
}
148.
}
149.
}
150.
}
151.
}
152.
}
153.
return
false
;
154.
}
155.
}
156.
157.
/**
158.
* Strategie, ktera rika, ze v jedne skupine muze byt dane cislo pouze jednou
159.
* @author Pavel Micka
160.
*/
161.
class
OneInAGroupStrategy
implements
SudokuStrategy {
162.
163.
public
boolean
solve(SudokuField[][] sudoku) {
164.
int
groupCount = (
int
) Math.sqrt(sudoku.length);
//pocitame se ctvercovym sudoku, pocet skupin na radku a sloupec
165.
for
(
int
i =
0
; i < sudoku.length; i++) {
166.
for
(
int
j =
0
; j < sudoku[i].length; j++) {
167.
int
solution = sudoku[i][j].getSolution();
168.
if
(solution !=
0
) {
//pokud pole neni vyreseno
169.
for
(
int
k = i - (i % groupCount); k < i - (i % groupCount) + groupCount; k++) {
//radky
170.
for
(
int
l = j - (j % groupCount); l < j - (j % groupCount) + groupCount; l++) {
//sloupce
171.
if
(sudoku[k][l].getSolution() ==
0
){
//pokud pole jeste neni vyreseno
172.
if
(sudoku[k][l].hasCandidate(solution)){
//a ma odpovidajiciho kandidata
173.
sudoku[k][l].removeCandidate(solution);
174.
System.out.println(
"OneInAGroup: Odstranuji kandidata "
+ solution
175.
+
" na souradnicich x: "
+ l +
" y: "
+ k);
176.
return
true
;
177.
}
178.
}
179.
}
180.
}
181.
}
182.
}
183.
}
184.
return
false
;
185.
}
186.
}
187.
188.
/**
189.
* Trida policka sudoku
190.
* @author Pavel Micka
191.
*/
192.
class
SudokuField {
193.
194.
/**
195.
* Mnozina kandidatu
196.
*/
197.
private
Set<Integer> candidates;
198.
199.
/**
200.
* Vytvori policko, kandidaty jsou cisla 1-9
201.
*/
202.
public
SudokuField() {
203.
this
.candidates =
new
HashSet<Integer>();
204.
for
(
int
i =
1
; i <=
9
; i++) {
205.
candidates.add(i);
206.
}
207.
}
208.
209.
/**
210.
* Vytvori policko s jedinym kandidatem (resenim)
211.
* @param nr reseni
212.
*/
213.
public
SudokuField(
int
nr) {
214.
this
.candidates =
new
HashSet<Integer>();
215.
candidates.add(nr);
216.
}
217.
218.
/**
219.
* Zjisti, jestli je dane cislo kandidatem tohoto pole
220.
* @param nr cislo
221.
* @return true pokud je cislo kandidatem, false jinak
222.
*/
223.
public
boolean
hasCandidate(
int
nr) {
224.
return
candidates.contains(nr);
225.
}
226.
/**
227.
* Odstrani kandidata
228.
* @param nr kandidat
229.
*/
230.
public
void
removeCandidate(
int
nr) {
231.
boolean
succ = candidates.remove(nr);
232.
assert
succ;
233.
}
234.
235.
/**
236.
* Vrati cislo, ktere je resenim tohoto policka
237.
* @return cislo, ktere je resenim, 0 pokud jeste pole nebylo vyreseno
238.
*/
239.
public
int
getSolution() {
240.
if
(candidates.size() !=
1
) {
241.
return
0
;
242.
}
else
{
243.
return
(Integer) (candidates.toArray()[
0
]);
244.
}
245.
}
246.
}
001.
/**
002.
* Resic Sudoku pomoci backtrackingu. Tato metoda nezjisti, jestli je dane
003.
* sudoku resitelne clovekem, ale zda-li ma dane zadani vubec reseni, pripadne
004.
* kolik takovychto reseni umoznuje (zjisti a vypise vsechna reseni).
005.
* @author Pavel Micka
006.
*/
007.
class
SudokuSolver {
008.
public
:
009.
/**
010.
* Velikost ulohy == klasicke sudoku 9*9, 3x vnitrni ctverec 3*3, kazde cislo
011.
* (1-9) pouze jednou v radku, sloupci i ctverci
012.
*/
013.
static
const
int
SUDOKU_SIZE = 9;
014.
/**
015.
* Velikost vnitrnich ctvercu (3*3 dle beznych pravidel)
016.
*/
017.
static
const
int
SQUARE_SIZE = 3;
018.
/**
019.
* Prazdne pole
020.
*/
021.
static
const
int
EMPTY = 0;
022.
023.
/**
024.
* Vyresi zadane Sudoku pomoci backtrackingu (najde vsechna reseni)
025.
* @param array pole zadani
026.
*/
027.
static
void
solveSudoku(
int
** array) {
028.
bool
** fixed =
new
bool
*[SUDOKU_SIZE];
029.
for
(
int
i = 0; i < SUDOKU_SIZE; i++) {
030.
fixed[i] =
new
bool
[SUDOKU_SIZE];
031.
}
032.
033.
for
(
int
i = 0; i < SUDOKU_SIZE; i++) {
034.
for
(
int
j = 0; j < SUDOKU_SIZE; j++) {
035.
if
(array[i][j] != 0) fixed[i][j] =
true
;
036.
else
fixed[i][j] =
false
;
037.
}
038.
}
039.
040.
//prejdeme na prvni nepredvyplnenou souradnici
041.
int
x = -1;
042.
int
y = 0;
043.
do
{
044.
x = x + 1;
//posun o souradnici dal
045.
bool
overflow = x >= SUDOKU_SIZE;
//pretekl radek?
046.
if
(overflow) {
047.
x = 0;
048.
y += 1;
049.
}
050.
}
while
(fixed[y][x]);
//dokud je pole zablokovane (soucasti zadani)
051.
052.
for
(
int
i = 1; i <= SUDOKU_SIZE; i++) {
053.
solve(array, fixed, x, y, i);
054.
}
055.
056.
//dealokace
057.
for
(
int
i = 0; i < SUDOKU_SIZE; i++)
delete
fixed[i];
058.
delete
[] fixed;
059.
060.
}
061.
private
:
062.
/**
063.
* Resi Sudoku
064.
* @param array pole reseni
065.
* @param fixed pole, ve kterem true znamena, ze jde o hodnotu ze zadani,
066.
* @false, ze jde o hodnotu resitele
067.
* @param x souradnice x, na kterou se bude pridavat dalsi hodnota
068.
* @param y souradnice y, na kterou se bude pridavat dalsi hodnota
069.
* @param value hodnota
070.
*/
071.
static
void
solve(
int
** array,
bool
** fixed,
int
x,
int
y,
int
value) {
072.
if
(!checkConsistency(array, x, y, value))
return
;
//reseni neni konzistentni
073.
array[y][x] = value;
//set
074.
do
{
075.
x = x + 1;
//posun o souradnici dal
076.
bool
overflow = x >= SUDOKU_SIZE;
//pretekl radek?
077.
if
(overflow) {
078.
x = 0;
079.
y += 1;
080.
if
(y == SUDOKU_SIZE) {
//pretekl sloupec...konec reseni
081.
printArray(array);
082.
return
;
083.
}
084.
}
085.
}
while
(fixed[y][x]);
//dokud je pole zablokovane (soucasti zadani)
086.
for
(
int
i = 1; i <= SUDOKU_SIZE; i++) {
//backtrack
087.
solve(array, fixed, x, y, i);
088.
}
089.
array[y][x] = EMPTY;
//reset policka (aby neprekazelo pri backtracku)
090.
}
091.
/**
092.
* Zkontroluje, jestli je reseni stale korektni
093.
* @param array pole reseni
094.
* @param x x souradnice, na kterou je pridavana hodnota
095.
* @param y y souradnice, na kterou je pridavana hodnota
096.
* @param value hodnota
097.
* @return true - pokud je reseni konzistentni, false - pokud reseni neni konzistentni
098.
*/
099.
static
bool
checkConsistency(
int
** array,
int
x,
int
y,
int
value) {
100.
//Sloupec
101.
for
(
int
i = 0; i < SUDOKU_SIZE; i++) {
102.
if
(i != y && array[i][x] == value)
return
false
;
103.
}
104.
//radek
105.
for
(
int
i = 0; i < SUDOKU_SIZE; i++) {
106.
if
(i != x && array[y][i] == value)
return
false
;
107.
}
108.
//ctverec
109.
int
vertical = y/SQUARE_SIZE;
//o kolikaty vertikalni ctverec se jedna
110.
int
horizontal = x/SQUARE_SIZE;
//o kolikaty horizontalni ctverec se jedna
111.
112.
for
(
int
i = vertical*SQUARE_SIZE; i < vertical*SQUARE_SIZE + 3; i++) {
113.
for
(
int
j = horizontal*SQUARE_SIZE; j < horizontal*SQUARE_SIZE + 3; j++) {
114.
if
(array[i][j] == value)
return
false
;
115.
}
116.
}
117.
return
true
;
118.
}
119.
/**
120.
* Vypise pole Sudoku
121.
* @param array pole sudoku
122.
*/
123.
static
void
printArray(
int
** array) {
124.
for
(
int
i = 0; i < SUDOKU_SIZE; i++) {
125.
for
(
int
j = 0; j < SUDOKU_SIZE; j++) {
126.
cout << array[i][j] <<
"|"
;
127.
}
128.
cout <<
"\\n"
;
129.
}
130.
cout <<
"\\n"
;
131.
}
132.
};
Litaratura
- STUART, Andrew. Sudokuwiki.org/ [online]. 2008 [cit. 2010-08-24]. Dostupné z WWW: <http://www.sudokuwiki.org/>.
- JOHNSON, Angus. Angus johnson's homepage [online]. 2005 [cit. 2010-08-24]. SOLVING SUDOKU. Dostupné z WWW: <http://www.angusj.com/sudoku/hints.php>.