Tesina Cubo Di Rubik v2

download Tesina Cubo Di Rubik v2

of 71

description

Rubik cube

Transcript of Tesina Cubo Di Rubik v2

  • POLITECNICO DI TORINO

    III Facolt di Ingegneria dell'Informazione

    Corso di Laurea in Ingegneria Informatica

    Tesina di Intelligenza Articiale

    Primo step risolutivo del cubo di Rubik

    Implementazione e applicazione dell'algoritmo A*

    Docente:

    Prof. Elio Piccolo

    Studenti:

    Gian Marco Pazzola 179803

    Giorgio Sogos 177905

    Anno accademico 2011-2012

  • Indice

    1 Il cubo di Rubik 1

    2 Il metodo Fridrich 6

    3 Digitalizzazione del contesto 8

    3.1 Cubo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

    3.2 Mosse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

    3.3 Scramble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

    4 Implementazione dell'algoritmo A* 12

    4.1 Scelta della funzione di valutazione . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

    4.2 Riconoscimento delle simmetrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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.

    Figura 1.1. Rappresentazione di un cubo di Rubik.

    Il cubo di Rubik composto da tre assi perpendicolari tra loro su cui sono montati i sei centri del

    cubo, tali centri sono dunque ssi e possono ruotare solo su se stessi (vedi Figura 1.2). Perci si

    hanno sempre le seguenti propriet:

    il centro opposto al rosso l'arancione;

    il centro opposto al blu il verde;

    il centro opposto al bianco il giallo.

    1

  • 1 Il cubo di Rubik

    Figura 1.2. Rappresentazione dei centri.

    Ogni coppia di centri racchiude uno spigolo per un totale di dodici. Essi sono caratterizzati da due

    colori. In Figura 1.3 mostrato lo spigolo rosso-bianco.

    Figura 1.3. Rappresentazione dello spigolo rosso-bianco.

    Ogni terna di spigoli circonda un angolo, complessivamente un cubo di Rubik ne ospita otto. In

    Figura 1.4 rappresentato l'angolo rosso-bianco-verde, racchiuso tra la terna di spigoli rosso-verde,

    bianco-rosso e verde-bianco.

    Figura 1.4. Rappresentazione dell'angolo rosso-bianco-verde..

    Questa particolare costruzione permette di poter eettuare esclusivamente degli specici movimenti

    attraverso la rotazione di 90 di un centro. Tale rotazione implica lo spostamento contemporaneodi 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 movi-

    mento a partire da una determinata congurazione, occorre introdurre un'appropriata terminologia

    2

  • 1 Il cubo di Rubik

    Figura 1.5. Rotazione del centro giallo.

    in cui ciascuna faccia identicata univocamente rispetto al punto di vista dell'osservatore (vedi

    Figura 1.6). La notazione da noi adottata :

    F: front la faccia frontale rispetto all'osservatore;

    R: right la faccia alla destra di front ;

    B: back la faccia opposta a front ;

    L: left la faccia alla sinistra di front ;

    D: down la faccia inferiore del cubo;

    U: up la faccia opposta a down.

    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

    dal numero 1. Ad esempio f ' diventer f1

    3

  • 1 Il cubo di Rubik

    Mossa orario antiorario

    3D 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 catego-

    ria di mosse interessa solo gli spigoli compresi tra i quattro centri che vengono traslati, mentre la

    posizione e l'orientamento degli angoli rester immutata.

    4

  • 1 Il cubo di Rubik

    Questi movimenti prendono il nome di:

    m: meridian rotazione attorno all'asse RIGHT-LEFT ;

    e: equator rotazione attorno all'asse UP-DOWN ;

    s: standing rotazione attorno all'asse BACK-FRONT ;

    come ragurato in Tabella 1.2.

    Mossa orario antiorario

    3D 2D 3D 2D

    Tabella 1.2. Rappresentazione delle mosse ottenute dalla rotazione attorno ai tre assi del cubetto

    virtuale presente al centro del cubo.

    5

  • 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 ricom-

    porre il cubo bisogna memorizzare un totale di 119 algoritmi. Le quattro fasi sono sintetizzate

    dall'acronimo CFOP: Cross, F2L, OLL, PLL.

    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).

    Figura 2.1. Esempio di una croce bianca.

    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.

    6

  • 2 Il metodo Fridrich

    Figura 2.2. Esempio F2L.

    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.

    Figura 2.3. Esempio OLL.

    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.

    Figura 2.4. Cubo risolto.

    7

  • Capitolo 3

    Digitalizzazione del contesto

    Questo capitolo ha lo scopo di illustrare come si passati dalla rappresentazione descritta in

    precedenza al codice di programmazione C.

    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.

    typedef struct cubo{

    char F[3][3];

    char R[3][3];

    char B[3][3];

    char L[3][3];

    char D[3][3];

    8

  • 3 Digitalizzazione del contesto

    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.

    Figura 3.1. Stampa della congurazione iniziale del cubo.

    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:

    cubo r(cubo* c);

    cubo l(cubo* c);

    cubo u(cubo* c);

    cubo d(cubo* c);

    cubo f(cubo* c);

    cubo b(cubo* c);

    cubo m(cubo* c);

    cubo e(cubo* c);

    cubo s(cubo* c);

    cubo r1(cubo* c);

    cubo l1(cubo* c);

    cubo u1(cubo* c);

    9

  • 3 Digitalizzazione del contesto

    cubo d1(cubo* c);

    cubo f1(cubo* c);

    cubo b1(cubo* c);

    cubo m1(cubo* c);

    cubo e1(cubo* c);

    cubo s1(cubo* c);

    Segue un esempio dell'applicazione della funzione right :

    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

  • 3 Digitalizzazione del contesto

    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 8! 38 12! 212 5,19 1020. In realt non tutte queste congurazioni sonorealizzabili in quanto occorre tenere conto dei vincoli di costruzione del cubo, perci il numero

    esatto delle combinazioni 43.252.003.274.489.856.000 4,33 1019.

    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

    nodi da espandere; essa pari a f(n) = g(n) + h(n) dove:

    12

  • 4 Implementazione dell'algoritmo A*

    g(n) il costo del cammino dal nodo iniziale al nodo n;

    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 Scelta della funzione di valutazione

    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) una semplice valutazione del tipo: quanti pezzi

    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. Se si prende in considerazione un singolo spigolo, in cui uno dei due

    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*

    Figura 4.1. Allineamento dello spigolo rosso-bianco con il centro rosso.

    Figura 4.2. Allineamento dello spigolo rosso-bianco con il centro bianco.

    arancione, il che implica che, in questo caso, occorrono due mosse per poter allineare il rosso di

    uno spigolo al suo centro.

    Di seguito sono rappresentate tutte le possibili congurazioni di un singolo spigolo (rosso-

    bianco), il numero di mosse necessarie a posizionarlo e il calcolo eettuato. A partire da tali

    rappresentazioni stata ricavata l'euristica da noi utilizzata.

    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 numero di mosse totali per

    posizionare lo spigolo;

    Figura 4.3. Esempio dello spigolo rosso-bianco correttamente allineato.

    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.

    2 mosse: le congurazioni che, al minimo, si risolvono in due mosse si dividono in diverse

    categorie:

    1. In questo caso uno dei due colori dello spigolo giace sulla faccia corretta (d=0), men-

    tre 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 mosse. Inoltre, per discriminare alcuni casi particolari

    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-giallo-

    arancione, 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 mosse necessarie per

    poter posizionare lo spigolo;

    Figura 4.8. Esempio dello spigolo rosso-bianco che dista tre mosse dalla posizione corretta.

    4 mosse: in Figura 4.9 rappresenta l'ultima congurazione possibile ed quella in cui

    entrambi i colori dello spigolo giacciono su facce opposte. Questa l'unica congurazione

    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.

    La somma delle distanze dtot calcolate per ogni spigolo bianco fornisce la stima euristica h(n), la

    quale pu essere dunque sintetizzata come segue:

    1. individuare uno spigolo in cui uno dei due colori bianco;

    2. individuare il colore della faccia su cui giace il bianco individuato nel punto uno;

    3. calcolare la distanza tra la faccia su cui giace il bianco e la faccia bianca;

    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;

    5. sommare le distanze calcolate;

    6. se dtot = 1+1 e lo spigolo giace sulla linea bianco - colore_spigolo - giallo - colore_opposto_spigolo

    dtot = 1 + 1 + 1

    7. ripetere dal punto 1 per ogni spigolo bianco;

    8. calcolare h(n) come h(n) = dtot1 + dtot2 + dtot3 + dtot4.

    4.2 Riconoscimento delle simmetrie

    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

    equivalenti ma rappresentate dierentemente nelle sei matrici. Inoltre la posizione degli angoli

    ininuente. Ad esempio in Figura 4.10 sono mostrate quattro congurazioni completamente

    identiche dal punto di vista della croce.

    Le funzioni che nel programma C si occupano di individuare queste simmetrie sono:

    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

    L'algoritmo diviso nelle seguenti fasi:

    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

  • 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;if){

    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*.

    In Figura 5.1 mostrato un semplice esempio in cui la congurazione iniziale mischiata

    ruotando di 180 la faccia frontale. Questo fa si che la risoluzione della croce, applicando l'algoritmo

    descritto nei capitoli precedenti, presenti un albero come ragurato in Figura 5.1.

    Figura 5.1. Albero delle soluzioni.

    possibile notare come l'euristica suggerisca da subito le mosse che permettono la risoluzione nel

    minor numero di passi, indicando le mosse f e f ' come nodi pi promettenti.

    In Figura 5.2 mostrato l'output del programma C che implementa l'algoritmo.

    22

  • 5 Applicazione dell'algoritmo

    Figura 5.2. Output del programma rubik.c.

    Di seguito mostrata l'applicazione dell'algoritmo su un esempio pi complesso dove il cubo

    iniziale mischiato ragurato in Figura 5.3

    Figura 5.3. Congurazione 2D di un cubo a seguito di uno scramble.

    23

  • 5 Applicazione dell'algoritmo

    La soluzione fornita dal programma rappresentata in Figura 5.4.

    Figura 5.4. Output del programma rubik.c. a seguito di uno scramble.

    Si pu notare dalla stampa in Figura 5.4 che il numero di nodi memorizzati decisamente basso:

    209 contro i 648.232.975 che avrebbe richiesto una ricerca in ampiezza standard.

    Inne abbiamo analizzato le prestazioni dell'algoritmo facendogli eseguire 10.000 cubi comple-

    tamente mischiati ottenendo i risultati illustrati in Figura 5.5;

    Figura 5.5. Risultati su 10.000 cubi diversi.

    da cui si pu calcolare che mediamente l'algoritmo impiega 6,54 mosse per risolvere la croce bianca

    a partire da una qualsiasi congurazione.

    24

  • Capitolo 6

    Codice sorgente

    #include

    #include

    #include

    #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

    cubo l(cubo* c);

    cubo u(cubo* c);

    cubo d(cubo* c);

    cubo f(cubo* c);

    cubo b(cubo* c);

    cubo m(cubo* c);

    cubo e(cubo* c);

    cubo s(cubo* c);

    cubo r1(cubo* c);

    cubo l1(cubo* c);

    cubo u1(cubo* c);

    cubo d1(cubo* c);

    cubo f1(cubo* c);

    cubo b1(cubo* c);

    cubo m1(cubo* c);

    cubo e1(cubo* c);

    cubo s1(cubo* c);

    cubo esegui(cubo* c, char* m);

    void ruota(char m[3][3], char mCopia[3][3]);

    void ruota1(char m[3][3], char mCopia[3][3]);

    int hop(elementoLista* item);

    int h(cubo* c);

    int dist(char color1, char color2);

    char opposto(char color);

    void insert(cubo c, int f, elementoLista* padre, char* m);

    void append(elementoLista* item);

    elementoLista* elimina(elementoLista* testa, elementoLista* item);

    elementoLista* pop();

    void stampaListe();

    void stampa(cubo* c);

    void percorso(elementoLista* foglia, int n);

    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

  • 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

  • 6 Codice sorgente

    if(esisteInOpen == NULL && esisteInClosed == NULL){

    // printf("%s ",mossa[i]);

    insert(n[i], f_n[i], ptr, mossa[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);

    }

    }

    }

    }

    return 0;

    }

    //restituisce il numero di mosse necessarie per posizionare un singolo pezzo

    int valuta(char cBianco, char spigolo, char cSpigolo){

    int p;

    //distanza tra il centro del bianco e il centro bianco

    p = dist(cBianco, 'w');

    //distanza tra il centro dello spigolo e il centro di colore dello spigolo

    p = p + dist(spigolo, cSpigolo);

    if(p == 2){

    //il centro del bianco spigolo o OppostoSpigolo

    if(cBianco == spigolo || cBianco == opposto(spigolo)){

    //il centro di spigolo bianco o giallo?

    if(cSpigolo == 'w' || cSpigolo == 'y'){

    p++;

    }

    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

    if(c->D[0][1] == 'w'){//trovo il bianco

    d = d + valuta(c->D[1][1],c->F[2][1],c->F[1][1]);

    }

    if(c->D[1][0] == 'w'){//trovo il bianco

    d = d + valuta(c->D[1][1],c->L[2][1],c->L[1][1]);

    }

    if(c->D[1][2] == 'w'){//trovo il bianco

    d = d + valuta(c->D[1][1],c->R[2][1],c->R[1][1]);

    }

    if(c->D[2][1] == 'w'){//trovo il bianco

    d = d + valuta(c->D[1][1],c->B[2][1],c->B[1][1]);

    }

    return d;

    }

    int dist(char color1, char color2){

    if(color1 == color2)

    return 0;

    if(opposto(color1)==color2)

    return 2;

    return 1;

    }

    char opposto(char color){

    switch (color){

    case 'r':

    return 'o';

    case 'g':

    return 'b';

    case 'o':

    return 'r';

    case 'b':

    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;iR[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;iR[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;iR[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;iR[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

    cubo u(cubo* c){

    cubo copia;

    int i,j;

    for (i=0;iR[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->R[0][0];

    copia.F[0][1] = c->R[0][1];

    copia.F[0][2] = c->R[0][2];

    copia.R[0][0] = c->B[0][0];

    copia.R[0][1] = c->B[0][1];

    copia.R[0][2] = c->B[0][2];

    copia.L[0][0] = c->F[0][0];

    copia.L[0][1] = c->F[0][1];

    copia.L[0][2] = c->F[0][2];

    copia.B[0][0] = c->L[0][0];

    copia.B[0][1] = c->L[0][1];

    copia.B[0][2] = c->L[0][2];

    ruota(copia.U, c->U);

    return copia;

    }

    cubo u1(cubo* c){

    40

  • 6 Codice sorgente

    cubo copia;

    int i,j;

    for (i=0;iR[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;iR[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;iR[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

  • 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;iR[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;iR[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;iR[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;iR[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;iR[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;iR[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;iR[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;iR[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;iR[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

  • 6 Codice sorgente

    }

    printf("\t");

    for(j=0;jF[i][j]);

    }

    printf("\t");

    for(j=0;jR[i][j]);

    }

    printf("\t");

    for(j=0;jB[i][j]);

    }

    printf("\n");

    }

    printf("\n");

    for (i=0;ic=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

    elementoLista* elimina(elementoLista* testa, elementoLista* item){

    elementoLista* indice;

    elementoLista* before;

    indice=testa;

    if(item == NULL){ //elimina il primo elemento

    testa=testa->next;

    free(indice);

    return testa;

    }

    before=indice;

    if(item == indice){

    testa=testa->next;

    free(indice);

    return testa;

    }

    while(indice->next!=NULL){

    indice=indice->next;

    if(item == indice){

    before->next = indice->next;

    free(indice);

    return testa;

    }

    before=indice;

    }

    }

    void stampaListe(){ //debug

    elementoLista* indice = open;

    printf("----open----\n");

    while(indice != NULL){

    56

  • 6 Codice sorgente

    printf("mossa: %s\nvalore: %d\nindirizzo: %d\nnext: %d\npadre: %d\n

    configurazione:\n",indice->m,indice->f,indice,indice->next,indice->padre);

    stampa(&indice->c);

    indice = indice->next;

    }

    printf("------------\n");

    printf("----closed----\n");

    indice = closed;

    while(indice != NULL)

    {

    printf("mossa: %s\nvalore: %d\nindirizzo: %d\nnext: %d\npadre: %d\n

    configurazione:\n",indice->m,indice->f,indice,indice->next,indice->padre);

    stampa(&indice->c);

    indice = indice->next;

    }

    printf("--------------\n");

    }

    void percorso(elementoLista* foglia, int n){

    char temp[11][10];

    int j;

    int i = 0;

    while(foglia->padre != NULL){

    //stampa(&foglia->c);printf("\n");

    if(n == PESI)

    sprintf(temp[i], "[%s(%d)] ",foglia->m,foglia->f);

    else

    sprintf(temp[i], "[%s] ",foglia->m);

    foglia = foglia->padre;

    i++;

    }

    for(j= i-1; j >= 0; j--){

    printf("%s",temp[j]);

    if(j>0) printf(" --> ");

    }

    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

    if(c->R[0][1] == 'w'){//trovo il bianco

    if(c->R[1][1] == cBianco && c->U[1][2] == spigolo && c->U[1][1] == Cspigolo)

    return 1;

    }

    if(c->R[1][0] == 'w'){//trovo il bianco

    if(c->R[1][1] == cBianco && c->F[1][2] == spigolo && c->F[1][1] == Cspigolo)

    return 1;

    }

    if(c->R[1][2] == 'w'){//trovo il bianco

    if(c->R[1][1] == cBianco && c->B[1][0] == spigolo && c->B[1][1] == Cspigolo)

    return 1;

    }

    if(c->R[2][1] == 'w'){//trovo il bianco

    if(c->R[1][1] == cBianco && c->D[1][2] == spigolo && c->D[1][1] == Cspigolo)

    return 1;

    }

    if(c->B[0][1] == 'w'){//trovo il bianco

    if(c->B[1][1] == cBianco && c->U[0][1] == spigolo && c->U[1][1] == Cspigolo)

    return 1;

    }

    if(c->B[1][0] == 'w'){//trovo il bianco

    if(c->B[1][1] == cBianco && c->R[1][2] == spigolo && c->R[1][1] == Cspigolo)

    return 1;

    }

    if(c->B[1][2] == 'w'){//trovo il bianco

    if(c->B[1][1] == cBianco && c->L[1][0] == spigolo && c->L[1][1] == Cspigolo)

    return 1;

    }

    if(c->B[2][1] == 'w'){//trovo il bianco

    if(c->B[1][1] == cBianco && c->D[2][1] == spigolo && c->D[1][1] == Cspigolo)

    return 1;

    }

    if(c->L[0][1] == 'w'){//trovo il bianco

    if(c->L[1][1] == cBianco && c->U[1][0] == spigolo && c->U[1][1] == Cspigolo)

    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

    if(c->D[1][1] == cBianco && c->L[2][1] == spigolo && c->L[1][1] == Cspigolo)

    return 1;

    }

    if(c->D[1][2] == 'w'){//trovo il bianco

    if(c->D[1][1] == cBianco && c->R[2][1] == spigolo && c->R[1][1] == Cspigolo)

    return 1;

    }

    if(c->D[2][1] == 'w'){//trovo il bianco

    if(c->D[1][1] == cBianco && c->B[2][1] == spigolo && c->B[1][1] == Cspigolo)

    return 1;

    }

    return 0;

    }

    void append(elementoLista* item){

    elementoLista* indice = closed;

    if(closed == NULL){

    closed = item;

    return;

    }

    while(indice->next != NULL){

    indice = indice->next;

    }

    indice->next = item;

    }

    int hop(elementoLista* item){

    int i = 0;

    while(item != NULL){

    i++;

    item = item->padre;

    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

    Il cubo di RubikIl metodo FridrichDigitalizzazione del contestoCuboMosseScramble

    Implementazione dell'algoritmo A*Scelta della funzione di valutazioneRiconoscimento delle simmetrieImplementazione dell'algoritmo

    Applicazione dell'algoritmoCodice sorgenteBibliografia