codice:
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <limits.h>
typedef unsigned int unint;
#define CEILING(X) (X-(int)(X)) > 0 ? (int)(X+1) : (int)(X)
void toggle_db (int, int, int, int , int, unint *****);
int main ()
{
unint *board2d, *board1d, *****db;
int NR,NC, i, j, interi ,elem, count,config, cella, num_con, caso;
int start_cell;
float integer;
printf("Inserire il numero NR di righe della scacchiera: ");
scanf("%d", &NR);
printf("Inserire il numero NC di colonne della scacchiera: ");
scanf("%d", &NC);
/** Allocazione della scacchiera a due dimensioni **/
board2d=malloc(NR*NC*sizeof(unint));
if(board2d==NULL)
{
printf("Spazio non disponibile\n\n");
return(1);
}
/** Calcolo dei bit da allocare sottoforma di interi **/
integer= (float)(NR*NC)/(CHAR_BIT*(sizeof(unint)));
interi=CEILING(integer);
/** Allocazione della scacchiera rappresentata in una dimensione **/
board1d=malloc(interi*sizeof(unint));
if(board1d==NULL)
{
printf("Spazio non disponibile\n\n");
return(1);
}
/** Inizializzazione della scacchiera 2d a zero **/
for(i=0;i<NR;i++)
{
for(j=0;j<NC;j++)
{
board2d[i*NR+j]=0;
}
}
/** ******************************************************************************************************************************************* **/
/** Allocazione del database e sua inizializzazione tramite la funzione toggle. L'allocazione avviene secondo lo schema: num_con=2,3,4; **/
/** caso=0,1,2,3 corrispondente a orizzontali, verticali, diagonali principali, diagonali secondarie; **/
/** configurazione= 0,..., max per caso, esempio: caso=0 configurazioni=0, NR*(NC-(num+2))+1; **/
/** cella= cella in cui inizia il pattern,...,cella in cui finisce, esempio primo tris orizzontale->cella=0, 1, 2. **/
/** l'indice CELLA indica l'apparteneza di una certa configurazione a quella cella della tabella, così lo stesso bis sarà considerato due volte **/
/** in quanto a lui apparterranno 2 celle e la differenza tra questi due pattern uguali sarà proprio l'indice cella. **/
/** La funzione toggle inizializza solo il primo vettore per ogni configurazione, e poi lo stesso vettore viene copiato negli altri vettori **/
/** appartenenti alla stessa configurazione, riutilizzando le stesse condizioni usate per far variare l'indice CELLA dei singoli vettori del db **/
/** ******************************************************************************************************************************************* **/
db=(unint *****)malloc(3*sizeof(unint ****));
for(num_con=0; num_con<3; num_con++)
{
db[num_con]=(unint ****)malloc(4*sizeof(unint ***));
for(caso=0; caso<4; caso++)
{
switch(caso)
{
case (0):
start_cell = 0;
db[num_con][caso]=(unint ***)malloc(((NR*(NC-(num_con+2)+1)))*sizeof(unint **));
for(config=0; config<(NR*(NC-(num_con+2)+1)); config++)
{
db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
for(cella=start_cell; cella<start_cell+(num_con+2); cella++)
{
db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
/** Con questo piccolo accorgimento, dopo aver creato i vettori unidimensionali, **/
/** se è il primo lo inizializzo a quello che voglio io, tramite la funzione toggle **/
/** altrimenti copio il vettore precedente in quello appena allocato. **/
/** Ovviamente per precedente si intende quello con indice di cella precedente, ma che appartiene allo stesso pattern **/
/** Tuttavia mi da segmentation fault all'atto della copia del vettore **/
if(cella==start_cell)
toggle_db(NC, num_con, caso, config, cella, db);
else
{
for(i=0; i<interi; i++)
{
db[num_con][caso][config][cella][i] = db[num_con][caso][config][(cella-1)][i];
}
}
}
if ((start_cell+num_con+2)%NC != 0)
start_cell++;
else
start_cell += num_con+2;
}
break;
case (1):
db[num_con][caso]=(unint ***)malloc((NC*(NR-(num_con+2)+1))*sizeof(unint **));
for(config=0;config<(NC*(NR-(num_con+2)+1));config++)
{
db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
for(cella=config;cella<config+NC*(num_con+2);cella+=NC)
{
db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
if(cella==start_cell)
toggle_db(NC, num_con, caso, config, cella, db);
else
{
for(i=0;i<interi;i++)
{
db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-NC)][i];
}
}
}
}
break;
case (2):
start_cell=0;
db[num_con][caso]=(unint ***)malloc(((num_con+2)*((NC-(num_con+2)+1)*(NR-(num_con+2)+1)))*sizeof(unint **));
for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
{
db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
for(cella=start_cell;cella<start_cell+NC*(num_con+2);cella+=(NC+1))
{
db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
if(cella==start_cell)
toggle_db(NC, num_con, caso, config, cella, db);
else
{
for(i=0;i<interi;i++)
{
db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-(NC+1))][i];
}
}
}
if ((start_cell+num_con+2)%NC != 0)
start_cell++;
else
start_cell += num_con+2;
}
break;
case (3):
start_cell=num_con+1;
db[num_con][caso]=(unint ***)malloc(((num_con+2)*((NC-(num_con+2)+1)*(NR-(num_con+2)+1)))*sizeof(unint **));
for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
{
db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
for(cella=start_cell;cella<start_cell+(NC-1)*(num_con+2);cella+=(NC-1))
{
db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
if(cella==start_cell)
toggle_db(NC, num_con, caso, config, cella, db);
else
{
for(i=0;i<interi;i++)
{
db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-(NC-1))][i];
}
}
}
if ((start_cell+1)%NC !=0)
start_cell ++;
else
start_cell+=num_con+2;
}
break;
};
}
}
/** Disallocazione del database **/
for(num_con=0;num_con<3;num_con++)
{
for(caso=0; caso<4; caso++)
{
switch(caso)
{
case (0):
start_cell=0;
for(config=0;config<(NR*(NC-(num_con+2)+1));config++)
{
for(cella=start_cell;cella<start_cell+(num_con+2);cella++)
{
free(db[num_con][caso][config][cella]);
}
if ((start_cell+num_con+2)%NC != 0)
start_cell++;
else
start_cell += num_con+2;
}
free(db[num_con][caso][config]);
break;
case (1):
for(config=0;config<(NC*(NR-(num_con+2)+1));config++)
{
for(cella=config;cella<config+NC*(num_con+2);cella+=NC)
{
free(db[num_con][caso][config][cella]);
}
}
free(db[num_con][caso][config]);
break;
case (2):
start_cell=0;
for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
{
for(cella=start_cell;cella<start_cell+NC*(num_con+2);cella+=(NC+1))
{
free(db[num_con][caso][config][cella]);
}
if ((start_cell+num_con+2)%NC != 0)
start_cell++;
else
start_cell += num_con+2;
}
free(db[num_con][caso][config]);
break;
case (3):
start_cell=num_con+1;
for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
{
for(cella=start_cell;cella<start_cell+(NC-1)*(num_con+2);cella+=(NC-1))
{
free(db[num_con][caso][config][cella]);
}
if ((start_cell+1)%NC !=0)
start_cell ++;
else
start_cell+=num_con+2;
}
free(db[num_con][caso][config]);
break;
};
free(db[num_con][caso]);
}
free(db[num_con]);
}
free(db);
return(0);
}
void toggle_db (int NC, int pedine, int caso, int config, int cella, unint *****daba)
{
int i, s, set_on;
switch(caso)
{
case(0):
{
for(s=cella;s<cella+(pedine+2);s++)
{
i= s/(CHAR_BIT*sizeof(unint));
set_on = s % (CHAR_BIT*sizeof(unint));
daba[pedine][caso][config][cella][i] |= (1<<set_on);
}
}
break;
case(1):
{
for(s=cella;s<cella+NC*(pedine+2);s+=NC)
{
i= s/(CHAR_BIT*sizeof(unint));
set_on = s % (CHAR_BIT*sizeof(unint));
daba[pedine][caso][config][cella][i] |= (1<<set_on);
}
}
break;
case(2):
{
for(s=cella;s<cella+NC*(pedine+2);s+=NC+1)
{
i= s/(CHAR_BIT*sizeof(unint));
set_on = s % (CHAR_BIT*sizeof(unint));
daba[pedine][caso][config][cella][i] |= (1<<set_on);
}
}
break;
case(3):
{
for(s=cella;s<cella+(NC-1)*(pedine+2);s+=(NC-1))
{
i= s/(CHAR_BIT*sizeof(unint));
set_on = s % (CHAR_BIT*sizeof(unint));
daba[pedine][caso][config][cella][i] |= (1<<set_on);
}
}
break;
}
}