#include #include /* Numero massimo di tentativi */ #define MAX_ATTEMPT 500 /* Numero di colori del gioco */ #define NUM_COLORS 7 /* Numero di elementi della sequenza da indovinare */ #define NUM 4 /* Carattere che separa i vari colori nelle funzioni di stampa */ #define SEP '\t' /* Definisco il tipo di dato color */ typedef enum{ RED , WHITE , BLUE , GREEN , YELLOW , PURPLE , MAGENTA } color; /* Definisco il tipo comb come array di NUM elementi di tipo color */ typedef color comb[NUM]; /* La struttura attempt conterra' ogni tentativo, dove: c conterra' la combinazione di colori usata cor conterrĂ  il numero di elementi in posizione corretta qcor conterrĂ  il numero di elementi presenti ma non in posizione corretta */ typedef struct{ comb c; int cor , qcor; } attempt; /* VARIABILI GLOBALI */ /* vettore che contiene i tentativi */ attempt t[MAX_ATTEMPT]; /* numero di tentativi */ int n; /* codice che rappresenta la "combinazione massima" sara' composto da NUM ( NUM_COLORS - 1 ) es: se NUM = 4 e NUM_COLORS = 7 max_code sara' 6666 */ long max_code; /* FINE VARIABILI GLOBALI */ /* Prototipi delle funzioni utilizzate */ void printColor( color c ); void printComb( comb c ); int correct( comb c , comb d ); int quasiCorrect( comb c , comb d ); int isCompatible( comb c ); void findFirst( comb c ); long getMaxCode( void ); int power( int base , int exp ); int main( void ) { /* Ottengo max_code */ max_code = getMaxCode(); //printf("%ld\n", max_code); /* Ripeto per al massimo MAX_ATTEMPT volte la procedura per trovare la combinazione decisa dall'utente oppure fino a che non viene inserito il valore NUM come elementi corretti, il quale sta ad indicare che la sequenza e' stata trovata. */ n = 0; do { /* Trovo la prima combinazione compatibile con quelle inserite in precedenza */ findFirst( t[n].c ); /* La stampo in modo che l'utente possa inserire il numero dei valori corretti e di quelli quasi corretti */ printComb( t[n].c ); /* Chiedo all'utente di inserire il numero di elementi corretti */ scanf( "%d" , &t[n].cor ); /* Chiedo all'utente di inserire il numero di elementi quasi corretti */ scanf( "%d" , &t[n].qcor ); /* Incremento il numero di tentativi effettuati */ }while( n < MAX_ATTEMPT && t[ n++ ].cor != NUM ); printf("Ho vinto!\n"); return 0; } /* printColor Riceve un colore c e stampa una stringa che lo descrive Non ritorna nulla */ void printColor( color c ) { switch( c ) { case RED: printf("RED"); break; case WHITE: printf("WHITE"); break; case BLUE: printf("BLUE"); break; case GREEN: printf("GREEN"); break; case YELLOW: printf("YELLOW"); break; case PURPLE: printf("PURPLE"); break; case MAGENTA: printf("MAGENTA"); break; default: printf("ERRORE"); exit(-1); break; } } /* printComb Riceve una combinazione c e stampa i colori separati da un carattere SEP e infine va a capo. Non ritorna nulla. */ void printComb( comb c ) { int i = 0; printColor( c[i] ); for( i = 1 ; i < NUM ; ++i ) { putchar(SEP); printColor( c[i] ); } putchar('\n'); } /* correct Confronta due combinazioni c e d. Ritorna il numero di elementi in posizione corretta. */ int correct( comb c , comb d ) { int i , cont; for( cont = i = 0 ; i < NUM ; ++i ) { if( c[i] == d[i] ) ++cont; } return cont; } /* quasiCorrect Confronta due combinazioni c e d. Ritorna il numero di elementi in posizione quasi corretta. Ossia, una volta esclusi quelli gia' conteggiati come corretti, quelli di d presenti in c ma non nella stessa posizione */ int quasiCorrect( comb c , comb d ) { int i , j; int cont = 0; /* usati[NUM] terra' il segno di quanti e quali elementi abbiamo usato nei controlli */ int usati[NUM]; /* Trovo gli elementi gia' in posizione corretta e li escludo dai prossimi controlli segnandoli usati, altrimenti li segno come non usati. */ for( i = 0 ; i < NUM ; ++i ) { if( c[i] == d[i] ) usati[i] = 1; else usati[i] = 0; } /* Controllo gli elementi di d con quelli di c escludendo quelli gia' usati. Una volta che incontro un elemento di d in una posizione diversa dentro c incremento il contatore e segno l'elemento come usato. Poi passo all'elemento seguente di c. */ for( i = 0 ; i < NUM ; ++i ) if( c[i] != d[i] ) for( j = 0 ; j < NUM ; ++j ) if( c[j] == d[i] && !usati[j] ) { usati[j] = 1; ++cont; break; } return cont; } /* isCompatible Riceve una combinazione c e la confronta con tutte quelle gia' tentate. Utilizza le variabili globali n e t[MAX_ATTEMPT] che contengono tutti i tentativi gia' usati. Se la combinazione e' compatibile con quelle gia' inserite, ossia se ha lo stesso numero di elementi corretti e quasi corretti ritorna 1 altrimenti ritorna 0 */ int isCompatible( comb c ) { int i; for( i = 0 ; i < n ; ++i ) { if( correct( t[i].c , c ) != t[i].cor ) return 0; if( quasiCorrect( t[i].c , c ) != t[i].qcor ) return 0; } return 1; } /* Usata per impostare la variabile globale max_code Il suo significato e' spiegato alla dichiarazione di max_code */ long getMaxCode( void ) { int i , j; long max = 0; int factor; for( i = 0 ; i < NUM ; ++i ) { max += ( NUM_COLORS - 1 ) * power( 10 , i ); } return max; } /* Ritorna base alla exp */ int power( int base , int exp ) { int i; int pow = 1; for( i = 0 ; i < exp ; ++i ) pow *= base; return pow; } /* Trova la prima combinazione compatibile con quelle gia' inserite Imposta c come questa combinazione */ void findFirst( comb c ) { int x; int i; for( x = 0 ; x <= max_code; ++x ) { for( i = 0 ; i < NUM ; ++i ) { c[i] = ( x / power( 10 , i ) ) % NUM_COLORS; } if( isCompatible( c ) ) return; } printf("Hai sbagliato a inserire i numeri o stai barando...\n"); printf("Termino.\n"); exit(1); }