#include <stdio.h>
#include <string.h>
#include "zapoctovy-program.c"
#include "funkcni_prototypy.h"
int main(void)
{
printf("\n******* SUDOKU *******\n\n");
printf("Sudoku zobrazuje reseni krok po kroku.\n\n");
printf("Zadej %d radku o %d cislech.\n", 9, 9);
printf("Cisla mohou byt oddelena libovolnym znakem\n");
printf("Zadej nulu pro prazdne pole.\n");
printf("Pro ukonceni zadej pismeno Q.\n\n");
while (zadej_zadani()) {
citac = 0;
vyres_sudoku();
zobraz_sudoku();
if (! hotove_sudoku()) printf("Neco je spatne\n");
printf("Pocet testu: %ld\n\n", citac);
}/*konec while*/
printf("\n");
return 0;
}
#ifndef funkci_prototypy_H
#define funkci_prototypy_H
static long int citac;
static char sudoku[9][9];
/*------Funkce ktere kontroluji zadani atd.------*/
int zadej_zadani(void);
int zadej_radek(int radek);
int zkontroluj_vstupni_zadani(void);
int zkontroluj_vstupni_radky(void);
int zkontroluj_vstupni_radek(int radek);
int zkontroluj_vstupni_sloupce(void);
int zkontroluj_vstupni_sloupec(int sloupec);
int zkontroluj_vstupni_ctverecky(void);
int zkontroluj_vstupni_ctverecek(int ctverecek);
void transformuj_ctverecek(char buffer[], int ctverecek);
int zkontroluj_diagonalu(void);
int zkontroluj_vstupni_diagonalu(int i);
int zkontroluj_druhou_diagonalu(void);
int zkontroluj_druhou_vstupni_diagonalu(int i);
/*------Funkce pro reseni------*/
void vyres_sudoku(void);
int volne_pole_cislo(int cislo, int radek, int sloupec);
void transformuj_ctverecek_poli(char buffer[], int radek, int sloupec);
/*-------Ostatni-------*/
void zobraz_sudoku_cekani(void);
void zobraz_sudoku(void);
void obrazek(int cislo);
int hotove_sudoku(void);
void cekani(void);
#endif
#include "funkcni_prototypy.h"
int zadej_zadani(void) /* Funkce pozada o zadani na kazdem radku 9 cisel */
{
int radek; char sudoku;
printf("Zadejte prosim zadani: \n");
while (1){
for (radek = 0; radek < 9; radek++){
if (! zadej_radek(radek)) return (0);
}/*konec for*/
printf("\n Problem sudoku: \n");
zobraz_sudoku();
if (zkontroluj_vstupni_zadani()) return(1);
else printf("\n");
}/*konec while*/
}/*konec zadej_zadani*/
int zadej_radek(int radek) /*Do pole se zadavaji cisla od 0 do 9, nezalezi jestli jsou oddelena od sebe nebo ne. /
/*Pouze prvnich 9 cisel bude nacteno*/
/*Pouzil jsem fgets() s gets() to nemusi fungovat*/
{
int c, i;
int sloupec = 0;
int vysledek = 1;
/*Nulovani pole*/
for (i = 0; i < 9; i++) {
sudoku[radek][i] = 0;
}/*konec for*/
printf("radek %d : ", radek + 1);
while(1){
c = getc(stdin);
if (c == feof(stdin) || c == 0x0A) return vysledek;
else if ((c == 'Q') || (c == 'q')) vysledek = 0;
/*Prevede zadani do radku sudoku*/
else if ((vysledek) && (sloupec < 9) && (c >= '0') && (c <= '9')) {
sudoku[radek][sloupec++] = c - 48;
}/*konec if*/
}/* konec while*/
}/*konec zadej_radek*/
int zkontroluj_vstupni_zadani(void) /*Jednotlive funkce zkontroluji, jestli nebylo zadano zadani*/
{ /*Tim se vyhneme dalsim problemum*/
int vysledek = 1;
if (! zkontroluj_vstupni_radky()) vysledek = 0;
if (! zkontroluj_vstupni_sloupce()) vysledek = 0;
if (! zkontroluj_vstupni_ctverecky()) vysledek = 0;
if (! zkontroluj_diagonalu()) vysledek = 0;
if (! zkontroluj_druhou_diagonalu()) vysledek = 0;
return vysledek;
}/*konec zkontroluj_vstupni_zadani*/
int zkontroluj_diagonalu(void) /*Zkontroluje, jestli nejsou dve stejna cisla na digonale*/
{ /*pomoci nasledujici funkce*/
int i;
int vysledek = 1;
if (! zkontroluj_vstupni_diagonalu(i)) vysledek = 0;
return vysledek;
}
int zkontroluj_vstupni_diagonalu(int i)
{
int j, k , l;
for (i = 0; i < 8; i++) {
if ( sudoku[i][i] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
if (sudoku[j][j] == sudoku[i][i]) {
printf("chyba v digonale na radku %d a %d: stejna cisla\n", i + 1, j + 1);
return 0;
}/*konec if*/
}/*konec for j*/
}/*konec for i*/
return 1;
}/*konec zkontroluj_vstupni_diagonalu*/
int zkontroluj_druhou_diagonalu(void) /*Zkontroluje, jestli nejsou dve stejna cisla na digonale*/
{ /*pomoci nasledujici funkce*/
int i;
int vysledek = 1;
if (! zkontroluj_druhou_vstupni_diagonalu(i)) vysledek = 0;
return vysledek;
}
int zkontroluj_druhou_vstupni_diagonalu(int i)
{
int m, n, l, k, j;
for (i = 0; i < 8; i++) {
m = 8; n = 0;
n = m - i;
if ( sudoku[i][m] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
n = 8; l = 0;
l = n - j;
if (sudoku[j][l] == sudoku[i][m]) {
printf("chyba v digonale na radku %d a %d: stejna cisla\n", i + 1, j + 1);
return (0);
}
}
}
return 1;
}/*konec zkontroluj_druhou_vstupni_diagonalu*/
int zkontroluj_vstupni_radky(void) /*Zkontroluje, jestli nejsou dve stejna cisla na radkach*/
{
int radek;
int vysledek = 1;
for (radek = 0; radek < 9; radek++) {
if (! zkontroluj_vstupni_radek(radek)) vysledek = 0;
}/*konec for*/
return vysledek;
}/*konec zkontroluj_vstupni_radky*/
int zkontroluj_vstupni_radek(int radek) /*Zkontroluje, jestli nejsou dve stejna cisla na radkach */
{
int i, j;
for (i = 0; i < 8; i++) {
if ( sudoku[radek][i] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
if (sudoku[radek][i] == sudoku[radek][j]) {
printf("Chyba radku %d: stejna cisla\n", radek + 1);
return 0;
}/*konec if*/
}/*konec for j*/
}/*konec for i*/
return 1;
}/* konec zkontroluj_vstupni_radek*/
int zkontroluj_vstupni_sloupce(void) /*Zkontroluje, jestli nejsou stejna cisla ve sloupcich*/
{
int sloupec;
int vysledek = 1;
for (sloupec = 0; sloupec < 9; sloupec++) {
if (! zkontroluj_vstupni_sloupec(sloupec)) vysledek = 0;
}/*konec for*/
return vysledek;
}/*konec zkontroluj_vstupni_sloupce*/
int zkontroluj_vstupni_sloupec(int sloupec) /*Zkontroluje, jestli nejsou stejna cisla ve sloupci*/
{
int i, j;
for (i = 0; i < 8; i++) {
if ( sudoku[i][sloupec] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
if (sudoku[i][sloupec] == sudoku[j][sloupec]) {
printf("Chyba sloupec %d: stejna cisla\n", sloupec + 1);
return 0;
}/*konec if*/
}/*konec for j*/
}/*konec for i*/
return 1;
}/*konec zkontroluj_vstupni_sloupec*/
int zkontroluj_vstupni_ctverecky(void) /*Zkontroluje, jestli nejsou stejna ciala v malych ctvercich (3x3)*/
{
int ctverecek;
int vysledek = 1;
for (ctverecek = 0; ctverecek < 9; ctverecek++) {
if (! zkontroluj_vstupni_ctverecek(ctverecek)) vysledek = 0;
}/*konec for*/
return vysledek;
}/*konec zkontroluj_vstupni_ctverecky*/
int zkontroluj_vstupni_ctverecek(int ctverecek) /*Zkontroluje, jestli nejsou stejna cisla v malem cverci (3x3)*/
{
char buffer[35];
int i, j;
transformuj_ctverecek(buffer, ctverecek);
for (i = 0; i < 8; i++) {
if (buffer[i] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
if (buffer[i] == buffer[j]) {
printf("Chyba v 3x3 %d: stejna cisla\n", ctverecek + 1);
return 0;
}/*konec if*/
}/*konec for j*/
}/*konec for */
return 1;
}/*konec zkontroluj_vstupni_ctverecek*/
void transformuj_ctverecek(char buffer[], int ctverecek) /*Prevede ctverec 3x3 do 1-dimenzionalniho pole*/
{
int i, j, k, l, m;
k = (((ctverecek) % 3) * 3);
l = (((ctverecek + 3) / 3) * 3) - 3;
m = 0;
for (j = l; j < l + 3; j++) {
for (i = k; i < k + 3; i++) {
buffer[m++] = sudoku[j][i];
}/*konec for i*/
}/*konec for j*/
}/*konec transformuj_ctverecek*/
/*------Funkce pro reseni------*/
void vyres_sudoku(void) /*rekurzivni funkce*/
{
int radek, sloupec, cislo, buffer_cislo;
for (radek = 0; radek < 9; radek++) {
for (sloupec = 0; sloupec < 9; sloupec++) {
if (sudoku[radek][sloupec]) continue;
for (cislo = 1; cislo <= 9; cislo++) {
if (! volne_pole_cislo(cislo, radek, sloupec)) continue;
buffer_cislo = sudoku[radek][sloupec];
sudoku[radek][sloupec] = cislo;
citac++;
/*zobraz_sudoku_cekani();*/
vyres_sudoku();
if (hotove_sudoku()) return;
sudoku[radek][sloupec] = buffer_cislo;
}/*konec for cislo*/
return;
}/*konec for sloupec*/
}/*konec for radek*/
return;
}/*konec vyres_sudoku */
int volne_pole_cislo(int cislo, int radek, int sloupec) /*Funkce testuje, jestli cislo uz je v poli, radku, 3x3 nebo diagonale*/
{
char buffer[35];
int i, j, k, l, m, n, a , b;
for (i = 0; i < 8; i++) {
a = 0;
a += i;
if (sudoku[i][a] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
b = 0;
b += j;
if (sudoku[j][b] == sudoku[i][a]) return (0);
}
}
for (i = 0; i < 8; i++) {
k = 8;
m = 0;
m = k - i;
if ( sudoku[i][m] == 0 ) continue;
for (j = i + 1; j < 9; j++) {
n = 8;
l = 0;
l = n - j;
if (sudoku[j][l] == sudoku[i][m]) return (0);
}
}
for (i = 0; i < 9; i++) if (sudoku[radek][i] == cislo) return(0);
for (i = 0; i < 9; i++) if (sudoku[i][sloupec] == cislo) return(0);
transformuj_ctverecek_poli(buffer, radek, sloupec);
for (i = 0; i < 9; i++) if (buffer[i] == cislo) return (0);
/* Jestli se mozne dane cislo doplnit podle splnenych podminek vrati funkce TRUE*/
return(1);
}/*konec volne_pole_cislo*/
void transformuj_ctverecek_poli(char buffer[], int radek, int sloupec)
{
int i, j, k;
while ((radek % 3) != 0) radek--;
while ((sloupec % 3) != 0) sloupec--;
k = 0;
for (j = radek; j < radek + 3; j++) {
for (i = sloupec; i < sloupec + 3; i++) {
buffer[++k] = sudoku[j][i];
}/*konec for i*/
}/*konec for j*/
}/*konec transformuj_ctverecek_poli*/
/*-------Ostatni-------*/
void zobraz_sudoku_cekani(void) /*Zobrazi sudoku a bude cekat na stisknuti klavesy*/
{
zobraz_sudoku();
printf("%ld, zadejte klavesu pro pokracovani", citac);
cekani();
}/*konec zobraz_sudoku_cekani */
void zobraz_sudoku(void) /*zobraz sudoku*/
{
int radek, sloupec;
for (radek = 0; radek < 9; radek++) {
for (sloupec = 0; sloupec < 9; sloupec++) {
printf(" %1d ", sudoku[radek][sloupec]);
if ( ((sloupec % 3) == 2) && (sloupec < 8) ) {
printf(" | ");
}
}/*konec for sloupec*/
printf("\n");
if ( ((radek % 3) == 2) && (radek < 8) ) {
obrazek(33);
}
}/*konec for radek*/
printf("\n");
}/*konec zobraz_sudoku*/
void obrazek(int cislo) /*zobrazuje dany znak, aby byl vysledek prehlednejsi*/
{
int i;
for (i = 1; i <= cislo; i++) {
printf("-");
}
printf("\n");
}/*konec obrazek*/
int hotove_sudoku(void) /*zkontroluje, jestli je sudoku hotove(plne)*/
{ /*jestli ano vraci TRUE, jestli ne vraci FALSE*/
int radek, sloupec; /*zacina od konce*/
for (radek = 8; radek >= 0; radek--) {
for (sloupec = 8; sloupec >= 0; sloupec--) {
if (sudoku[radek][sloupec] == 0 ) {
return 0;
}
}/*konec for sloupec*/
}/*konec for radek*/
return 1;
}/*konec hotove_sudoku*/
void cekani(void) /*Ceka na stisk klavesy enter*/
{
char c;
while(1){
c = fgetc(stdin);
if (c == feof(stdin) || c == 0x0A) return;
}/*konec while*/
}/*konec funkce cekani*/