//mingw32 sur W7 gcc 4.8.1 //gcc -Wall -Wextra -std=c99 -march=native -Ofast -flto -fomit-frame-pointer -pipe -o Solitaire.exe Solitaire.c && Solitaire.exe #include #include #include #define TRUE 1 #define FALSE 0 #define VIDE 0 #define BILLE 1 #define INTERDIT 2 // #define USESYM 1 //Utilisation des symétries #define INFINI 1 //Arrêt ou non dès qu'une solution est trouvée //#define PRINT 0 //Ecritures ou non Résultats //#define PRINTDEP 0//10000000000 unsigned long long DEPLACEMENTS=0; //Nombre total de déplacements unsigned long long MULTDEP=0; //Multiple de PRINTDEP déplacements unsigned long long SOL1=0; //Nombre de solutions avec le nb souhaité de billes restantes et la position finale souhaitée unsigned long long SOL2=0; //Nombre de solutions avec le nb souhaité de billes restantes sans la position finale souhaitée unsigned long long SYMETRIES=0; //Nombre de symétries #define DIM 7 //Dimension du plateau de jeu depuis l'indice 1 #define DIMm1 (DIM - 1) //Dimension du plateau de jeu depuis l'indice 0 #define DIMdemi 4 //Demi Dimension du plateau de jeu depuis l'indice 1 #define DIMdemim1 (DIMdemi-1) //Demi Dimension du plateau de jeu depuis l'indice 0 #define BILLESWIN 1 //Nombre souhaité de billes restantes #define LWIN 3 //Ligne finale souhaitée (si 1 bille restante) #define CWIN 3 //Colonne finale souhaitée (si 1 bille restante) /* // Solitaire Anglais //40 861 647 040 079 968 Solutions short P[DIM][DIM]={ {2,2,1,1,1,2,2}, {2,2,1,1,1,2,2}, {1,1,1,1,1,1,1}, {1,1,1,0,1,1,1}, {1,1,1,1,1,1,1}, {2,2,1,1,1,2,2}, {2,2,1,1,1,2,2} }; */ // Grande Pyramide short P[DIM][DIM]={ {2,2,0,0,0,2,2}, {2,2,0,1,0,2,2}, {0,0,1,1,1,0,0}, {0,1,1,1,1,1,0}, {1,1,1,1,1,1,1}, {2,2,0,0,0,2,2}, {2,2,0,0,0,2,2} }; /* // Petit Diamant short P[DIM][DIM]={ {2,2,0,0,0,2,2}, {2,2,0,1,0,2,2}, {0,0,1,1,1,0,0}, {0,1,1,0,1,1,0}, {0,0,1,1,1,0,0}, {2,2,0,1,0,2,2}, {2,2,0,0,0,2,2} }; // Fire Place short P[DIM][DIM]={ {2,2,1,1,1,2,2}, {2,2,1,1,1,2,2}, {0,0,1,1,1,0,0}, {0,0,1,0,1,0,0}, {0,0,0,0,0,0,0}, {2,2,0,0,0,2,2}, {2,2,0,0,0,2,2} }; // Cross short P[DIM][DIM]={ {2,2,0,0,0,2,2}, {2,2,0,1,0,2,2}, {0,0,1,1,1,0,0}, {0,0,0,1,0,0,0}, {0,0,0,1,0,0,0}, {2,2,0,0,0,2,2}, {2,2,0,0,0,2,2} }; // Plus short P[DIM][DIM]={ {2,2,0,0,0,2,2}, {2,2,0,1,0,2,2}, {0,0,0,1,0,0,0}, {0,1,1,1,1,1,0}, {0,0,0,1,0,0,0}, {2,2,0,1,0,2,2}, {2,2,0,0,0,2,2} }; */ //Affichage du plateau de jeu void Draw(short billes) { int i=0,j=0; for (i=0;i1;j--) {printf(" ");} for (j=0;j=PRINTDEP) { // DEPLACEMENTS=DEPLACEMENTS-PRINTDEP; // ++MULTDEP; // printf("%llu deplacements testes (%llu/%llu)\n",MULTDEP*PRINTDEP+DEPLACEMENTS,SOL1,SOL2); // fflush(stdout); // } // } //Recherche de Symétries if(0 || USESYM) { //Recherche d'une symétrie selon l'axe vertical symv=1; for(i=0;i-1 && !(symd1&&j==i) && P[i][j-1]==BILLE && P[i][j-2]==VIDE) {//Test déplacement à effectuer billes2=billes-1; ++DEPLACEMENTS; //Test si le coup est gagnant gagnant=0; if(billes2==BILLESWIN) { gagnant=2; ++SOL2; if(BILLESWIN==1 && LWIN==i && CWIN==j-2) { gagnant=1; ++SOL1; } //fin position souhaitée // if(PRINT) { // printf("%llu/%llu solution(s) trouvee(s) a %llu deplacements\n",SOL1,SOL2,DEPLACEMENTS); // //Déplacement // P[i][j]=VIDE; P[i][j-1]=VIDE; P[i][j-2]=BILLE; // //affichage // Draw(billes2); // //Retour au plateau précédent // P[i][j]=BILLE;P[i][j-1]=BILLE;P[i][j-2]=VIDE; // } //coup non gagnant }else{ //Déplacement P[i][j]=VIDE; P[i][j-1]=VIDE; P[i][j-2]=BILLE; //Nouveau plateau à jouer gagnant=Jouer(billes2); //affichage // if(PRINT && gagnant!=0) {Draw(billes2);} //Retour au plateau précédent P[i][j]=BILLE;P[i][j-1]=BILLE;P[i][j-2]=VIDE; } if(!INFINI&&gagnant==1) {return(gagnant);} //arrêt de la recherche } //fin Ouest //Sud if(i+2-1 && P[i-1][j]==BILLE && P[i-2][j]==VIDE) {//Test déplacement à effectuer billes2=billes-1; ++DEPLACEMENTS; //Test si le coup est gagnant gagnant=0; if(billes2==BILLESWIN) { gagnant=2; ++SOL2; if(BILLESWIN==1 && LWIN==i-2 && CWIN==j) { gagnant=1; ++SOL1; } //fin position souhaitée // if(PRINT) { // printf("%llu/%llu solution(s) trouvee(s) a %llu deplacements\n",SOL1,SOL2,DEPLACEMENTS); // //Déplacement // P[i][j]=VIDE; P[i-1][j]=VIDE; P[i-2][j]=BILLE; // //affichage // Draw(billes2); // // c=getchar(); // //Retour au plateau précédent // P[i][j]=BILLE;P[i-1][j]=BILLE;P[i-2][j]=VIDE; // } //coup non gagnant }else{ //Déplacement P[i][j]=VIDE; P[i-1][j]=VIDE; P[i-2][j]=BILLE; //Nouveau plateau à jouer gagnant=Jouer(billes2); //affichage // if(PRINT && gagnant!=0) {Draw(billes2);} //Retour au plateau précédent P[i][j]=BILLE;P[i-1][j]=BILLE;P[i-2][j]=VIDE; } if(!INFINI&&gagnant==1) {return(gagnant);} //arrêt de la recherche } //fin Nord ++balayees; if(balayees==billes) {return(gagnant);} //arrêt anticipé du balayage s'il ne reste plus de billes à balayer } //fin bille } //fin lignes } //fin colonnes return(gagnant); }//fin Jouer //Routine principale //int main(int argc, char *argv[]) { int main() { int i=0,j=0; short billes=0; //Nombre courant de billes short gagnant=0; //etat du coup courant SYSTEMTIME str_t; LARGE_INTEGER freq, time1,time2; double time; //Calcul nb de billes for (i=0;i