sudoku/sudoku.c
2013-10-18 23:04:41 +02:00

356 lines
6.8 KiB
C

#include "sudoku.h"
/*
* Restituisce un numero casuale nell'intervallo [min, max)
*/
int randomr(int min, int max){
int base = rand();
int intervallo = max - min;
if (RAND_MAX == base)
return randomr(min, max);
if (base < RAND_MAX - (RAND_MAX % intervallo))
return min + base / (RAND_MAX / intervallo);
else
return randomr(min, max);
}
/*
* Restituisce due numeri casuali diversi
*/
int *randomd(){
int *r = (int *)malloc(2 * sizeof(int));
do{
r[0] = randomr(1,9);
r[1] = randomr(1,9);
}while(r[0] == r[1]);
return r;
}
/*
* Scambia due variabili.
* Fallisce se si passa la stessa variabile 2 volte.
*/
void scambia(int* a, int* b){
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
/*
* Blocca l'esecuzione finchè non viene premuto invio
*/
void pausa(){
char c;
do
getchar();
while ((c = getchar()) != '\n' && c != EOF);
}
/*
* Cancella le evidenziature per i valori errati
*/
void cancella_errati(){
for(int i=0; i<n; i++)
for(int k=0; k<n; k++)
if(sudoku[i][k][1] == 2)
sudoku[i][k][1] = 1;
}
/*
* Cancella la tabella del sudoku
*/
void vuota(){
for(int i=0; i<n; i++)
for(int k=0; k<n; k++){
sudoku[i][k][0] = 0;
sudoku[i][k][1] = 1;
}
}
/*
* Inizializza la tabella del sudoku
* generando uno schema
*/
void inizializza(int spazi){
int base[n][n] = {\
{6,9,7,1,4,3,8,2,5},\
{4,1,8,9,2,5,6,3,7},\
{2,5,3,8,7,6,4,9,1},\
{7,3,2,4,6,8,5,1,9},\
{8,4,9,3,5,1,7,6,2},\
{5,6,1,2,9,7,3,8,4},\
{3,8,4,7,1,9,2,5,6},\
{1,2,6,5,3,4,9,7,8},\
{9,7,5,6,8,2,1,4,3}\
};
int sostituzioni[9];
/* genera uno schema
* facendo delle sostituzione
* in uno di partenza.
*/
for(int l=0; l<25; l++){
int *r;
//scambia riga
r = randomd();
for(int i=0; i<n; i++){
for(int k=0; k<n; k++)
sostituzioni[k] = base[i][k];
for(int s=0; s<9; s++)
if (sostituzioni[s] == r[0])
sostituzioni[s] = r[1];
else if (sostituzioni[s] == r[1])
sostituzioni[s] = r[0];
for(int p=0; p<9; p++)
for(int q=0; q<9; q++)
base[i][q] = sostituzioni[q];
}
//scambia colonna
r = randomd();
for(int i=0; i<n; i++){
for(int k=0; k<n; k++)
sostituzioni[k] = base[i][k];
for(int s=0; s<9; s++)
if (sostituzioni[s] == r[0])
sostituzioni[s] = r[1];
else if (sostituzioni[s] == r[1])
sostituzioni[s] = r[0];
for(int p=0; p<9; p++)
for(int q=0; q<9; q++)
base[q][i] = sostituzioni[q];
}
}
for(int l=0; l<25; l++){
int r = randomr(0,3);
switch(r){
//colonna centrale fissa
case 0:{
for(int i=0; i<9; i++){
for(int k=0; k<9; k++)
sostituzioni[k] = base[i][k];
for(int j=0; j<9; j++)
if(j != 4)
base[i][j] = sostituzioni[8-j] ;
}
break;
}
//riga centrale fissa
case 1:{
for(int k=0; k<9; k++){
for(int i=0; i<9; i++)
sostituzioni[i] = base[i][k];
for(int j=0; j<9; j++)
if(j!=4)
base[j][k] = sostituzioni[8-j];
}
break;
}
//inversione riga 3-5
case 2:{
for(int i=0; i<9; i++)
scambia(&base[3][i], &base[5][i]);
break;
}
}
}
//inserisci gli spazi
for(int i=0; i<spazi; i++){
int unico = 0; //la casella è valida
do{
int x = randomr(0,9);
int y = randomr(0,9);
if(!base[x][x])
unico = 1;
else {
base[x][y] = 0;
unico = 0;
}
}while(unico == 1);
}
//copia lo schema generato nella matrice
for(int i=0; i<n; i++)
for(int k=0; k<n; k++){
sudoku[i][k][0] = base[i][k];
if(!base[i][k])
sudoku[i][k][1] = 1;
}
}
/*
* Restituisce 0 se nella riga non sono presenti duplicati
* altrimenti restituisce 1.
*/
int controlla_riga(int m){
float media = 0;
for(int i=0; i<n; i++)
media += sudoku[m][i][0];
if(media/9 != 5)
return 1;
return 0;
}
/*
* Restituisce 0 se nella colonna non sono presenti duplicati
* altrimenti restituisce 1.
*/
int controlla_colonna(int m){
float media = 0;
for(int i=0; i<n; i++)
media += sudoku[i][m][0];
if(media/9 != 5)
return 1;
return 0;
}
/*
* Restituisce 0 se nel quadrante non sono presenti duplicati
* altrimenti restituisce 1.
*/
int controlla_quadrante(int m){
float media = 0;
int **quadrante = ottieni_quadrante(m);
for(int i=0; i<n; i++)
media += quadrante[i][0];
if(media/9 != 5)
return 1;
return 0;
}
/*
* Restituisce un array di puntatori a intero del quadrante m.
*/
int **ottieni_quadrante(int m){
int **quadrante = (int **)malloc(sizeof(int *) * n);
int quadranti[][2] = {{0,0}, {0,3}, {0,6}, {3,0}, {3,3}, {3,6},{6,0}, {6,3}, {6,6}};
int t = quadranti[m][0], s = quadranti[m][1], j = 0;
for(int i=t; i<(t+3); i++)
for(int k=s; k<(s+3); k++){
quadrante[j] = sudoku[i][k];
j++;
}
return quadrante;
}
/*
* Evidenzia le casella errate.
* m: numero della riga/colonna/quadrante.
* tipo: 0 - riga,
* 1 - colonna,
* 2 - quadrante,
*/
void evidenzia(int m, int tipo){
switch(tipo){
//riga
case 0:{
for(int i=0; i<n; i++)
if(sudoku[m][i][1])
sudoku[m][i][1] = 2;
break;
}
//colonna
case 1:{
for(int i=0; i<n; i++)
if(sudoku[i][m][1])
sudoku[i][m][1] = 2;
break;
}
//quadrante
case 2:{
int **quadrante = ottieni_quadrante(m);
for(int i=0; i<n; i++)
if(quadrante[i][1])
quadrante[i][1] = 2;
break;
}
}
}
/*
* Controlla la presenza di errori e li evidenzia.
* Restituisce 0 se il sudoku non è corretto altrimenti 1.
*/
int corretto(){
int errori = 0;
for(int i=0; i<n; i++)
if(controlla_riga(i)){
evidenzia(i, 0);
errori = 1;
}
for(int i=0; i<n; i++)
if(controlla_colonna(i)){
evidenzia(i, 1);
errori = 1;
}
for(int i=0; i<n; i++)
if(controlla_riga(i)){
evidenzia(i, 2);
errori = 1;
}
return !errori;
}
/*
* Stampa la tabella del sudoku
*/
void stampa(){
printf("\n\n\n");
for(int i=0; i<n; i++){
printf("%-25s", RESET);
for(int k=0; k<n; k++){
if(!sudoku[i][k][0])
printf("%-12s ", RESET);
else {
switch(sudoku[i][k][1]){
//Schema non modificabile
case 0:{
printf("%-12s%d ", BIANCO, sudoku[i][k][0]);
break;
}
//Inseriti dal giocatore
case 1:{
printf("%-12s%d ", VERDE, sudoku[i][k][0]);
break;
}
//Errati
case 2:{
printf("%-12s%d ", ROSSO, sudoku[i][k][0]);
break;
}
}
}
}
printf("\n\n\n");
}
printf("\n");
}
/*
* Legge la mossa del giocatore
*/
void leggi_mossa(){
int x, y, m;
printf("%s%s%s", VERDE, "(x,y,m): ", BIANCO);
scanf("%d,%d,%d", &x, &y, &m);
if(!sudoku[x][y][1])
printf("%-50sNon puoi cambiare il numero in (%d,%d)",ROSSO, x, y);
else if(!(0 < m < 10))
printf("%-45sSolo numeri tra 1 e 9 estremi inclusi.", ROSSO);
else if(!(0 < x < 10) || !(0 < y < 10))
printf("%.45sLe cordinate sono tra 1 e 9 estremi inclusi.", ROSSO);
else{
sudoku[x][y][0] = m;
return;
}
pausa();
}