#include <stdio.h>
#include <string.h>
/* Size of the sub-squares also called "boxes", "blocks", "regions" */
#define MIN 3
/* Size of the large square also called "grid" */
#define MAX 9
/* Return code functions */
#define FALSE 0
#define TRUE 1
char sudoku[MAX][MAX]; /* The grid */
long int citac; /* Test counter */
int g_display_flag; /* Flag for displaying set by the option -a */
/********/
int main(int argc, char *argv[]);
int zobraz_pamarametr(char t[]);
/**** INPUTS AND CHECKS ****/
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 sub_square);
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);
/**** RESOLUTION ****/
void vyres_sudoku(void);
int volne_pole_cislo(int number, int row, int sloupec);
void transformuj_ctverecek_poli(char buffer[], int radek, int sloupec);
/**** MISCELLANEOUS ****/
void zobraz_sudoku_cekani(void);
void zobraz_sudoku(void);
void obrazek(int cislo);
int hotove_sudoku(void);
void cekani(void);
int zkontroluj_vstupni_diagonalu2(void);
/******/
int main(int argc, char *argv[])
/******/
{
/* Display option in resolve() function. */
g_display_flag = ((argc >= 2) && (zobraz_pamarametr(argv[1])));
/**********/
printf("\n******* SUDOKU *******\n\n");
printf("Sudoku zobrazuje reseni krok po kroku.\n\n");
printf("Zadej %d radku o %d cislech.\n", MAX, MAX);
printf("Cisla mohou byt oddelena libovolnym cislem.\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("Wrong problem...\n");
printf("Tests: %ld\n\n", citac);
}/* end while */
printf("\n");
return 0;
}
/*******************/
int zobraz_pamarametr (char t[])
/*******************/
{
/* Return TRUE if the user has typed an application with a display option
in the form: a, A, or /a, /A, or -a, -A, etc ... otherwise return FALSE. */
char c;
if (strlen(t) == 1) c = t[0];
else if (strlen(t) == 2) c = t[1];
else c = 0;
return ((c == 'A') || (c == 'a'));
}/* end display_parameter */
/***************************/
/**** INPUTS AND CHECKS ****/
/***************************/
/************/
int zadej_zadani(void)
/************/
{/* User inputs 9 lines of 9 digits. */
int radek;
printf("Enter your Sudoku puzzle: \n");
while (TRUE){
for (radek = 0; radek < MAX; radek++){
if (! zadej_radek(radek)) return (FALSE);
}/* end for */
printf("\nSudoku problem: \n");
zobraz_sudoku();
if (zkontroluj_vstupni_zadani()) return(TRUE);
else printf("\n");
}/* end while */
}/* input_grid */
/**************/
int zadej_radek(int radek)
/**************/
{
/* The user must enter a line from 0 to 9 digits
separated or not by one or more characters.
Only the first 9 digits are retained.
The most practical: Numerical keypad and
put a point after every 3rd number.
Avoid using gets() because of overflows.
In this case, remember to completely empty the buffer. */
int c, i;
int sloupec = 0;
int vysledek = TRUE;
/* Reset to zero of the cells in the row. */
for (i = 0; i < MAX; i++) {
sudoku[radek][i] = 0;
}/* for */
/*******/
printf("row %d : ", radek + 1);
while(TRUE){
c = fgetc(stdin);
if (c == feof(stdin) || c == 0x0A) return vysledek;
else if ((c == 'Q') || (c == 'q')) vysledek = FALSE;
/* Transfer the keyboard input line into the row of the grid. */
else if ( (vysledek) && (sloupec < MAX) && (c >= '0') && (c <= '9')) {
sudoku[radek][sloupec++] = c - 48;
}/*end if */
}/* end while */
}/*end input_a_line */
int zkontroluj_diagonalu(void)
/*********************/
{/* Checks if no duplicate into the columns. */
int i;
int vysledek = TRUE;
if (! zkontroluj_vstupni_diagonalu(i)) vysledek = FALSE;
return vysledek;
}
int zkontroluj_vstupni_diagonalu(int i)
/*******************/
{/* Checks if no duplicate into the row. */
int j;
for (i = 0; i < MAX - 1; i++) {
if ( sudoku[i][i] == 0 ) continue;
for (j = i + 1; j < MAX; j++) {
if (sudoku[j][j] == sudoku[i][i]) {
printf("Error row %d and %d equal numbers\n", i + 1, j + 1);
return FALSE;
}/* end if */
}/* end for j */
}/* end for i */
return TRUE;
}/* end check_input_a_row */
int zkontroluj_druhou_diagonalu(void)
/*********************/
{/* Checks if no duplicate into the columns. */
int i;
int vysledek = TRUE;
if (! zkontroluj_druhou_vstupni_diagonalu(i)) vysledek = FALSE;
return vysledek;
}
int zkontroluj_druhou_vstupni_diagonalu(int i)
/*******************/
{/* Checks if no duplicate into the row. */
int j, k, l;
for (i = 0; i < MAX - 1; i++) {
k = 9 - i;
if ( sudoku[i][k] == 0 ) continue;
for (j = i + 1; j > MAX + 1; i ++) {
l = 9 - j;
if (sudoku[i][k] == sudoku[j][l]) {
printf("Error row %d and %d equal numbers\n", i + 1, j + 1);
return FALSE;
}/* end if */
}/* end for j */
}/* end for i */
return TRUE;
}/* end check_input_a_row */
/******************/
int zkontroluj_vstupni_zadani(void)
/******************/
{/* Check whether any duplicate throughout the grid. */
int vysledek = TRUE;
if (! zkontroluj_vstupni_radky()) vysledek = FALSE;
if (! zkontroluj_vstupni_sloupce()) vysledek = FALSE;
if (! zkontroluj_vstupni_ctverecky()) vysledek = FALSE;
if (! zkontroluj_diagonalu()) vysledek = FALSE;
if (! zkontroluj_druhou_diagonalu()) vysledek = FALSE;
return vysledek;
}/* end check_input_grid */
/******************/
int zkontroluj_vstupni_radky(void)
/******************/
{/* Checks if no duplicate into the rows. */
int radek;
int vysledek = TRUE;
for (radek = 0; radek < MAX; radek++) {
if (! zkontroluj_vstupni_radek(radek)) vysledek = FALSE;
}/* end for */
return vysledek;
}/* end check_input_rows */
/*******************/
int zkontroluj_vstupni_radek(int radek)
/*******************/
{/* Checks if no duplicate into the row. */
int i, j;
for (i = 0; i < MAX - 1; i++) {
if ( sudoku[radek][i] == 0 ) continue;
for (j = i + 1; j < MAX; j++) {
if (sudoku[radek][i] == sudoku[radek][j]) {
printf("Error row %d: and equal numbers\n", radek + 1);
return FALSE;
}/* end if */
}/* end for j */
}/* end for i */
return TRUE;
}/* end check_input_a_row */
/*********************/
int zkontroluj_vstupni_sloupce(void)
/*********************/
{/* Checks if no duplicate into the columns. */
int sloupec;
int vysledek = TRUE;
for (sloupec = 0; sloupec < MAX; sloupec++) {
if (! zkontroluj_vstupni_sloupec(sloupec)) vysledek = FALSE;
}/* end for */
return vysledek;
}/* end check_input_columns */
/**********************/
int zkontroluj_vstupni_sloupec(int sloupec)
/**********************/
{/* Checks if no duplicate into the column. */
int i, j;
for (i = 0; i < MAX - 1; i++) {
if ( sudoku[i][sloupec] == 0 ) continue;
for (j = i + 1; j < MAX; j++) {
if (sudoku[i][sloupec] == sudoku[j][sloupec]) {
printf("Error column %d: equal numbers\n", sloupec + 1);
return FALSE;
}/* end if */
}/* end for j */
}/* end for i */
return TRUE;
}/* end check_input_a_column */
/*************************/
int zkontroluj_vstupni_ctverecky(void)
/*************************/
{/* Checks if no duplicate into the sub-squares of 3 x 3. */
int ctverecek;
int vysledek = TRUE;
for (ctverecek = 0; ctverecek < MAX; ctverecek++) {
if (! zkontroluj_vstupni_ctverecek(ctverecek)) vysledek = FALSE;
}/* end for */
return vysledek;
}/* end check_input_sub_squares */
/**************************/
int zkontroluj_vstupni_ctverecek(int ctverecek)
/**************************/
{/* Checks if no duplicate into the sub-square of 3 x 3. */
char buffer[MAX + 10];
int i, j;
transformuj_ctverecek(buffer, ctverecek);
for (i = 0; i < MAX - 1; i++) {
if (buffer[i] == 0 ) continue;
for (j = i + 1; j < MAX; j++) {
if (buffer[i] == buffer[j]) {
printf("Error sub-square %d: equal numbers\n", ctverecek + 1);
return FALSE;
}/* end if */
}/* end for j */
}/* end for i */
return TRUE;
}/* end check_input_a_sub_square */
/*******************/
void transformuj_ctverecek(char buffer[], int ctverecek)
/*******************/
{/* Transfer the sub-square of 3 x 3 into a one-dimensional array. */
int i, j, x, y, z;
x = (((ctverecek) % MIN) * MIN);
y = (((ctverecek + MIN) / MIN) * MIN) - MIN;
z = 0;
for (j = y; j < y + MIN; j++) {
for (i = x; i < x + MIN; i++) {
buffer[z++] = sudoku[j][i];
}/* end for i */
}/* end for j */
}/* end trans_sub_square */
/**** RESOLUTION ****/
/********************/
void vyres_sudoku(void)
/**********/
{/* Attention, recursive function... */
int radek, sloupec, cislo, buffer_cislo;
for (radek = 0; radek < MAX; radek++) {
for (sloupec = 0; sloupec < MAX; sloupec++) {
if (sudoku[radek][sloupec]) continue;
for (cislo = 1; cislo <= MAX; cislo++) {
if (! volne_pole_cislo(cislo, radek, sloupec)) continue;
buffer_cislo = sudoku[radek][sloupec];
sudoku[radek][sloupec] = cislo;
citac++;
if (g_display_flag) zobraz_sudoku_cekani();
vyres_sudoku();
if (hotove_sudoku()) return;
/* To see all the solutions of the grids
with multiple solutions,
switch the line above as a comment and
remove the comment command of the line below. */
/* if (hotove_sudoku()) zobraz_sudoku_cekani();*/
sudoku[radek][sloupec] = buffer_cislo;
}/* end for number */
return;
}/* end for col */
}/* end for row */
return;
}/* end resolve */
int volne_pole_cislo(int cislo, int radek, int sloupec)
/**********************/
{
/* Test if the number is already in
the line, or the column, or the sub-square of 3 X 3
afferent at the cell pointed to by line and column. */
char buffer[MAX + 10];
int i;
/* If the number is used in the line return FALSE */
for (i = 0; i < MAX; i++) if (sudoku[radek][i] == cislo) return(FALSE);
/* If the number is used in the column return FALSE */
for (i = 0; i < MAX; i++) if (sudoku[i][sloupec] == cislo) return(FALSE);
/* If the number is used in the sub-square of 3 X 3 return FALSE */
transformuj_ctverecek_poli(buffer, radek, sloupec);
for (i = 0; i < MAX; i++) if (buffer[i] == cislo) return (FALSE);
/* whereby the number is available for the cell, return TRUE. */
return(TRUE);
}/* end free_cell_for_number */
/***************************/
void transformuj_ctverecek_poli(char buffer[], int radek, int sloupec)
/***************************/
/* Transfer the sub-square of 3 x 3 of
the cell into a one-dimensional array. */
{
int i, j, k;
while ((radek % MIN) != 0) radek--;
while ((sloupec % MIN) != 0) sloupec--;
k = 0;
for (j = radek; j < radek + MIN; j++) {
for (i = sloupec; i < sloupec + MIN; i++) {
buffer[++k] = sudoku[j][i];
}/* end for i */
}/* end for j */
}/* end trans_sub_square_of_cell */
/***********************/
/**** MISCELLANEOUS ****/
/***********************/
/***********************/
void zobraz_sudoku_cekani(void)
/***********************/
{/* Display the grid with wait for the enter key on the keybord. */
zobraz_sudoku();
printf("%ld, hit the enter key for continuation.", citac);
cekani();
}/* display_grid_waiting */
/***************/
void zobraz_sudoku(void)
/***************/
{/* Display the grid. */
int radek, sloupec;
for (radek = 0; radek < MAX; radek++) {
for (sloupec = 0; sloupec < MAX; sloupec++) {
printf(" %1d ", sudoku[radek][sloupec]);
if ( ((sloupec % MIN) == MIN - 1) && (sloupec < MAX - 1) ) {
printf(" | ");
}
}/* end for col */
printf("\n");
if ( ((radek % MIN) == MIN - 1) && (radek < MAX-1) ) {
obrazek(33);
}
}/* end for row */
printf("\n");
}/* end display_grid */
/*****************/
void obrazek(int cislo)
/*****************/
{/* Displays a sequence of asterisk character. */
int i;
for (i = 1; i <= cislo; i++) {
printf("-");
}
printf("\n");
}/* end display_string */
/****************/
int hotove_sudoku(void)
/****************/
/* Test if the grid is finished.
Return TRUE if grid completed, otherwise return FALSE.
Begins with the end of the grid,
this one being completed by its beginning. */
{
int radek, sloupec;
for (radek = MAX - 1; radek >= 0; radek--) {
for (sloupec = MAX - 1; sloupec >= 0; sloupec--) {
if (sudoku[radek][sloupec] == 0 ) {
return FALSE;
}
}/* end for col */
}/* end for row */
return TRUE;
}/* end finished_grid */
/**********/
void cekani(void)
/**********/
{/* Wait for the enter key on the keybord. */
char c;
while(TRUE){
c = fgetc(stdin);
if (c == feof(stdin) || c == 0x0A) return;
}/* end while */
}/* end waiting */
Zdravím, potřeboval bych tento program dopsat tak, aby z toho bylo diagonální sudoku. Snažím se něco dopsat do funkce int volne_pole_cislo(int cislo, int radek, int sloupec).