356 lines
6.8 KiB
C
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();
|
||
|
}
|