Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Docente:
Prof. Elio Piccolo
Studenti:
Pazzola
Sogos
Gian Marco
Giorgio
177905
179803
Indice
1 Il cubo di Rubik
2 Il metodo Fridrich
3.1
Cubo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2
Mosse
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3
Scramble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4 Implementazione dell'algoritmo A*
12
4.1
13
4.2
17
4.3
Implementazione dell'algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5 Applicazione dell'algoritmo
22
6 Codice sorgente
25
Bibliograa
68
ii
Capitolo 1
Il cubo di Rubik
Il cubo di Rubik un celebre rompicapo inventato dal professore di architettura e scultore ungherese
Ern Rubik nel 1974.
Il Cubo presenta nove quadrati su ognuna delle sue sei facce, per un totale di 54 quadrati. I
quadrati dieriscono tra loro per il colore, con un totale di sei colori dierenti. Quando il Cubo di
Rubik risolto, ogni faccia ha tutti i nove quadrati dello stesso colore.
1 Il cubo di Rubik
90 di un centro.
di quattro spigoli e quattro angoli e coinvolge allo stesso tempo cinque facce. L'unica faccia che
non subir cambiamenti quella che giace attorno al centro opposto a quello che viene ruotato.
In Figura 1.5 mostrata una rotazione di -90 della faccia gialla.
Per poter rappresentare tutte le possibili congurazioni, ottenibili eettuando un qualsiasi movimento a partire da una determinata congurazione, occorre introdurre un'appropriata terminologia
1 Il cubo di Rubik
Figura 1.6. Notazione per le diverse facce rispetto al punto di vista dell'osservatore.
Di conseguenza una rotazione di 90 della faccia frontale in senso orario sar identicata con il
simbolo f, mentre una rotazione di -90 sar identicata con f '
1 .
La Tabella 1.1 illustra le diverse congurazioni ottenute a fronte della rotazione di una qualsiasi
delle facce in senso orario e antiorario.
Le lettere maiuscole faranno sempre riferimento alle facce del cubo, mentre le lettere minuscole
faranno riferimento al movimento della faccia corrispondente.
1 nel
codice C tutte le rappresentazioni di rotazioni di -90 che qui sono indicate con l'apice saranno sostituite
f1
1 Il cubo di Rubik
Mossa
orario
3D
antiorario
2D
3D
2D
Tabella 1.1. Rappresentazione delle mosse ottenute ruotando una faccia del cubo a
partire dal cubo risolto.
Oltre alle mosse elencate n'ora possibile eettuare altri tre tipi di movimenti ossia quelli dati
dalla rotazione attorno ai tre assi del cubetto virtuale presente al centro del cubo. Questa categoria di mosse interessa solo gli spigoli compresi tra i quattro centri che vengono traslati, mentre la
posizione e l'orientamento degli angoli rester immutata.
1 Il cubo di Rubik
orario
3D
antiorario
2D
3D
2D
Tabella 1.2. Rappresentazione delle mosse ottenute dalla rotazione attorno ai tre assi del cubetto
virtuale presente al centro del cubo.
Capitolo 2
Il metodo Fridrich
Il Metodo Fridrich il metodo di risoluzione del cubo di Rubik creato da Jessica Fridrich agli inizi
degli anni ottanta ed uno dei metodi pi usati dai partecipanti alle competizioni di speedcubing.
Non il metodo pi complesso in assoluto, ma di fatto non un metodo adatto ai principianti.
Consiste nella memorizzazione ed esecuzione di quattro fasi e ad eccezione della prima, per ricomporre il cubo bisogna memorizzare un totale di 119 algoritmi.
Cross: consiste nel posizionare gli spigoli di una faccia del cubo in modo da formare una
croce tale che entrambi i colori di ogni spigolo siano allineati con i relativi centri. Per questa
fase non ci sono algoritmi ma si esegue basandosi sull'intuito e sull'esperienza: il numero di
mosse per fare la croce dovrebbe essere limitato o superare di poco gli otto movimenti del
cubo (un esempio mostrato in Figura 2.1).
F2L: lo scopo di questa fase quello di completare i primi due strati del cubo. Questo fatto
inserendo le quattro coppie angolo spigolo tra i pezzi della croce sistemati nel primo passo,
come mostrato in Figura 2.2.
I casi che si possono presentare in questa situazione sono 41 (22 + 19 casi simmetrici) i quali
possono essere risolti mediante l'utilizzo di algoritmi prestabiliti.
2 Il metodo Fridrich
OLL: consiste nell'orientare l'ultimo strato del cubo in modo da completare la faccia opposta
a quella della croce (nell'esempio si dovranno orientare i pezzi dell'ultimo strato in modo da
ottenere la faccia gialla come in Figura 2.3).
I casi che si possono presentare in questa situazione sono 57.
PLL: in questa fase occorre permutare i pezzi dell'ultimo strato ancora fuori posto in modo
da completare il cubo (vedi Figura 2.4).
I casi che si possono presentare in questa situazione sono 21.
Capitolo 3
3.1
Cubo
Per la rappresentazione del cubo si scelta una struttura dati composta da sei matrici di dimensione
3x3. Esse rappresentano rispettivamente le facce del cubo F, R, B, L, D e U; questo suggerisce che
il punto di vista della macchina sso (il cubo non sar mai virtualmente ruotato).
I colori sono rappresentati da un char che contiene la lettera iniziale del colore:
r: red ;
g: green ;
o: orange ;
b: blue ;
y: yellow ;
w: white.
char U[3][3];
} cubo;
Il cubo sar stampato seguendo la notazione gi utilizzata in precedenza, come in Figura 1.6.
Di seguito mostrato un esempio di stampa in cui la faccia frontale rossa, quella di destra verde,
quella inferiore bianca e le altre di conseguenza.
3.2
Mosse
Per rappresentare tutte le possibili mosse utilizziamo 18 funzioni, le quali spostano gli elementi
delle matrici coinvolte nel movimento in modo coerente con la mossa da eseguire. Le funzioni si
aspettano in ingresso un cubo generico e restituiscono in output un cubo con la congurazione
derivata dalla mossa eettuata.
Di seguito sono riportati i prototipi di tali funzioni:
stampa(&start);
start = r(&start);
stampa(&start);
Figura 3.2. Stampa della congurazione iniziale del cubo e stampa della congurazione
a fronte della mossa r.
Come possibile vedere dall'output in Figura 3.2, la stampa coerente con la congurazione
illustrata in Tabella 1.1.
3.3
Scramble
Per scramble si intende una successione di mosse atte a mischiare il cubo. Nel nostro programma
abbiamo predisposto una funzione che esegue 35 mosse casuali che eettuano lo scrmable.
Segue un esempio della chiamata a tale funzione:
stampa(&start);
10
start = scramble(&start);
stampa(&start);
Figura 3.3. Stampa della congurazione iniziale del cubo e stampa della congurazione
a seguito dello scramble.
11
Capitolo 4
Implementazione dell'algoritmo A*
Normalmente impossibile avere in memoria una struttura dati che descriva tutto lo spazio degli
stati. Basti pensare che, per il cubo di Rubik, il numero totale delle congurazioni possibili dato
dalle combinazioni di tutti gli angoli con tutti gli spigoli considerando anche le eventuali orientazioni
dei singoli pezzi, ossia
realizzabili in quanto occorre tenere conto dei vincoli di costruzione del cubo, perci il numero
esatto delle combinazioni
Nonostante sia un sotto problema della risoluzione completa del cubo, il numero di combinazioni
che devono essere analizzate per completare il primo step del metodo Fridrich decisamente elevato.
Infatti, considerando che in media il numero di mosse necessarie pari a otto e che le mosse possibili
che possono essere eettuate su una qualsiasi congurazione sono 18, si ha che il numero totale di
nodi che devono essere tenuti in memoria per rappresentare l'albero completo, senza l'eliminazione
di eventuali simmetrie, pari a
180 + 181 + 182 + 183 + 184 + 185 + 186 + 187 + 188 = 11.668.193.551
e considerando che ogni nodo rappresentato da una struttura che ha una dimensione di 68 Byte,
lo spazio di memoria richiesto sarebbe pari a circa 793 GByte. Per questo motivo inopportuno
utilizzare un algoritmo di ricerca in ampiezza per trovare la soluzione con il percorso minimo.
Nasce quindi spontanea la necessit di utilizzare un metodo di ricerca che costruisca un grafo
che rappresenta una porzione dello spazio degli stati.
A* un algoritmo di ricerca su gra che individua un percorso da un dato nodo iniziale verso un
dato nodo goal. Utilizza una stima euristica che classica ogni nodo attraverso una stima della
strada migliore che passa attraverso tale nodo. Il nodo che sar visitato scelto in base a tale stima
euristica. La funzione di valutazione utilizzata dall'algoritmo A* fornisce una stima del costo di un
cammino a costo minimo dal nodo di partenza al nodo nale vincolato a passare per un certo nodo
n dove f(n) il valore della funzione in n. La funzione di valutazione sar utilizzata per ordinare i
12
dove:
4 Implementazione dell'algoritmo A*
h(n)
la stima del costo di un cammino da n a uno stato nale. Per poter calcolare
h(n)
occorre utilizzare tutta la conoscenza euristica disponibile nel dominio del problema.
Il nostro obiettivo quello di applicare l'algoritmo A* alla prima parte del metodo Fridrich (cross),
ossia l'unica che pu essere eseguita solo intuitivamente.
Per fare questo abbiamo bisogno di un'euristica che ci permetta di scegliere di espandere solo i
nodi pi promettenti.
4.1
Come gi detto in precedenza la funzione di valutazione composta da altre due funzioni: g(n) e
.
h(n)
La funzione g(n) tiene traccia del numero di mosse eettuate per arrivare al nodo n. Per quanto
riguarda la scelta della funzione euristica
h(n)
sono al loro posto non era suciente per far convergere l'algoritmo ad una soluzione esplorando
un numero di stati ridotto; con un'euristica incompleta si correva il rischio di ricadere in una
soluzione troppo onerosa in termini di memoria. Occorreva, dunque, valutare anche quanto uno
spigolo fosse vicino, in termini di mosse, ad arrivare alla corretta posizione. In questo modo stato
possibile discriminare situazioni in cui tutti gli spigoli erano fuori posto.
Il nostro scopo quello di realizzare, a partire da una congurazione qualsiasi del cubo, la
croce sulla faccia bianca.
colori bianco, esso si pu trovare in 12 posizioni orientato in due modi diversi per un totale di
24 possibili congurazioni. Il numero di mosse necessarie ad inserire lo spigolo analizzato, nella
posizione corretta della croce, varia da un minimo di zero (lo spigolo gi nella posizione corretta)
ad un massimo di quattro mosse. Il totale di queste mosse calcolato per ogni spigolo che appartiene
.
alla croce fornisce l'h(n)
Per poter spiegare quante mosse sono necessarie per posizionare uno spigolo nella posizione corretta
ci serviamo del seguente esempio:
per prima cosa occorre allineare uno dei due colori dello spigolo al centro corrispondente (in
Figura 4.1 viene allineato lo spigolo rosso-bianco con il centro rosso);
successivamente si deve allineare il colore rimanente al rispettivo centro (in Figura 4.2 viene
allineato lo spigolo rosso-bianco con il centro bianco);
Il numero di mosse necessarie per poter allineare un colore dello spigolo con il suo centro dipende
dalla faccia in cui si trova il colore stesso ad esempio la faccia rossa dista 2 mosse dalla faccia
13
4 Implementazione dell'algoritmo A*
A partire da tali
0 mosse: esiste solo un caso in cui sono necessarie zero mosse per posizionare il pezzo (vedi
Figura 4.3); la parte bianca dello spigolo giace sulla faccia bianca (distanza=0) mentre la
parte rossa giace sulla faccia rossa (d=0) .
dtot = 0 + 0 = 0
posizionare lo spigolo;
1 mossa: nel caso lo spigolo si trovi in una delle congurazioni mostrate in Figura 4.4 sar
necessaria una singola mossa per poter posizionare correttamente lo spigolo. Quando la parte
rossa dello spigolo giace sulla faccia rossa (d=0) la parte bianca dello spigolo giace su una
14
4 Implementazione dell'algoritmo A*
faccia che dista 1 dalla faccia bianca (verde o blu). Analogamente quando la parte bianca
dello spigolo giace sulla faccia bianca (d=0), la parte rossa giace su una faccia che dista 1
dalla faccia rossa (verde o blu). In entrambi i casi il risultato sar .
dtot = 1 + 0 = 1;
Figura 4.4. Esempio dello spigolo rosso-bianco che dista una mossa dalla posizione corretta.
1. In questo caso uno dei due colori dello spigolo giace sulla faccia corretta (d=0), mentre l'altro giace sulla faccia opposta rispetto al suo colore, ad esempio il bianco giace
sulla faccia gialla, quindi occorrerebbero 2 mosse per posizionarlo (vedi Figura 4.5). Il
risultato sar pari a
dtot = 0 + 2 = 2
mosse;
Figura 4.5. Esempio dello spigolo rosso-bianco che dista due mosse dalla posizione corretta.
2. In questo caso ciascun colore dello spigolo giace su una faccia da cui dista 1.
Ad
esempio nel primo caso in Figura 4.6 il bianco giace sull'arancione (d=1) e il rosso giace
sul verde (d=1);
dtot = 1 + 1 = 2
descritti in seguito si noti che lo spigolo non giace mai sulla linea che passa per i colori
bianco-rosso-giallo-arancione (evidenziata nella Figura 4.6);
3 mosse: le congurazioni che, al minimo, si risolvono in tre mosse si dividono in due diverse
categorie:
1. Questo un caso particolare, in cui se si esegue il calcolo come fatto n'ora si ottiene il
valore 2, in quanto le due facce dello spigolo giacciono entrambe su facce da cui distano
una singola mossa; ad esempio nel primo caso della Figura 4.7 si pu notare che il
bianco dista una faccia dall'arancione cos come il rosso dista una sola faccia dal giallo.
15
4 Implementazione dell'algoritmo A*
Figura 4.6. Esempio dello spigolo rosso-bianco che dista due mosse dalla posizione corretta.
In realt occorre tenere conto del fatto che lo spigolo giace sulla linea bianco-rosso-gialloarancione, questo suggerisce la necessit di eseguire un ulteriore mossa per posizionare
in modo corretto lo spigolo. Il calcolo nale sar dunque
dtot = 1 + 1 + 1 = 3
mosse;
Figura 4.7. Esempio dello spigolo rosso-bianco che dista tre mosse dalla posizione corretta.
2. In queste congurazioni un colore dello spigolo giace sulla faccia opposta al colore stesso,
mentre l'altro colore giace su una faccia adiacente. Ad esempio, come mostrato in Figura
4.8, la parte rossa dello spigolo giace sulla faccia arancione (d=2) mentre la parte bianca
giace sulla faccia verde (d=1). In totale si avr
dtot = 2 + 1 = 3
Figura 4.8. Esempio dello spigolo rosso-bianco che dista tre mosse dalla posizione corretta.
4 mosse:
16
4 Implementazione dell'algoritmo A*
che si risolve in quattro mosse. Infatti la faccia gialla dista 2 dalla faccia bianca e la faccia
arancione dista 2 dalla faccia rossa
dtot = 2 + 2 = 4
mosse necessarie.
Figura 4.9. Esempio dello spigolo rosso-bianco che dista quattro mosse dalla posizione corretta.
dtot
,
h(n)
la
2. individuare il colore della faccia su cui giace il bianco individuato nel punto uno;
4. calcolare la distanza tra la faccia su cui giace la parte non bianca dello spigolo e la faccia del
colore non bianco dello spigolo;
6. se
dtot = 1+1 e lo spigolo giace sulla linea bianco - colore_spigolo - giallo - colore_opposto_spigolo
dtot = 1 + 1 + 1
8. calcolare
4.2
h(n)
come
h(n)
= dtot1 + dtot2 + dtot3 + dtot4 .
Nello sviluppo dell'algoritmo A* sar necessario individuare se delle congurazioni sono gi state
elaborate. Per fare questo non suciente un semplice controllo nel quale si verica se le sei matrici
con cui rappresentato il cubo siano identiche alle sei matrici di una congurazione gi analizzata
in precedenza.
Infatti, possibile che le varie mosse che sono eseguite portino a congurazioni
17
4 Implementazione dell'algoritmo A*
Figura 4.10. Quattro congurazioni equivalenti dal punto di vista della croce.
elementoLista* esiste(...);
int confronta(...);
4.3
Implementazione dell'algoritmo
1. Il nodo di partenza (start), che corrisponde al cubo mischiato, posto all'interno di una lista
di nome OPEN dopo averne calcolato la funzione di valutazione
f (start) = 0 + h(start)
;
//passo 1
insert(start,g+h(&start),NULL,NULL);
2. si controlla se la lista OPEN vuota, in quel caso si esce con fallimento;
while(1){
//passo 2
if(open==NULL){
printf("Fallimento: open vuota\n");
return -1;
}
...
}
18
4 Implementazione dell'algoritmo A*
3. si rimuove il primo nodo dalla lista OPEN la quale ordinata in modo crescente rispetto al
valore della funzione di valutazione f(n) e lo si pone in una lista di nome CLOSED;
//passo 3
ptr = pop();
append(ptr);
4. si controlla se il nodo appena inserito un nodo nale e in quel caso si esce con il cammino
risolutivo trovato;
//passo 4
if(h(&ptr->c) == 0){ //condizione finale
printf("Successo.\n");
percorso(ptr);
return 0;
}
5. si espande il nodo considerato generando tutti i suoi successori, ossia si creano 18 cubi ognuno
dei quali rappresenta una possibile mossa eettuata sul cubo di partenza. Per ognuno dei
cubi generati si calcola la funzione di valutazione;
//passo 5
g = hop(ptr);
n[0] = r(&ptr->c);
f_n[0] = g + h(&n[0]);
n[1] = r1(&ptr->c);
f_n[1] = g + h(&n[1]);
n[2] = l(&ptr->c);
f_n[2] = g + h(&n[2]);
n[3] = l1(&ptr->c);
f_n[3] = g + h(&n[3]);
n[4] = u(&ptr->c);
f_n[4] = g + h(&n[4]);
n[5] = u1(&ptr->c);
f_n[5] = g + h(&n[5]);
n[6] = d(&ptr->c);
f_n[6] = g + h(&n[6]);
n[7] = d1(&ptr->c);
f_n[7] = g + h(&n[7]);
19
4 Implementazione dell'algoritmo A*
n[8] = f(&ptr->c);
f_n[8] = g + h(&n[8]);
n[9] = f1(&ptr->c);
f_n[9] = g + h(&n[9]);
n[10] = b(&ptr->c);
f_n[10] = g + h(&n[10]);
n[11] = b1(&ptr->c);
f_n[11] = g + h(&n[11]);
n[12] = m(&ptr->c);
f_n[12] = g + h(&n[12]);
n[13] = m1(&ptr->c);
f_n[13] = g + h(&n[13]);
n[14] = e(&ptr->c);
f_n[14] = g + h(&n[14]);
n[15] = e1(&ptr->c);
f_n[15] = g + h(&n[15]);
n[16] = s(&ptr->c);
f_n[16] = g + h(&n[16]);
n[17] = s1(&ptr->c);
f_n[17] = g + h(&n[17]);
6. ad ogni nodo che non si trova n in OPEN n in CLOSED (si veda 4.2 Riconoscimento delle
simmetrie) si associa la rispettiva funzione di valutazione, si creano i puntatori al nodo che
li ha generati (padre) e si inseriscono in modo ordinato nella lista OPEN;
for (i=0;i<18;i++){
//passo 6
esisteInOpen = esiste(&n[i],open);
esisteInClosed = esiste(&n[i],closed);
if(esisteInOpen == NULL && esisteInClosed == NULL)
insert(n[i], f_n[i], ptr, mossa[i]);
...
}
7. nel caso in cui un nodo appena generato corrisponda ad una congurazione gi analizzata e
quindi presente in OPEN o in CLOSED (si veda 4.2), si verica se la funzione di valutazione
del nodo in questione sia minore di quella gi presente. In tal caso se il nodo era nella lista
CLOSED si aggiorna il valore di f, si reindirizza il puntatore al padre che ha generato il nodo
con la funzione di valutazione inferiore e si sposta l'elemento aggiornato nella lista OPEN;
20
4 Implementazione dell'algoritmo A*
se il nodo, invece, era nella lista OPEN necessario solamente aggiornare la funzione di
valutazione e il puntatore al nodo padre;
for (i=0;i<18;i++){
...
//passo 7
else{
if(esisteInOpen != NULL && f_n[i] < esisteInOpen->f){
insert(n[i], f_n[i], ptr, mossa[i]);
elimina(open,esisteInOpen);
}
if(esisteInClosed != NULL && f_n[i] < esisteInClosed->f){
insert(n[i], f_n[i], ptr, mossa[i]);
elimina(closed,esisteInClosed);
}
}
}
8. si continua l'algoritmo a partire dal passo numero 2.
21
Capitolo 5
Applicazione dell'algoritmo
In questo capitolo saranno analizzati alcuni esempi dell'applicazione dell'algoritmo A*.
22
5 Applicazione dell'algoritmo
23
5 Applicazione dell'algoritmo
24
Capitolo 6
Codice sorgente
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PESI 0
#define NO_PESI 1
typedef struct cubo{
char F[3][3];
char R[3][3];
char B[3][3];
char L[3][3];
char D[3][3];
char U[3][3];
} cubo;
typedef struct struttura{
cubo c;
int f;
char m[2]; //mossa
struct struttura* padre;
struct struttura* next;
} elementoLista;
cubo r(cubo* c);
25
6 Codice sorgente
26
6 Codice sorgente
void albero();
elementoLista* esiste(cubo* c, elementoLista* testa);
int confronta(char cBianco, char spigolo, char Cspigolo, cubo* c);
cubo scramble(cubo* c);
elementoLista* open;
elementoLista* closed;
int nodi_generati();
int main (void){
cubo start;
int i,j;
elementoLista* esisteInOpen=NULL;
elementoLista* esisteInClosed=NULL;
elementoLista* ptr;
cubo n[18];
int f_n[18];
char mossa[18][3];
int g = 0;
int menu = 0;
char scelta[3];
FILE *file;
open = NULL;
closed = NULL;
strcpy(mossa[0],"r");
strcpy(mossa[1],"r1");
strcpy(mossa[2],"l");
strcpy(mossa[3],"l1");
strcpy(mossa[4],"u");
strcpy(mossa[5],"u1");
strcpy(mossa[6],"d");
strcpy(mossa[7],"d1");
27
6 Codice sorgente
strcpy(mossa[8],"f");
strcpy(mossa[9],"f1");
strcpy(mossa[10],"b");
strcpy(mossa[11],"b1");
strcpy(mossa[12],"m");
strcpy(mossa[13],"m1");
strcpy(mossa[14],"e");
strcpy(mossa[15],"e1");
strcpy(mossa[16],"s");
strcpy(mossa[17],"s1");
for (i=0;i<3;i++){
for(j=0;j<3;j++){
start.F[i][j]='r';
start.R[i][j]='g';
start.B[i][j]='o';
start.L[i][j]='b';
start.D[i][j]='w';
start.U[i][j]='y';
}
}
printf("Il programma funziona in tre modalita' differenti.\n");
printf("Digitare:\n");
printf("1 per mischiare il cubo automaticamente\n");
printf("2 per mischiare il cubo manualmente\n");
printf("3 per mischiare il cubo a partire da un elenco di mosse lette da file\n");
scanf("%d",&menu);
switch(menu){
case 1:
start = scramble(&start);
break;
case 2:
stampa(&start);
printf("Digitare una tra le seguenti mosse:\n
r, r1, l, l1, u, u1, d, d1, f, f1, b, b1, m, m1, e, e1, s, s1\n\n");
28
6 Codice sorgente
scanf("%s",scelta);
while(strcmp(scelta,"x")!=0){
start = esegui(&start, scelta);
stampa(&start);
printf("Digitare la mossa successiva o digitare x
per avviare la risoluzione della croce\n");
scanf("%s",scelta);
}
break;
case 3:
file=fopen("scramble.txt","r");
if(!file){
printf("file scramble.txt non trovato.\n");
return -1;
}
else{
while(!feof(file)){
fscanf(file, "%s", scelta);
start=esegui(&start, scelta);
}
fclose(file);
}
break;
default:
printf("scelta non valida, il cubo sara' mischiato automaticamente\n");
start = scramble(&start);
break;
}
printf("Configurazione di partenza:\n");
stampa(&start);
//passo 1
insert(start,g+h(&start),NULL,NULL);
//passo 2
while(1){
29
6 Codice sorgente
if(open==NULL){
printf("Fallimento: open vuota\n");
return -1;
}
//passo 3
ptr = pop();
append(ptr);
//passo 4
if(h(&ptr->c) == 0){ //condizione finale
printf("\nSuccesso\n");
printf("Numero di mosse: %d\n",hop(ptr)-1);
percorso(ptr,NO_PESI);
printf("\nNodi memorizzati: %d\n",nodi_generati());
printf("Soluzione:\n");
stampa(&ptr->c);
printf("\n\nDigitare 1 per vedere i nodi analizzati, con il relativo peso\n");
menu = 0;
scanf("%d",&menu);
if(menu == 1){
printf("\n\nalbero:\n");
percorso(ptr,PESI); printf("**\n");
albero();
}
printf("\n");
system("pause");
return 0;
}
//passo 5
g = hop(ptr);
n[0] = r(&ptr->c);
f_n[0] = g + h(&n[0]);
n[1] = r1(&ptr->c);
f_n[1] = g + h(&n[1]);
30
6 Codice sorgente
n[2] = l(&ptr->c);
f_n[2] = g + h(&n[2]);
n[3] = l1(&ptr->c);
f_n[3] = g + h(&n[3]);
n[4] = u(&ptr->c);
f_n[4] = g + h(&n[4]);
n[5] = u1(&ptr->c);
f_n[5] = g + h(&n[5]);
n[6] = d(&ptr->c);
f_n[6] = g + h(&n[6]);
n[7] = d1(&ptr->c);
f_n[7] = g + h(&n[7]);
n[8] = f(&ptr->c);
f_n[8] = g + h(&n[8]);
n[9] = f1(&ptr->c);
f_n[9] = g + h(&n[9]);
n[10] = b(&ptr->c);
f_n[10] = g + h(&n[10]);
n[11] = b1(&ptr->c);
f_n[11] = g + h(&n[11]);
n[12] = m(&ptr->c);
f_n[12] = g + h(&n[12]);
n[13] = m1(&ptr->c);
f_n[13] = g + h(&n[13]);
n[14] = e(&ptr->c);
f_n[14] = g + h(&n[14]);
n[15] = e1(&ptr->c);
f_n[15] = g + h(&n[15]);
n[16] = s(&ptr->c);
f_n[16] = g + h(&n[16]);
n[17] = s1(&ptr->c);
f_n[17] = g + h(&n[17]);
for (i=0;i<18;i++){
//passo 6
esisteInOpen = esiste(&n[i],open);
esisteInClosed = esiste(&n[i],closed);
31
6 Codice sorgente
32
6 Codice sorgente
}
}
return p;
}
int h(cubo* c){
int d = 0;
if(c->F[0][1] == 'w'){//trovo il bianco
d = d + valuta(c->F[1][1],c->U[2][1],c->U[1][1]);
}
if(c->F[1][0] == 'w'){//trovo il bianco
d = d + valuta(c->F[1][1],c->L[1][2],c->L[1][1]);
}
if(c->F[1][2] == 'w'){//trovo il bianco
d = d + valuta(c->F[1][1],c->R[1][0],c->R[1][1]);
}
if(c->F[2][1] == 'w'){//trovo il bianco
d = d + valuta(c->F[1][1],c->D[0][1],c->D[1][1]);
}
if(c->R[0][1] == 'w'){//trovo il bianco
d = d + valuta(c->R[1][1],c->U[1][2],c->U[1][1]);
}
if(c->R[1][0] == 'w'){//trovo il bianco
d = d + valuta(c->R[1][1],c->F[1][2],c->F[1][1]);
}
if(c->R[1][2] == 'w'){//trovo il bianco
d = d + valuta(c->R[1][1],c->B[1][0],c->B[1][1]);
}
if(c->R[2][1] == 'w'){//trovo il bianco
d = d + valuta(c->R[1][1],c->D[1][2],c->D[1][1]);
}
if(c->B[0][1] == 'w'){//trovo il bianco
d = d + valuta(c->B[1][1],c->U[0][1],c->U[1][1]);
33
6 Codice sorgente
}
if(c->B[1][0] == 'w'){//trovo il bianco
d = d + valuta(c->B[1][1],c->R[1][2],c->R[1][1]);
}
if(c->B[1][2] == 'w'){//trovo il bianco
d = d + valuta(c->B[1][1],c->L[1][0],c->L[1][1]);
}
if(c->B[2][1] == 'w'){//trovo il bianco
d = d + valuta(c->B[1][1],c->D[2][1],c->D[1][1]);
}
if(c->L[0][1] == 'w'){//trovo il bianco
d = d + valuta(c->L[1][1],c->U[1][0],c->U[1][1]);
}
if(c->L[1][0] == 'w'){//trovo il bianco
d = d + valuta(c->L[1][1],c->B[1][2],c->B[1][1]);
}
if(c->L[1][2] == 'w'){//trovo il bianco
d = d + valuta(c->L[1][1],c->F[1][0],c->F[1][1]);
}
if(c->L[2][1] == 'w'){//trovo il bianco
d = d + valuta(c->L[1][1],c->D[1][0],c->D[1][1]);
}
if(c->U[0][1] == 'w'){//trovo il bianco
d = d + valuta(c->U[1][1],c->B[0][1],c->B[1][1]);
}
if(c->U[1][0] == 'w'){//trovo il bianco
d = d + valuta(c->U[1][1],c->L[0][1],c->L[1][1]);
}
if(c->U[1][2] == 'w'){//trovo il bianco
d = d + valuta(c->U[1][1],c->R[0][1],c->R[1][1]);
}
if(c->U[2][1] == 'w'){//trovo il bianco
d = d + valuta(c->U[1][1],c->F[0][1],c->F[1][1]);
}
34
6 Codice sorgente
35
6 Codice sorgente
return 'g';
case 'w':
return 'y';
case 'y':
return 'w';
}
}
cubo r(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][2] = c->D[0][2];
copia.F[1][2] = c->D[1][2];
copia.F[2][2] = c->D[2][2];
copia.U[0][2] = c->F[0][2];
copia.U[1][2] = c->F[1][2];
copia.U[2][2] = c->F[2][2];
copia.B[0][0] = c->U[2][2];
copia.B[1][0] = c->U[1][2];
copia.B[2][0] = c->U[0][2];
copia.D[0][2] = c->B[2][0];
copia.D[1][2] = c->B[1][0];
36
6 Codice sorgente
copia.D[2][2] = c->B[0][0];
ruota(copia.R, c->R);
return copia;
}
cubo r1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][2] = c->U[0][2];
copia.F[1][2] = c->U[1][2];
copia.F[2][2] = c->U[2][2];
copia.U[0][2] = c->B[2][0];
copia.U[1][2] = c->B[1][0];
copia.U[2][2] = c->B[0][0];
copia.B[0][0] = c->D[2][2];
copia.B[1][0] = c->D[1][2];
copia.B[2][0] = c->D[0][2];
copia.D[0][2] = c->F[0][2];
copia.D[1][2] = c->F[1][2];
copia.D[2][2] = c->F[2][2];
37
6 Codice sorgente
ruota1(copia.R, c->R);
return copia;
}
cubo l(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][0] = c->U[0][0];
copia.F[1][0] = c->U[1][0];
copia.F[2][0] = c->U[2][0];
copia.U[0][0] = c->B[2][2];
copia.U[1][0] = c->B[1][2];
copia.U[2][0] = c->B[0][2];
copia.B[0][2] = c->D[2][0];
copia.B[1][2] = c->D[1][0];
copia.B[2][2] = c->D[0][0];
copia.D[0][0] = c->F[0][0];
copia.D[1][0] = c->F[1][0];
copia.D[2][0] = c->F[2][0];
ruota(copia.L, c->L);
38
6 Codice sorgente
return copia;
}
cubo l1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][0] = c->D[0][0];
copia.F[1][0] = c->D[1][0];
copia.F[2][0] = c->D[2][0];
copia.U[0][0] = c->F[0][0];
copia.U[1][0] = c->F[1][0];
copia.U[2][0] = c->F[2][0];
copia.B[0][2] = c->U[2][0];
copia.B[1][2] = c->U[1][0];
copia.B[2][2] = c->U[0][0];
copia.D[0][0] = c->B[2][2];
copia.D[1][0] = c->B[1][2];
copia.D[2][0] = c->B[0][2];
ruota1(copia.L, c->L);
return copia;
}
39
6 Codice sorgente
40
6 Codice sorgente
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][0] = c->L[0][0];
copia.F[0][1] = c->L[0][1];
copia.F[0][2] = c->L[0][2];
copia.R[0][0] = c->F[0][0];
copia.R[0][1] = c->F[0][1];
copia.R[0][2] = c->F[0][2];
copia.B[0][0] = c->R[0][0];
copia.B[0][1] = c->R[0][1];
copia.B[0][2] = c->R[0][2];
copia.L[0][0] = c->B[0][0];
copia.L[0][1] = c->B[0][1];
copia.L[0][2] = c->B[0][2];
ruota1(copia.U, c->U);
return copia;
}
cubo d(cubo* c){
cubo copia;
41
6 Codice sorgente
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[2][0] = c->L[2][0];
copia.F[2][1] = c->L[2][1];
copia.F[2][2] = c->L[2][2];
copia.R[2][0] = c->F[2][0];
copia.R[2][1] = c->F[2][1];
copia.R[2][2] = c->F[2][2];
copia.B[2][0] = c->R[2][0];
copia.B[2][1] = c->R[2][1];
copia.B[2][2] = c->R[2][2];
copia.L[2][0] = c->B[2][0];
copia.L[2][1] = c->B[2][1];
copia.L[2][2] = c->B[2][2];
ruota(copia.D, c->D);
return copia;
}
cubo d1(cubo* c){
cubo copia;
int i,j;
42
6 Codice sorgente
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[2][0] = c->R[2][0];
copia.F[2][1] = c->R[2][1];
copia.F[2][2] = c->R[2][2];
copia.R[2][0] = c->B[2][0];
copia.R[2][1] = c->B[2][1];
copia.R[2][2] = c->B[2][2];
copia.L[2][0] = c->F[2][0];
copia.L[2][1] = c->F[2][1];
copia.L[2][2] = c->F[2][2];
copia.B[2][0] = c->L[2][0];
copia.B[2][1] = c->L[2][1];
copia.B[2][2] = c->L[2][2];
ruota1(copia.D, c->D);
return copia;
}
cubo f(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
43
6 Codice sorgente
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.R[0][0] = c->U[2][0];
copia.R[1][0] = c->U[2][1];
copia.R[2][0] = c->U[2][2];
copia.L[0][2] = c->D[0][0];
copia.L[1][2] = c->D[0][1];
copia.L[2][2] = c->D[0][2];
copia.D[0][0] = c->R[2][0];
copia.D[0][1] = c->R[1][0];
copia.D[0][2] = c->R[0][0];
copia.U[2][0] = c->L[2][2];
copia.U[2][1] = c->L[1][2];
copia.U[2][2] = c->L[0][2];
ruota(copia.F, c->F);
return copia;
}
cubo f1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
44
6 Codice sorgente
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.R[0][0] = c->D[0][2];
copia.R[1][0] = c->D[0][1];
copia.R[2][0] = c->D[0][0];
copia.L[0][2] = c->U[2][2];
copia.L[1][2] = c->U[2][1];
copia.L[2][2] = c->U[2][0];
copia.D[0][0] = c->L[0][2];
copia.D[0][1] = c->L[1][2];
copia.D[0][2] = c->L[2][2];
copia.U[2][0] = c->R[0][0];
copia.U[2][1] = c->R[1][0];
copia.U[2][2] = c->R[2][0];
ruota1(copia.F, c->F);
return copia;
}
cubo b(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
45
6 Codice sorgente
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.R[0][2] = c->D[2][2];
copia.R[1][2] = c->D[2][1];
copia.R[2][2] = c->D[2][0];
copia.L[0][0] = c->U[0][2];
copia.L[1][0] = c->U[0][1];
copia.L[2][0] = c->U[0][0];
copia.D[2][0] = c->L[0][0];
copia.D[2][1] = c->L[1][0];
copia.D[2][2] = c->L[2][0];
copia.U[0][0] = c->R[0][2];
copia.U[0][1] = c->R[1][2];
copia.U[0][2] = c->R[2][2];
ruota(copia.B, c->B);
return copia;
}
cubo b1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
46
6 Codice sorgente
}
}
copia.R[0][2] = c->U[0][0];
copia.R[1][2] = c->U[0][1];
copia.R[2][2] = c->U[0][2];
copia.L[0][0] = c->D[2][0];
copia.L[1][0] = c->D[2][1];
copia.L[2][0] = c->D[2][2];
copia.D[2][0] = c->R[2][2];
copia.D[2][1] = c->R[1][2];
copia.D[2][2] = c->R[0][2];
copia.U[0][0] = c->L[2][0];
copia.U[0][1] = c->L[1][0];
copia.U[0][2] = c->L[0][0];
ruota1(copia.B, c->B);
return copia;
}
cubo m(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
47
6 Codice sorgente
copia.F[0][1] = c->U[0][1];
copia.F[1][1] = c->U[1][1];
copia.F[2][1] = c->U[2][1];
copia.U[0][1] = c->B[2][1];
copia.U[1][1] = c->B[1][1];
copia.U[2][1] = c->B[0][1];
copia.B[0][1] = c->D[2][1];
copia.B[1][1] = c->D[1][1];
copia.B[2][1] = c->D[0][1];
copia.D[0][1] = c->F[0][1];
copia.D[1][1] = c->F[1][1];
copia.D[2][1] = c->F[2][1];
return copia;
}
cubo m1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[0][1] = c->D[0][1];
copia.F[1][1] = c->D[1][1];
copia.F[2][1] = c->D[2][1];
48
6 Codice sorgente
copia.U[0][1] = c->F[0][1];
copia.U[1][1] = c->F[1][1];
copia.U[2][1] = c->F[2][1];
copia.B[0][1] = c->U[2][1];
copia.B[1][1] = c->U[1][1];
copia.B[2][1] = c->U[0][1];
copia.D[0][1] = c->B[2][1];
copia.D[1][1] = c->B[1][1];
copia.D[2][1] = c->B[0][1];
return copia;
}
cubo e(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[1][0] = c->L[1][0];
copia.F[1][1] = c->L[1][1];
copia.F[1][2] = c->L[1][2];
copia.R[1][0] = c->F[1][0];
copia.R[1][1] = c->F[1][1];
copia.R[1][2] = c->F[1][2];
49
6 Codice sorgente
copia.B[1][0] = c->R[1][0];
copia.B[1][1] = c->R[1][1];
copia.B[1][2] = c->R[1][2];
copia.L[1][0] = c->B[1][0];
copia.L[1][1] = c->B[1][1];
copia.L[1][2] = c->B[1][2];
return copia;
}
cubo e1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.F[1][0] = c->R[1][0];
copia.F[1][1] = c->R[1][1];
copia.F[1][2] = c->R[1][2];
copia.R[1][0] = c->B[1][0];
copia.R[1][1] = c->B[1][1];
copia.R[1][2] = c->B[1][2];
copia.L[1][0] = c->F[1][0];
copia.L[1][1] = c->F[1][1];
copia.L[1][2] = c->F[1][2];
50
6 Codice sorgente
copia.B[1][0] = c->L[1][0];
copia.B[1][1] = c->L[1][1];
copia.B[1][2] = c->L[1][2];
return copia;
}
cubo s(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.R[0][1] = c->U[1][0];
copia.R[1][1] = c->U[1][1];
copia.R[2][1] = c->U[1][2];
copia.L[0][1] = c->D[1][0];
copia.L[1][1] = c->D[1][1];
copia.L[2][1] = c->D[1][2];
copia.D[1][0] = c->R[2][1];
copia.D[1][1] = c->R[1][1];
copia.D[1][2] = c->R[0][1];
copia.U[1][0] = c->L[2][1];
copia.U[1][1] = c->L[1][1];
copia.U[1][2] = c->L[0][1];
return copia;
51
6 Codice sorgente
}
cubo s1(cubo* c){
cubo copia;
int i,j;
for (i=0;i<3;i++){
for(j=0;j<3;j++){
copia.F[i][j]=c->F[i][j];
copia.R[i][j]=c->R[i][j];
copia.B[i][j]=c->B[i][j];
copia.L[i][j]=c->L[i][j];
copia.D[i][j]=c->D[i][j];
copia.U[i][j]=c->U[i][j];
}
}
copia.R[0][1] = c->D[1][2];
copia.R[1][1] = c->D[1][1];
copia.R[2][1] = c->D[1][0];
copia.L[0][1] = c->U[1][2];
copia.L[1][1] = c->U[1][1];
copia.L[2][1] = c->U[1][0];
copia.D[1][0] = c->L[0][1];
copia.D[1][1] = c->L[1][1];
copia.D[1][2] = c->L[2][1];
copia.U[1][0] = c->R[0][1];
copia.U[1][1] = c->R[1][1];
copia.U[1][2] = c->R[2][1];
return copia;
}
void ruota (char m[3][3], char mCopia[3][3]){
52
6 Codice sorgente
m[0][0] = mCopia[2][0];
m[0][1] = mCopia[1][0];
m[0][2] = mCopia[0][0];
m[1][0] = mCopia[2][1];
m[1][2] = mCopia[0][1];
m[2][0] = mCopia[2][2];
m[2][1] = mCopia[1][2];
m[2][2] = mCopia[0][2];
}
void ruota1 (char m[3][3], char mCopia[3][3]){
m[0][0] = mCopia[0][2];
m[0][1] = mCopia[1][2];
m[0][2] = mCopia[2][2];
m[1][0] = mCopia[0][1];
m[1][2] = mCopia[2][1];
m[2][0] = mCopia[0][0];
m[2][1] = mCopia[1][0];
m[2][2] = mCopia[2][0];
}
void stampa(cubo* c){
int i,j;
for (i=0;i<3;i++){
printf("\t");
for(j=0;j<3;j++){
printf("%c ",c->U[i][j]);
}
printf("\n");
}
printf("\n");
for (i=0;i<3;i++){
for(j=0;j<3;j++){
printf("%c ",c->L[i][j]);
53
6 Codice sorgente
}
printf("\t");
for(j=0;j<3;j++){
printf("%c ",c->F[i][j]);
}
printf("\t");
for(j=0;j<3;j++){
printf("%c ",c->R[i][j]);
}
printf("\t");
for(j=0;j<3;j++){
printf("%c ",c->B[i][j]);
}
printf("\n");
}
printf("\n");
for (i=0;i<3;i++){
printf("\t");
for(j=0;j<3;j++){
printf("%c ",c->D[i][j]);
}
printf("\n");
}
}
void insert(cubo c, int f, elementoLista* padre, char* m){
elementoLista* nuovoElemento;
elementoLista* indice;
elementoLista* before;
nuovoElemento=(elementoLista*)malloc(sizeof(elementoLista));
nuovoElemento->c=c;
nuovoElemento->f=f;
nuovoElemento->next=NULL;
nuovoElemento->padre=padre;
if(m!=NULL){
54
6 Codice sorgente
strcpy(nuovoElemento->m, m);
}
if(open == NULL){
open = nuovoElemento;
}else{
indice=open;
before=indice;
if(nuovoElemento->f < indice->f){
nuovoElemento->next = open;
open = nuovoElemento;
return;
}
while(indice->next!=NULL){
indice=indice->next;
if(nuovoElemento->f < indice->f){
before->next = nuovoElemento;
nuovoElemento->next = indice;
return;
}
before=indice;
}
indice->next=nuovoElemento;
}
return;
}
elementoLista* pop(elementoLista* testa){
elementoLista* indice;
indice=open;
open=open->next;
indice->next = NULL;
return indice;
}
55
6 Codice sorgente
56
6 Codice sorgente
57
6 Codice sorgente
}
elementoLista* esiste(cubo* c, elementoLista* testa){
int d = 0;
while(testa != NULL) {
if(c->F[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->F[1][1],c->U[2][1],c->U[1][1], &testa->c);
}
if(c->F[1][0] == 'w'){//trovo il bianco
d = d + confronta(c->F[1][1],c->L[1][2],c->L[1][1], &testa->c);
}
if(c->F[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->F[1][1],c->R[1][0],c->R[1][1], &testa->c);
}
if(c->F[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->F[1][1],c->D[0][1],c->D[1][1], &testa->c);
}
if(c->R[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->R[1][1],c->U[1][2],c->U[1][1], &testa->c);
}
if(c->R[1][0] == 'w'){//trovo il bianco
d = d + confronta(c->R[1][1],c->F[1][2],c->F[1][1], &testa->c);
}
if(c->R[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->R[1][1],c->B[1][0],c->B[1][1], &testa->c);
}
if(c->R[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->R[1][1],c->D[1][2],c->D[1][1], &testa->c);
}
if(c->B[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->B[1][1],c->U[0][1],c->U[1][1], &testa->c);
}
if(c->B[1][0] == 'w'){//trovo il bianco
58
6 Codice sorgente
d = d + confronta(c->B[1][1],c->R[1][2],c->R[1][1], &testa->c);
}
if(c->B[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->B[1][1],c->L[1][0],c->L[1][1], &testa->c);
}
if(c->B[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->B[1][1],c->D[2][1],c->D[1][1], &testa->c);
}
if(c->L[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->L[1][1],c->U[1][0],c->U[1][1], &testa->c);
}
if(c->L[1][0] == 'w'){//trovo il bianco
d = d + confronta(c->L[1][1],c->B[1][2],c->B[1][1], &testa->c);
}
if(c->L[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->L[1][1],c->F[1][0],c->F[1][1], &testa->c);
}
if(c->L[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->L[1][1],c->D[1][0],c->D[1][1], &testa->c);
}
if(c->U[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->U[1][1],c->B[0][1],c->B[1][1], &testa->c);
}
if(c->U[1][0] == 'w'){//trovo il bianco
d = d + confronta(c->U[1][1],c->L[0][1],c->L[1][1], &testa->c);
}
if(c->U[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->U[1][1],c->R[0][1],c->R[1][1], &testa->c);
}
if(c->U[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->U[1][1],c->F[0][1],c->F[1][1], &testa->c);
}
if(c->D[0][1] == 'w'){//trovo il bianco
d = d + confronta(c->D[1][1],c->F[2][1],c->F[1][1], &testa->c);
59
6 Codice sorgente
}
if(c->D[1][0] == 'w'){//trovo il bianco
d = d + confronta(c->D[1][1],c->L[2][1],c->L[1][1], &testa->c);
}
if(c->D[1][2] == 'w'){//trovo il bianco
d = d + confronta(c->D[1][1],c->R[2][1],c->R[1][1], &testa->c);
}
if(c->D[2][1] == 'w'){//trovo il bianco
d = d + confronta(c->D[1][1],c->B[2][1],c->B[1][1], &testa->c);
}
if(d == 4)
return testa;
d=0;
testa = testa->next;
}
return NULL;
}
int confronta(char cBianco, char spigolo, char Cspigolo, cubo* c){
if(c->F[0][1] == 'w'){//trovo il bianco
if(c->F[1][1] == cBianco && c->U[2][1] == spigolo && c->U[1][1] == Cspigolo)
return 1;
}
if(c->F[1][0] == 'w'){//trovo il bianco
if(c->F[1][1] == cBianco && c->L[1][2] == spigolo && c->L[1][1] == Cspigolo)
return 1;
}
if(c->F[1][2] == 'w'){//trovo il bianco
if(c->F[1][1] == cBianco && c->R[1][0] == spigolo && c->R[1][1] == Cspigolo)
return 1;
}
if(c->F[2][1] == 'w'){//trovo il bianco
if(c->F[1][1] == cBianco && c->D[0][1] == spigolo && c->D[1][1] == Cspigolo)
return 1;
}
60
6 Codice sorgente
61
6 Codice sorgente
return 1;
}
if(c->L[1][0] == 'w'){//trovo il bianco
if(c->L[1][1] == cBianco && c->B[1][2] == spigolo && c->B[1][1] == Cspigolo)
return 1;
}
if(c->L[1][2] == 'w'){//trovo il bianco
if(c->L[1][1] == cBianco && c->F[1][0] == spigolo && c->F[1][1] == Cspigolo)
return 1;
}
if(c->L[2][1] == 'w'){//trovo il bianco
if(c->L[1][1] == cBianco && c->D[1][0] == spigolo && c->D[1][1] == Cspigolo)
return 1;
}
if(c->U[0][1] == 'w'){//trovo il bianco
if(c->U[1][1] == cBianco && c->B[0][1] == spigolo && c->B[1][1] == Cspigolo)
return 1;
}
if(c->U[1][0] == 'w'){//trovo il bianco
if(c->U[1][1] == cBianco && c->L[0][1] == spigolo && c->L[1][1] == Cspigolo)
return 1;
}
if(c->U[1][2] == 'w'){//trovo il bianco
if(c->U[1][1] == cBianco && c->R[0][1] == spigolo && c->R[1][1] == Cspigolo)
return 1;
}
if(c->U[2][1] == 'w'){//trovo il bianco
if(c->U[1][1] == cBianco && c->F[0][1] == spigolo && c->F[1][1] == Cspigolo)
return 1;
}
if(c->D[0][1] == 'w'){//trovo il bianco
if(c->D[1][1] == cBianco && c->F[2][1] == spigolo && c->F[1][1] == Cspigolo)
return 1;
}
if(c->D[1][0] == 'w'){//trovo il bianco
62
6 Codice sorgente
63
6 Codice sorgente
}
return i;
}
void albero(){
elementoLista* indice = open;
while(indice != NULL){
percorso(indice,PESI);printf("\n");
indice = indice->next;
}
}
cubo scramble(cubo* c){
int random;
int i=0;
srand(time(NULL));
for(i = 0; i < 35; i++){
random = rand() % 18;
switch(random){
case 0:
*c = r(c);
break;
case 1:
*c = r1(c);
break;
case 2:
*c = l(c);
break;
case 3:
*c = l1(c);
break;
case 4:
*c = u(c);
64
6 Codice sorgente
break;
case 5:
*c = u1(c);
break;
case 6:
*c = d(c);
break;
case 7:
*c = d1(c);
break;
case 8:
*c = f(c);
break;
case 9:
*c = f1(c);
break;
case 10:
*c = b(c);
break;
case 11:
*c = b1(c);
break;
case 12:
*c = m(c);
break;
case 13:
*c = m1(c);
break;
case 14:
*c = e(c);
break;
case 15:
*c = e1(c);
break;
case 16:
*c = s(c);
break;
65
6 Codice sorgente
case 17:
*c = s1(c);
break;
}
}
return *c;
}
int nodi_generati(){
elementoLista* indice = open;
int n = 0;
while(indice != NULL){
n++;
indice = indice->next;
}
indice = closed;
while(indice != NULL){
n++;
indice = indice->next;
}
return n;
}
cubo esegui(cubo* c, char* mossa){
if(strcmp(mossa,"r") == 0)
return r(c);
if(strcmp(mossa,"r1") == 0)
return r1(c);
if(strcmp(mossa,"l") == 0)
return l(c);
if(strcmp(mossa,"l1") == 0)
return l1(c);
if(strcmp(mossa,"u") == 0)
return u(c);
if(strcmp(mossa,"u1") == 0)
66
6 Codice sorgente
return u1(c);
if(strcmp(mossa,"d") == 0)
return d(c);
if(strcmp(mossa,"d1") == 0)
return d1(c);
if(strcmp(mossa,"f") == 0)
return f(c);
if(strcmp(mossa,"f1") == 0)
return f1(c);
if(strcmp(mossa,"b") == 0)
return b(c);
if(strcmp(mossa,"b1") == 0)
return b1(c);
if(strcmp(mossa,"m") == 0)
return m(c);
if(strcmp(mossa,"m1") == 0)
return m1(c);
if(strcmp(mossa,"e") == 0)
return e(c);
if(strcmp(mossa,"e1") == 0)
return e1(c);
if(strcmp(mossa,"s") == 0)
return s(c);
if(strcmp(mossa,"s1") == 0)
return s1(c);
printf("Mossa non valida\n");
return *c;
}
67
Bibliograa
http://areeweb.polito.it/didattica/gcia/lucidi/Lucidi_Corso/1_Problem_solving/
problem_solving2.pdf
http://it.wikipedia.org/wiki/Cubo_di_rubik
http://it.wikipedia.org/wiki/Metodo_Fridrich
http://en.wikipedia.org/wiki/A*_search_algorithm
68