Accueil > > > KAKURO
KAKURO
Information sur la source
Description
Voila, je bosse sur un projet pour mes cours de programmation. Le premier projet consistait en une grille statique realisée correctement. Pour le second projet, mon prof veut un tableau dynamique. Je crois que j'en suis pas loin mais ca plante pour l'affichage et paf l'erreur habituelle "Erreur de segmentation". Vous pouvez tester le code en mettant en commentaire de la ligne 82 et la ligne 100 et la miracle ca marche. Mais ca ne m'arrange pas du tout puisque mes cases sont vides :(. Je sais que j'ai defini ici ma taille du tableau par nx,ny mais je dois en fait recuperer la taille en lisant la grille du kakuro, et la aussi je seche, j'utilise un "sscanf" pour lire dans le fichier, il me recupère bien la valeur mais ne l'attribue pas. Dans un premier temps, je cherche uniquement a resoudre mon problème d'affichage car après vérification, la memoire est belle est bien allouée. Bon, ne jugez pas mon code lol, je suis novice en programmation et je trouve que le prof a fait un peu fort de demander un kakuro pour des premières années, mais je debrouille meme si parfois je pourrais faire un meilleur codage. Je vous remercie a tous d'avance. Je joinds le zip comme ca vous avez une grille, donc quand vous jouer, vous tapez 1 puis 1 et encore 1 car c'est la grille11.txt
Source
- #include<stdio.h>
- #include<stdlib.h>
- #include"couleurs.h"
-
- typedef struct element
- {
- char type;
- int val[2];
- int attrib;
- }grille;
-
- /* Explication de la fonction INIT */
- /* Fonction servant a initialiser le tableau pour eviter des problemes d'allocation */
- /* de valeur dans les cases, pouvant causer des erreurs */
-
- void init(int nx,int ny,grille **tab)
- {
- int x,y;
- for(x=0;x<nx;x++)
- {
- for(y=0;y<ny;y++)
- {
- tab[x][y].type='Z';
- tab[x][y].val[0]=0;
- tab[x][y].val[1]=0;
- tab[x][y].attrib=-1;
- }
- }
- }
-
- /* Explication de la fonction AFFICHAGE */
- /* En fonction du type attribue a chaque case, un affichage se distinque par le switch */
- /* Le "default" equivalant aux cases blanches non-codees */
-
- void affichage(int nx,int ny,grille **tab)
- {
- int x,y,x2;
- printf("\033[H\033[2J");
- for(x=0;x<nx+1;x++)
- {
- couleur("31");
- printf("+-----");
- if(x==nx)
- {
- printf("+\n");
- }
- }
- for(x=0;x<nx;x++)
- {
- if(x==0)
- {
- printf("| ");
- }
- printf("| %2d ",x);
- if(x==nx-1)
- {
- printf("|\n");
- }
- }
- for(x=0;x<nx;x++)
- {
- for(x2=0;x2<nx+1;x2++)
- {
- couleur("31");
- printf("+-----");
- if(x2==nx)
- {
- printf("+\n");
- }
- }
- for(y=0;y<ny;y++)
- {
- if(y==0)
- {
- couleur("31");
- printf("| %2d ",x);
- couleur("0");
- }
- couleur("31");
- printf("|");
- couleur("0");
- switch (tab[x][y].type)
- {
- case 'D' : couleur("36");
- printf("%2d\\%2d",tab[x][y].val[1],tab[x][y].val[0]);
- couleur("0");
- break;
- case 'N' : couleur("32");
- printf("*****");
- couleur("0");
- break;
- case 'P' : couleur("33");
- printf(" %2d ",tab[x][y].val[0]);
- couleur("0");
- break;
- case 'B' : printf(" %2d ",tab[x][y].val[0]);
- break;
- default : printf(" ");
- break;
- }
- }
- couleur("31");
- printf("|\n");
- couleur("0");
- }
- for(x=0;x<nx+1;x++)
- {
- couleur("31");
- printf("+-----");
- if(x==nx)
- {
- printf("+\n");
- }
- couleur("0");
- }
- }
-
- /* Explication de la fonction LOAD */
- /* Fonction de lecture du fichier */
- /* Lecture du fichier a partir de la commande FGETS */
- /* Lecture ligne par ligne */
- /* En fonction du premier caractere, je peux definir le masque pour la commande SSCANF et */
- /* Ainsi recupere les differentes valeurs correspondant au type de la case, on rempli la structure */
- /* et on termine en fermant le fichier */
-
- void chargement(long int nx,long int ny,grille **tab,char fichier[20])
- {
- char type,temp[14];
- int ligne,colonne,valeur1,valeur2,i,j;
- int compteur=0,drap=0;
- FILE *jeu;
- jeu=fopen(fichier,"r");
- if(jeu==NULL)
- {
- printf(" \n Fichier non charge \n");
- }
- else
- {
- printf(" Fichier %s charge \n",fichier);
-
- /* Fonction de lecture du fichier. */
- /* Attrib est specifique de ce que je peux faire, */
- /* 0 affecte aux cases definitions, impossible de faire une action dessus. */
- /* 1 affecte aux cases noires, impossible de faire une action dessus. */
- /* -1 affecte aux cases blanches(Z), possibilite d'agir dessus */
- /* 3 affecte aux cases predifinies, case remplie par le joueur, impossible d'agir dessus sauf en supprimant la valeur, */
- /* et reaffectant la case en case blanche(Z) voir plus bas dans supprimvaleur */
-
- while(!feof(jeu))
- {
- fgets(temp,14,jeu);
- if(drap==0)
- {
- tab=(grille **)malloc(nx * sizeof(grille *));
- if(tab==NULL)
- {
- printf("\n Echec lors de l'allocation memoire!!!");
- }
- printf("La memoire allouee est de %d ",sizeof(grille*));
- for(i=0;i<nx;i++)
- {
- tab[i] = (grille *)malloc(ny * sizeof(grille));
- printf("La memoire allouee est de %d\n",sizeof(grille));
- if (tab[i] == NULL)
- {
- for (j=0;j<ny;j++)
- {
- printf("%d",j);
- free(tab[j]);
- printf("\n Echec lors de l'allocation memoire!!!");
- }
- }
- }
- drap=1;
- }
- if(temp[0]=='D')
- {
- sscanf(temp,"%c %d %d %d %d",&type,&ligne,&colonne,&valeur1,&valeur2);
- tab [ligne][colonne].attrib=0;
- tab [ligne][colonne].type=type;
- tab [ligne][colonne].val[0]=valeur1;
- tab [ligne][colonne].val[1]=valeur2;
- }
- if(temp[0]=='N')
- {
- sscanf(temp,"%c %d %d",&type,&ligne,&colonne);
- tab [ligne][colonne].type=type;
- tab [ligne][colonne].attrib=1;
- }
- if(temp[0]=='B')
- {
- tab[ligne][colonne].attrib=-1;
- }
- if(temp[0]=='P')
- {
- sscanf(temp,"%c %d %d %d",&type,&ligne,&colonne,&valeur1);
- tab [ligne][colonne].type=type;
- tab [ligne][colonne].val[0]=valeur1;
- tab [ligne][colonne].attrib=3;
- }
- compteur++;
- }
- fclose(jeu);
- }
-
- }
-
- /* Explication de la fonction SAUVEGARDE */
- /* Fonction de sauvegarde du jeu */
- /* On ouvre un fichier en ecriture, et ecrase l'ancien s'il y en a deja un nomme comme cela */
- /* et on enregistre les donnees dedans */
- /* Enregistrement case par case dans un fichier texte au meme format que les grilles de depart */
-
- void sauvegarde(int nx,int ny,grille **tab,char fichier[20])
- {
- int x,y;
- FILE *savegame;
- char nom_fic[20];
- printf("Veuillez entrer le nom du fichier : ");
- fgets(nom_fic,20,savegame);
- savegame=fopen(nom_fic,"w");
- if(savegame==NULL)
- {
- printf("Fichier non sauvegarde");
- }
- else
- {
- for(x=0;x<nx;x++)
- {
- for(y=0;y<ny;y++)
- {
- if(tab[x][y].type=='D')
- {
- fprintf(savegame,"%c %d %d %d %d\n",tab[x][y].type,x,y,tab[x][y].val[0],tab[x][y].val[1]);
- }
- if(tab[x][y].type=='B'||tab[x][y].type=='N')
- {
- fprintf(savegame,"%c %d %d\n",tab[x][y].type,x,y);
- }
- if(tab[x][y].type=='P')
- {
- fprintf(savegame,"%c %d %d %d\n",tab[x][y].type,x,y,tab[x][y].val[0]);
- }
- }
- }
- }
- }
-
- /* Explication de la fonction VERIFREGLE*/
- /* Fonction de verification pour les lignes horizontales */
- /* Premierement, on cherche la valeur de la case definition correspondant a la ligne */
- /* Dont la valeur fait partie, de la on sait d'ou notre verification doit partir (valeur DEPART) */
- /* Ensuite, on demarre du DEPART, on teste si la valeur se trouve deja sur la ligne */
- /* Si elle se trouve sur la ligne, on retourne directement 0 */
- /* Si la valeur ne se trouve pas sur la ligne, on verifie que la case est soit Blanche, soit Predefinie */
- /* Si elle l'est, alors on fait la somme de la valeur actuelle avec les valeurs precedentes. */
- /* Si a un moment donne, la colonne est differente de DEPART et que les cases sont differentes de B ou P */
- /* On a une case vide en plus de celle que l'on veut attribuer et donc cela ne sert a rien de tester la somme */
- /* En fin de fonction, on verifie les deux cas possibles et on retourne 1 si c'est possible ou 0 si ca ne l'est pas */
-
- int verifregle(int nx,int ny,grille **tab,int ligne,int colonne,int valeur)
- {
- int test=0,co,somme=valeur;
- int depart,def,echec=1;
- co=colonne;
- while(test==0)
- {
- if(tab[ligne][co-1].type=='D')
- {
- def=tab[ligne][co-1].val[0];
- depart=co;
- test=1;
- }
- co--;
- }
- for(depart=depart;depart<nx&&tab[ligne][depart].type!='N'&&tab[ligne][depart].type!='D';depart++)
- {
- if(valeur!=tab[ligne][depart].val[0])
- {
- if(tab[ligne][depart].type=='P'||tab[ligne][depart].type=='B')
- {
- somme=somme+tab[ligne][depart].val[0];
- }
- else if(colonne!=depart)
- echec=0;
- }
- else
- {
- return 0;
- }
- }
- if( (echec==1&&somme==def)||(echec==0&&somme<def))
- return 1;
- else
- return 0;
- }
-
- /* Explication de la fonctoion VERIFREGLE2 */
- /* Fonction de verification pour les lignes verticales */
- /* Premierement, on cherche la valeur de la case definition correspondant a la colonne */
- /* Dont la valeur fait paretie, de la sait d'ou notre verification doit partir (valeur DEPART) */
- /* Ensuite, on demarre du DEPART, on teste si la valeur se trouve deja sur la colonne */
- /* Si elle se trouve sur la ligben on retourne directement 0 */
- /* Si la valeur ne se trouve pas sur la colonne, on verifie que la case est soit Blanche, soit Predefinie */
- /* Si elle l'est, alors on fait la somme de la valeur actuelle avec les valeurs precedentes. */
- /* Si a un moment donne, la ligne est differente de DEPART et que les cases sont differentes de B ou de P */
- /* On a une case videen plus de celle que l'on veut attribuer et donc cela ne sert a rien de tester la somme */
- /* En fin de fonction, on verifie les deux cas possibles et on retourne 1 si c'est possible ou 0 si ca ne l'est pas */
-
- int verifregle2(int nx,int ny,grille **tab,int ligne,int colonne,int valeur)
- {
- int test=0;
- int somme=valeur;
- int def,echec=1,depart,li;
- li=ligne;
- while(test==0)
- {
- if(tab[li-1][colonne].type=='D')
- {
- def=tab[li-1][colonne].val[1];
- depart=li;
- test=1;
- }
- li--;
- }
- for(depart=depart;depart<ny&&tab[depart][colonne].type!='N'&&tab[depart][colonne].type!='D';depart++)
- {
- if(valeur!=tab[depart][colonne].val[0])
- {
- if(tab[depart][colonne].type=='P'||tab[depart][colonne].type=='B')
- somme=somme+tab[depart][colonne].val[0];
- else if(ligne!=depart)
- echec=0;
- }
- else
- {
- return 0;
- }
- }
- if((echec==1&&somme==def)||(echec==0&&somme<def))
- return 1;
- else
- return 0;
- }
-
- /* Explication de BACKTRACKING */
- /* Ne fonctionne pas correctement, plante sur la grille 32,34,35 */
-
- int backtracking(int nx,int ny,grille **tab, int lig, int colo)
- {
- int i=1;
- if(colo==ny)
- {
- lig=lig+1;
- colo=0;
- }
- while(tab[lig][colo].type=='D'||tab[lig][colo].type=='N'||tab[lig][colo].type=='P') /* Test pour voir le type de ligne */
- {
- colo++; /* Tant que c'est un des types test, on avance dans la colonne */
- if(colo==ny) /* Si on arrive en fin de colonne, on avance d'une ligne et on reviens a la case 0 de la colonne */
- {
- lig=lig+1;
- colo=0;
- }
- }
- if((colo==0&&lig==nx)||(colo==ny&&lig==nx)) /*Sert a verifier que je suis a la fin du tableau*/
- return 1;
- else
- {
- while(i<10) /* Test tant que i est plus que 10 */
- /* Si les 2 regles sont verifiees, on change le type de */
- /* en case Blanche, on affecte la valeur de i a la case */
- /* Ensuite on teste ce que la fonction et la colonne */
- /* renvoie */
- /* Sinon on reaffecte un type vide a la case ainsi que la */
- /* valeur 0 */
- /* On incremente le compteur et on recommence */
- {
- if(verifregle(nx,ny,tab,lig, colo,i)==1 && verifregle2(nx,ny,tab,lig, colo,i)==1)
- {
- tab[lig][colo].type='B';
- tab[lig][colo].val[0]=i;
- if(backtracking(nx,ny,tab, lig,colo+1)==1)
- return 1;
- }
- else
- {
- tab[lig][colo].type='Z';
- tab[lig][colo].val[0]=0;
- }
- i++;
- tab[lig][colo].type='Z';
- tab[lig][colo].val[0]=0;
- }
- return 0;
- }
- }
- void resolutionautomatique(int nx,int ny,grille **tab)
- {
- int colo=0,lig=0;
- /*fonction qui me permet de trouver le depart */
- if( backtracking(ny,nx,tab, colo, lig)==1 )
- printf("Solution possible\n");
- else
- printf("solution impossible\n");
- }
-
- /* Explication de la fonction JEU */
- /* Introduction des coordonnees de la case par le joueur */
- /* Fonction de test de valeur introduite par le joueur */
- /* Test de la case pour savoir si celle ci est libre ( type Z ) ou si elle correspond a un autre type */
- /* Si la case est libre, introduction de la valeur par le joueur puis test de la valeur entree avec les */
- /* fonction VERIFREGLE et VERIFREGLE2 */
- /* Si test ok, la valeur est encodee, sinon on refais la boucle */
-
- void jeu(int nx,int ny,grille **tab)
- {
- int ligne,colonne,valeur,test;
- do
- {
- printf("Veuillez entrer le numero de la ligne : \n");
- scanf("%d",&ligne);
- printf("Veuillez entrer le numero de la colonne : \n");
- scanf("%d",&colonne);
- if(tab[ligne][colonne].attrib==0)
- {
- test=0;
- affichage(nx,ny,tab);
- couleur("1;31");
- printf("Ceci est une case definition \n");
- couleur("0");
- }
- if(tab[ligne][colonne].attrib==1)
- {
- test=0;
- affichage(nx,ny,tab);
- couleur("1;31");
- printf("Ceci est une case noire \n");
- couleur("0");
- }
- if(tab[ligne][colonne].attrib==3)
- {
- test=0;
- affichage(nx,ny,tab);
- couleur("1;31");
- printf("Cette case a deja ete remplie par le joueur \n");
- couleur("0");
-
- }
- if(tab[ligne][colonne].attrib==-1)
- {
- printf("Veuillez introduire votre valeur comprise entre 1 et 9 inclus : \n");
- scanf("%d",&valeur);
- if(valeur>0&&valeur<10)
- {
- if(verifregle(nx,ny,tab,ligne,colonne,valeur)==0||verifregle2(nx,ny,tab,ligne,colonne,valeur)==0)
- {
- affichage(nx,ny,tab);
- couleur("1;31");
- printf("Cette valeur se trouve deja sur la ligne et/ou la colonne, ou la somme n'est pas correcte \n");
- couleur("0");
- test=0;
- }
- else
- {
- tab[ligne][colonne].type='P';
- tab[ligne][colonne].val[0]=valeur;
- tab[ligne][colonne].attrib=3;
- test=1;
- }
- }
- else
- {
- couleur("1;31");
- printf("La valeur introduire n'est pas comprise dans la fourchette\n");
- printf("Veuillez recommencer\n");
- couleur("0");
- }
- }
- }
- while(test==0);
- }
-
- /* Explication de la fonction SUPPRIMVALEUR */
- /* Fonction pour supprimer la valeur d'une case */
- /* Meme test que pour la fonction JEU, pour ne pas effacer n'importe quoi */
- /* Si case ok, la valeur est supprimee et on repasse la case en type Z pour pouvoir reecrire dedans par la suite */
- /* J'etais d'abord passe par une fonction pour modifier la valeur plutot que de la supprimer, mais cela pose */
- /* des problemes au niveau des regles de verification */
-
- void supprimvaleur(int nx,int ny,grille **tab)
- {
- int ligne,colonne,valeur,test;
- do
- {
- printf("Veuillez entrer le numero de la ligne : \n");
- scanf("%d",&ligne);
- printf("Veuillez entrer le numero de la colonne : \n");
- scanf("%d",&colonne);
- if(tab[ligne][colonne].attrib==-1)
- {
- affichage(nx,ny,tab);
- printf("Il n'y a rien a supprimer ici ici \n" );
- test=0;
- }
- if(tab[ligne][colonne].attrib==0)
- {
- affichage(nx,ny,tab);
- printf("Ceci est une case definition \n");
- test=0;
- }
- if(tab[ligne][colonne].attrib==1)
- {
- affichage(nx,ny,tab);
- printf("Ceci est une case noire \n");
- test=0;
- }
- if(tab[ligne][colonne].attrib==3)
- {
- tab[ligne][colonne].type='Z';
- tab[ligne][colonne].val[0]=valeur;
- tab[ligne][colonne].attrib=-1;
- printf("La valeur a ete supprimee \n");
- test=1;
- }
- }
- while(test==0);
-
- }
-
-
-
- /* Explication de la fonction AIDE */
- /* Fonction pour l'aide sur les valeurs possibles que peut prendre une case */
- /* Introduction par le joueur des coordonnees de la case */
- /* Test des valeurs de 1 a 9 par les fonctions VERIFREGLE et VERIFREGLE2 */
- /* Les valeurs retournees sont celles qui sont possibles d'introduire */
-
- void aide(int nx,int ny,grille **tab, int ligne, int colonne)
- {
- int i;
- printf("Solution possible : ");
- for(i=1;i<10;i++)
- {
- if(verifregle(nx,ny,tab,ligne,colonne,i)==1&&verifregle2(nx,ny,tab,ligne,colonne,i)==1)
- {
- printf("%d est une valeur possible pour cette case \n", i);
- }
- }
- printf("\n");
- }
-
- /* Explication de la fonction MENU2 */
- /* Menu de JEU avec la grille */
- /* 1. Entrer une valeur, permet d'entrer une valeur en appelant la fonction JEU */
- /* 2. Supprimer une valeur, supprimer la valeur d'une case en appelant la fonction SUPPRIMVALEUR */
- /* 3. Demander de l'aide, introduction des coordonnees par le joueur puis appel de la fonction AIDE */
- /* 4. Resolution automatique, appel de la fonction resolutionautomatique ( BACKTRACKING ) */
- /* 5. Sauvegarde de la partie, enregistre la partie dans un fichier txt en appelant la fonction SAUVEGARDE */
- /* 6. Retour, retour au menu principal */
-
- void menu2(int nx,int ny,grille **tab)
- {
- int ligne,colonne;
- char choix2;
- char fichier[20]="";
- do
- {
- affichage(nx,ny,tab);
- couleur("1;34");
- printf("***** MENU DU JEU *****\n");
- couleur("0");
- couleur("31");
- printf("-----------------------\n");
- couleur("0");
- printf("Que voulez-vous faire ?\n"
- "1.Entrer une valeur\n"
- "2.Supprimer une valeur\n"
- "3.Demander de l'aide\n"
- "4.Resolution automatique\n"
- "5.Sauvegarde de la partie\n"
- "6.Retour\n");
- do
- choix2=getchar();
- while((int)choix2<49||(int)choix2>55);
- switch ((int)choix2)
- {
- case 49 : jeu(nx,ny,tab);
- break;
- case 50 : supprimvaleur(nx,ny,tab);
- break;
- case 51 : printf("Entrez le numero de la ligne : \n");
- scanf("%d",&ligne);
- printf("Entrez le numero de la colonne : \n");
- scanf("%d",&colonne);
- aide(nx,ny,tab,ligne,colonne);
- break;
- case 52 : resolutionautomatique(nx,ny,tab);
- break;
- case 53 : sauvegarde(nx,ny,tab,fichier);
- break;
- }
- }
- while((int)choix2!=54);
- }
-
- /* Explication de la fonction MENU3 */
- /* Menu de selection de difficulte de la grille */
- /* 3 difficultes sont proposees */
- /* Utilisation de la commande SPRINTF pour concatener les valeurs introduites par le joueur */
-
- void menu3(int nx,int ny,grille **tab)
- {
- int choix3,choix4;
- char fichier[20]="";
- do
- {
- couleur("1;34");
- printf("Selectionnez le niveau de difficulte\n");
- couleur("0");
- printf("-------------1.Facile---------------\n"
- "-------------2.Moyen----------------\n"
- "-------------3.Expert---------------\n"
- "-------------4.Retour---------------\n");
- scanf("%d",&choix3);
- }
- while(choix3<1 || choix3>4);
- if((int)choix3!=4)
- {
- do
- {
- printf("Selectionnez votre grille de 1 a 5 : \n");
- scanf("%d",&choix4);
- }
- while(choix4<1 || choix4>5);
- sprintf(fichier,"grille%d%d.txt",choix3,choix4);
- chargement(nx,ny,tab,fichier);
- menu2(nx,ny,tab);
- }
- }
-
- /* Explication de la fonction MAIN */
- /* Menu de depart */
-
- int main()
- {
- long int nx=9;
- long int ny=9;
- grille **tab;
- char choix,fichier [20];
- printf("\033[H\033[2J");
- couleur("1;34");
- printf( "*****************************************************************************************************************\n"
- "*****************************************************************************************************************\n"
- "** **\n"
- "* *\n"
- "* *\n"
- "* *\n"
- "* *\n"
- "* *\n"
- "* BIENVENUE DANS LE JEU KAKURO *\n"
- "* *\n"
- "* *\n"
- "* *\n"
- "** **\n"
- "****************************************************************************************************************\n"
- "****************************************************************************************************************\n");
- printf("\n");
- printf(" Tapez 1 pour Jouer\n "
- " Tapez 2 pour charger une partie sauvegardee\n "
- " Tapez 3 pour quitter le jeu\n");
- do
- {
- choix=getchar();
- while((int)choix<49 || (int)choix>52);
- switch((int)choix)
- {
- case 49 : menu3(nx,ny,tab);
- break;
- case 50 : printf("Entrer le nom du fichier en specifiant son extension (.TXT) : \n");
- scanf("%s",fichier);
- chargement(nx,ny,tab,fichier);
- menu2(nx,ny,tab);
- break;
- }
- }
- while((int)choix!=51);
- return 0;
- }
#include<stdio.h>
#include<stdlib.h>
#include"couleurs.h"
typedef struct element
{
char type;
int val[2];
int attrib;
}grille;
/* Explication de la fonction INIT */
/* Fonction servant a initialiser le tableau pour eviter des problemes d'allocation */
/* de valeur dans les cases, pouvant causer des erreurs */
void init(int nx,int ny,grille **tab)
{
int x,y;
for(x=0;x<nx;x++)
{
for(y=0;y<ny;y++)
{
tab[x][y].type='Z';
tab[x][y].val[0]=0;
tab[x][y].val[1]=0;
tab[x][y].attrib=-1;
}
}
}
/* Explication de la fonction AFFICHAGE */
/* En fonction du type attribue a chaque case, un affichage se distinque par le switch */
/* Le "default" equivalant aux cases blanches non-codees */
void affichage(int nx,int ny,grille **tab)
{
int x,y,x2;
printf("\033[H\033[2J");
for(x=0;x<nx+1;x++)
{
couleur("31");
printf("+-----");
if(x==nx)
{
printf("+\n");
}
}
for(x=0;x<nx;x++)
{
if(x==0)
{
printf("| ");
}
printf("| %2d ",x);
if(x==nx-1)
{
printf("|\n");
}
}
for(x=0;x<nx;x++)
{
for(x2=0;x2<nx+1;x2++)
{
couleur("31");
printf("+-----");
if(x2==nx)
{
printf("+\n");
}
}
for(y=0;y<ny;y++)
{
if(y==0)
{
couleur("31");
printf("| %2d ",x);
couleur("0");
}
couleur("31");
printf("|");
couleur("0");
switch (tab[x][y].type)
{
case 'D' : couleur("36");
printf("%2d\\%2d",tab[x][y].val[1],tab[x][y].val[0]);
couleur("0");
break;
case 'N' : couleur("32");
printf("*****");
couleur("0");
break;
case 'P' : couleur("33");
printf(" %2d ",tab[x][y].val[0]);
couleur("0");
break;
case 'B' : printf(" %2d ",tab[x][y].val[0]);
break;
default : printf(" ");
break;
}
}
couleur("31");
printf("|\n");
couleur("0");
}
for(x=0;x<nx+1;x++)
{
couleur("31");
printf("+-----");
if(x==nx)
{
printf("+\n");
}
couleur("0");
}
}
/* Explication de la fonction LOAD */
/* Fonction de lecture du fichier */
/* Lecture du fichier a partir de la commande FGETS */
/* Lecture ligne par ligne */
/* En fonction du premier caractere, je peux definir le masque pour la commande SSCANF et */
/* Ainsi recupere les differentes valeurs correspondant au type de la case, on rempli la structure */
/* et on termine en fermant le fichier */
void chargement(long int nx,long int ny,grille **tab,char fichier[20])
{
char type,temp[14];
int ligne,colonne,valeur1,valeur2,i,j;
int compteur=0,drap=0;
FILE *jeu;
jeu=fopen(fichier,"r");
if(jeu==NULL)
{
printf(" \n Fichier non charge \n");
}
else
{
printf(" Fichier %s charge \n",fichier);
/* Fonction de lecture du fichier. */
/* Attrib est specifique de ce que je peux faire, */
/* 0 affecte aux cases definitions, impossible de faire une action dessus. */
/* 1 affecte aux cases noires, impossible de faire une action dessus. */
/* -1 affecte aux cases blanches(Z), possibilite d'agir dessus */
/* 3 affecte aux cases predifinies, case remplie par le joueur, impossible d'agir dessus sauf en supprimant la valeur, */
/* et reaffectant la case en case blanche(Z) voir plus bas dans supprimvaleur */
while(!feof(jeu))
{
fgets(temp,14,jeu);
if(drap==0)
{
tab=(grille **)malloc(nx * sizeof(grille *));
if(tab==NULL)
{
printf("\n Echec lors de l'allocation memoire!!!");
}
printf("La memoire allouee est de %d ",sizeof(grille*));
for(i=0;i<nx;i++)
{
tab[i] = (grille *)malloc(ny * sizeof(grille));
printf("La memoire allouee est de %d\n",sizeof(grille));
if (tab[i] == NULL)
{
for (j=0;j<ny;j++)
{
printf("%d",j);
free(tab[j]);
printf("\n Echec lors de l'allocation memoire!!!");
}
}
}
drap=1;
}
if(temp[0]=='D')
{
sscanf(temp,"%c %d %d %d %d",&type,&ligne,&colonne,&valeur1,&valeur2);
tab [ligne][colonne].attrib=0;
tab [ligne][colonne].type=type;
tab [ligne][colonne].val[0]=valeur1;
tab [ligne][colonne].val[1]=valeur2;
}
if(temp[0]=='N')
{
sscanf(temp,"%c %d %d",&type,&ligne,&colonne);
tab [ligne][colonne].type=type;
tab [ligne][colonne].attrib=1;
}
if(temp[0]=='B')
{
tab[ligne][colonne].attrib=-1;
}
if(temp[0]=='P')
{
sscanf(temp,"%c %d %d %d",&type,&ligne,&colonne,&valeur1);
tab [ligne][colonne].type=type;
tab [ligne][colonne].val[0]=valeur1;
tab [ligne][colonne].attrib=3;
}
compteur++;
}
fclose(jeu);
}
}
/* Explication de la fonction SAUVEGARDE */
/* Fonction de sauvegarde du jeu */
/* On ouvre un fichier en ecriture, et ecrase l'ancien s'il y en a deja un nomme comme cela */
/* et on enregistre les donnees dedans */
/* Enregistrement case par case dans un fichier texte au meme format que les grilles de depart */
void sauvegarde(int nx,int ny,grille **tab,char fichier[20])
{
int x,y;
FILE *savegame;
char nom_fic[20];
printf("Veuillez entrer le nom du fichier : ");
fgets(nom_fic,20,savegame);
savegame=fopen(nom_fic,"w");
if(savegame==NULL)
{
printf("Fichier non sauvegarde");
}
else
{
for(x=0;x<nx;x++)
{
for(y=0;y<ny;y++)
{
if(tab[x][y].type=='D')
{
fprintf(savegame,"%c %d %d %d %d\n",tab[x][y].type,x,y,tab[x][y].val[0],tab[x][y].val[1]);
}
if(tab[x][y].type=='B'||tab[x][y].type=='N')
{
fprintf(savegame,"%c %d %d\n",tab[x][y].type,x,y);
}
if(tab[x][y].type=='P')
{
fprintf(savegame,"%c %d %d %d\n",tab[x][y].type,x,y,tab[x][y].val[0]);
}
}
}
}
}
/* Explication de la fonction VERIFREGLE*/
/* Fonction de verification pour les lignes horizontales */
/* Premierement, on cherche la valeur de la case definition correspondant a la ligne */
/* Dont la valeur fait partie, de la on sait d'ou notre verification doit partir (valeur DEPART) */
/* Ensuite, on demarre du DEPART, on teste si la valeur se trouve deja sur la ligne */
/* Si elle se trouve sur la ligne, on retourne directement 0 */
/* Si la valeur ne se trouve pas sur la ligne, on verifie que la case est soit Blanche, soit Predefinie */
/* Si elle l'est, alors on fait la somme de la valeur actuelle avec les valeurs precedentes. */
/* Si a un moment donne, la colonne est differente de DEPART et que les cases sont differentes de B ou P */
/* On a une case vide en plus de celle que l'on veut attribuer et donc cela ne sert a rien de tester la somme */
/* En fin de fonction, on verifie les deux cas possibles et on retourne 1 si c'est possible ou 0 si ca ne l'est pas */
int verifregle(int nx,int ny,grille **tab,int ligne,int colonne,int valeur)
{
int test=0,co,somme=valeur;
int depart,def,echec=1;
co=colonne;
while(test==0)
{
if(tab[ligne][co-1].type=='D')
{
def=tab[ligne][co-1].val[0];
depart=co;
test=1;
}
co--;
}
for(depart=depart;depart<nx&&tab[ligne][depart].type!='N'&&tab[ligne][depart].type!='D';depart++)
{
if(valeur!=tab[ligne][depart].val[0])
{
if(tab[ligne][depart].type=='P'||tab[ligne][depart].type=='B')
{
somme=somme+tab[ligne][depart].val[0];
}
else if(colonne!=depart)
echec=0;
}
else
{
return 0;
}
}
if( (echec==1&&somme==def)||(echec==0&&somme<def))
return 1;
else
return 0;
}
/* Explication de la fonctoion VERIFREGLE2 */
/* Fonction de verification pour les lignes verticales */
/* Premierement, on cherche la valeur de la case definition correspondant a la colonne */
/* Dont la valeur fait paretie, de la sait d'ou notre verification doit partir (valeur DEPART) */
/* Ensuite, on demarre du DEPART, on teste si la valeur se trouve deja sur la colonne */
/* Si elle se trouve sur la ligben on retourne directement 0 */
/* Si la valeur ne se trouve pas sur la colonne, on verifie que la case est soit Blanche, soit Predefinie */
/* Si elle l'est, alors on fait la somme de la valeur actuelle avec les valeurs precedentes. */
/* Si a un moment donne, la ligne est differente de DEPART et que les cases sont differentes de B ou de P */
/* On a une case videen plus de celle que l'on veut attribuer et donc cela ne sert a rien de tester la somme */
/* En fin de fonction, on verifie les deux cas possibles et on retourne 1 si c'est possible ou 0 si ca ne l'est pas */
int verifregle2(int nx,int ny,grille **tab,int ligne,int colonne,int valeur)
{
int test=0;
int somme=valeur;
int def,echec=1,depart,li;
li=ligne;
while(test==0)
{
if(tab[li-1][colonne].type=='D')
{
def=tab[li-1][colonne].val[1];
depart=li;
test=1;
}
li--;
}
for(depart=depart;depart<ny&&tab[depart][colonne].type!='N'&&tab[depart][colonne].type!='D';depart++)
{
if(valeur!=tab[depart][colonne].val[0])
{
if(tab[depart][colonne].type=='P'||tab[depart][colonne].type=='B')
somme=somme+tab[depart][colonne].val[0];
else if(ligne!=depart)
echec=0;
}
else
{
return 0;
}
}
if((echec==1&&somme==def)||(echec==0&&somme<def))
return 1;
else
return 0;
}
/* Explication de BACKTRACKING */
/* Ne fonctionne pas correctement, plante sur la grille 32,34,35 */
int backtracking(int nx,int ny,grille **tab, int lig, int colo)
{
int i=1;
if(colo==ny)
{
lig=lig+1;
colo=0;
}
while(tab[lig][colo].type=='D'||tab[lig][colo].type=='N'||tab[lig][colo].type=='P') /* Test pour voir le type de ligne */
{
colo++; /* Tant que c'est un des types test, on avance dans la colonne */
if(colo==ny) /* Si on arrive en fin de colonne, on avance d'une ligne et on reviens a la case 0 de la colonne */
{
lig=lig+1;
colo=0;
}
}
if((colo==0&&lig==nx)||(colo==ny&&lig==nx)) /*Sert a verifier que je suis a la fin du tableau*/
return 1;
else
{
while(i<10) /* Test tant que i est plus que 10 */
/* Si les 2 regles sont verifiees, on change le type de */
/* en case Blanche, on affecte la valeur de i a la case */
/* Ensuite on teste ce que la fonction et la colonne */
/* renvoie */
/* Sinon on reaffecte un type vide a la case ainsi que la */
/* valeur 0 */
/* On incremente le compteur et on recommence */
{
if(verifregle(nx,ny,tab,lig, colo,i)==1 && verifregle2(nx,ny,tab,lig, colo,i)==1)
{
tab[lig][colo].type='B';
tab[lig][colo].val[0]=i;
if(backtracking(nx,ny,tab, lig,colo+1)==1)
return 1;
}
else
{
tab[lig][colo].type='Z';
tab[lig][colo].val[0]=0;
}
i++;
tab[lig][colo].type='Z';
tab[lig][colo].val[0]=0;
}
return 0;
}
}
void resolutionautomatique(int nx,int ny,grille **tab)
{
int colo=0,lig=0;
/*fonction qui me permet de trouver le depart */
if( backtracking(ny,nx,tab, colo, lig)==1 )
printf("Solution possible\n");
else
printf("solution impossible\n");
}
/* Explication de la fonction JEU */
/* Introduction des coordonnees de la case par le joueur */
/* Fonction de test de valeur introduite par le joueur */
/* Test de la case pour savoir si celle ci est libre ( type Z ) ou si elle correspond a un autre type */
/* Si la case est libre, introduction de la valeur par le joueur puis test de la valeur entree avec les */
/* fonction VERIFREGLE et VERIFREGLE2 */
/* Si test ok, la valeur est encodee, sinon on refais la boucle */
void jeu(int nx,int ny,grille **tab)
{
int ligne,colonne,valeur,test;
do
{
printf("Veuillez entrer le numero de la ligne : \n");
scanf("%d",&ligne);
printf("Veuillez entrer le numero de la colonne : \n");
scanf("%d",&colonne);
if(tab[ligne][colonne].attrib==0)
{
test=0;
affichage(nx,ny,tab);
couleur("1;31");
printf("Ceci est une case definition \n");
couleur("0");
}
if(tab[ligne][colonne].attrib==1)
{
test=0;
affichage(nx,ny,tab);
couleur("1;31");
printf("Ceci est une case noire \n");
couleur("0");
}
if(tab[ligne][colonne].attrib==3)
{
test=0;
affichage(nx,ny,tab);
couleur("1;31");
printf("Cette case a deja ete remplie par le joueur \n");
couleur("0");
}
if(tab[ligne][colonne].attrib==-1)
{
printf("Veuillez introduire votre valeur comprise entre 1 et 9 inclus : \n");
scanf("%d",&valeur);
if(valeur>0&&valeur<10)
{
if(verifregle(nx,ny,tab,ligne,colonne,valeur)==0||verifregle2(nx,ny,tab,ligne,colonne,valeur)==0)
{
affichage(nx,ny,tab);
couleur("1;31");
printf("Cette valeur se trouve deja sur la ligne et/ou la colonne, ou la somme n'est pas correcte \n");
couleur("0");
test=0;
}
else
{
tab[ligne][colonne].type='P';
tab[ligne][colonne].val[0]=valeur;
tab[ligne][colonne].attrib=3;
test=1;
}
}
else
{
couleur("1;31");
printf("La valeur introduire n'est pas comprise dans la fourchette\n");
printf("Veuillez recommencer\n");
couleur("0");
}
}
}
while(test==0);
}
/* Explication de la fonction SUPPRIMVALEUR */
/* Fonction pour supprimer la valeur d'une case */
/* Meme test que pour la fonction JEU, pour ne pas effacer n'importe quoi */
/* Si case ok, la valeur est supprimee et on repasse la case en type Z pour pouvoir reecrire dedans par la suite */
/* J'etais d'abord passe par une fonction pour modifier la valeur plutot que de la supprimer, mais cela pose */
/* des problemes au niveau des regles de verification */
void supprimvaleur(int nx,int ny,grille **tab)
{
int ligne,colonne,valeur,test;
do
{
printf("Veuillez entrer le numero de la ligne : \n");
scanf("%d",&ligne);
printf("Veuillez entrer le numero de la colonne : \n");
scanf("%d",&colonne);
if(tab[ligne][colonne].attrib==-1)
{
affichage(nx,ny,tab);
printf("Il n'y a rien a supprimer ici ici \n" );
test=0;
}
if(tab[ligne][colonne].attrib==0)
{
affichage(nx,ny,tab);
printf("Ceci est une case definition \n");
test=0;
}
if(tab[ligne][colonne].attrib==1)
{
affichage(nx,ny,tab);
printf("Ceci est une case noire \n");
test=0;
}
if(tab[ligne][colonne].attrib==3)
{
tab[ligne][colonne].type='Z';
tab[ligne][colonne].val[0]=valeur;
tab[ligne][colonne].attrib=-1;
printf("La valeur a ete supprimee \n");
test=1;
}
}
while(test==0);
}
/* Explication de la fonction AIDE */
/* Fonction pour l'aide sur les valeurs possibles que peut prendre une case */
/* Introduction par le joueur des coordonnees de la case */
/* Test des valeurs de 1 a 9 par les fonctions VERIFREGLE et VERIFREGLE2 */
/* Les valeurs retournees sont celles qui sont possibles d'introduire */
void aide(int nx,int ny,grille **tab, int ligne, int colonne)
{
int i;
printf("Solution possible : ");
for(i=1;i<10;i++)
{
if(verifregle(nx,ny,tab,ligne,colonne,i)==1&&verifregle2(nx,ny,tab,ligne,colonne,i)==1)
{
printf("%d est une valeur possible pour cette case \n", i);
}
}
printf("\n");
}
/* Explication de la fonction MENU2 */
/* Menu de JEU avec la grille */
/* 1. Entrer une valeur, permet d'entrer une valeur en appelant la fonction JEU */
/* 2. Supprimer une valeur, supprimer la valeur d'une case en appelant la fonction SUPPRIMVALEUR */
/* 3. Demander de l'aide, introduction des coordonnees par le joueur puis appel de la fonction AIDE */
/* 4. Resolution automatique, appel de la fonction resolutionautomatique ( BACKTRACKING ) */
/* 5. Sauvegarde de la partie, enregistre la partie dans un fichier txt en appelant la fonction SAUVEGARDE */
/* 6. Retour, retour au menu principal */
void menu2(int nx,int ny,grille **tab)
{
int ligne,colonne;
char choix2;
char fichier[20]="";
do
{
affichage(nx,ny,tab);
couleur("1;34");
printf("***** MENU DU JEU *****\n");
couleur("0");
couleur("31");
printf("-----------------------\n");
couleur("0");
printf("Que voulez-vous faire ?\n"
"1.Entrer une valeur\n"
"2.Supprimer une valeur\n"
"3.Demander de l'aide\n"
"4.Resolution automatique\n"
"5.Sauvegarde de la partie\n"
"6.Retour\n");
do
choix2=getchar();
while((int)choix2<49||(int)choix2>55);
switch ((int)choix2)
{
case 49 : jeu(nx,ny,tab);
break;
case 50 : supprimvaleur(nx,ny,tab);
break;
case 51 : printf("Entrez le numero de la ligne : \n");
scanf("%d",&ligne);
printf("Entrez le numero de la colonne : \n");
scanf("%d",&colonne);
aide(nx,ny,tab,ligne,colonne);
break;
case 52 : resolutionautomatique(nx,ny,tab);
break;
case 53 : sauvegarde(nx,ny,tab,fichier);
break;
}
}
while((int)choix2!=54);
}
/* Explication de la fonction MENU3 */
/* Menu de selection de difficulte de la grille */
/* 3 difficultes sont proposees */
/* Utilisation de la commande SPRINTF pour concatener les valeurs introduites par le joueur */
void menu3(int nx,int ny,grille **tab)
{
int choix3,choix4;
char fichier[20]="";
do
{
couleur("1;34");
printf("Selectionnez le niveau de difficulte\n");
couleur("0");
printf("-------------1.Facile---------------\n"
"-------------2.Moyen----------------\n"
"-------------3.Expert---------------\n"
"-------------4.Retour---------------\n");
scanf("%d",&choix3);
}
while(choix3<1 || choix3>4);
if((int)choix3!=4)
{
do
{
printf("Selectionnez votre grille de 1 a 5 : \n");
scanf("%d",&choix4);
}
while(choix4<1 || choix4>5);
sprintf(fichier,"grille%d%d.txt",choix3,choix4);
chargement(nx,ny,tab,fichier);
menu2(nx,ny,tab);
}
}
/* Explication de la fonction MAIN */
/* Menu de depart */
int main()
{
long int nx=9;
long int ny=9;
grille **tab;
char choix,fichier [20];
printf("\033[H\033[2J");
couleur("1;34");
printf( "*****************************************************************************************************************\n"
"*****************************************************************************************************************\n"
"** **\n"
"* *\n"
"* *\n"
"* *\n"
"* *\n"
"* *\n"
"* BIENVENUE DANS LE JEU KAKURO *\n"
"* *\n"
"* *\n"
"* *\n"
"** **\n"
"****************************************************************************************************************\n"
"****************************************************************************************************************\n");
printf("\n");
printf(" Tapez 1 pour Jouer\n "
" Tapez 2 pour charger une partie sauvegardee\n "
" Tapez 3 pour quitter le jeu\n");
do
{
choix=getchar();
while((int)choix<49 || (int)choix>52);
switch((int)choix)
{
case 49 : menu3(nx,ny,tab);
break;
case 50 : printf("Entrer le nom du fichier en specifiant son extension (.TXT) : \n");
scanf("%s",fichier);
chargement(nx,ny,tab,fichier);
menu2(nx,ny,tab);
break;
}
}
while((int)choix!=51);
return 0;
}
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
jeu des chiffres exact [ par mounmoun45 ]
salut a tous, Je souhaitreais réaliser un jeu des chiffres "exact" en utilisant les piles ou les arbres de langage c ,et j'ai besoin de votre aide.l
Problème de son [ par splifo ]
Bonjour,Je voudrais arrêter le son d'un jeu video à partir d'un programme externe sans arrêter le son de l'ordinateur.J'ai pensé à récupérer la variab
recherche mot dans un boggle [ par raziel50 ]
slt comment est il possible de chercher une chaine de caracteres dans une grille du jeu boggle en c++.j'ai charge un dictionnaire et je voudrais pouvo
Jeu de plateforme : balle [ par ketinu ]
Bonjour à tous,J'ai un projet à effectuer pour les cours. Il consiste à créer un jeu, le jeu que je souhaite créer est un jeu de plateforme : une ball
Jeu du chiffre croisé [ par benhmida ]
bonjour mes amis. je suis nouveau, je viens de m"inscrire dans votre site de codes sources et j'espère que ça va bcp m'aider. je vous remerc
gestion des timers [ par malbackt ]
Bonjour à tous; J'ai un jeu réalisé en opengl, son but est de parcourir une labyrinthe et de tuer tous les monstres qu'y existent;le problème c'est q
jeu SDL [ par uzixucf ]
bonjour tout le monde, je suis nouveau d'entre vousje suis entrain de developper un jeu en SDL (language C) qui se présente ainsi
Code d'initialisation de DirectX 9 [ par cathylarainette ]
J'ai telechargé un jeu de motos(SBK08) et tout s'instale sauf directX 9.Je cherche partout comment initialiser directX 9.Mon jeu ne peut pas s'ouvrir.
|
Derniers Blogs
[RIA SERVICES] INCLUDE ET DOMAINDATASOURCE[RIA SERVICES] INCLUDE ET DOMAINDATASOURCE par Audrey
Dans un de mes articles précédents , j'avais parlé des DomainDataSource avec RIA Services dans le cas d'une interface Maître - Détail. Dans le même principe, je vais parler d'une autre manière de mettre en forme ce cas d'interface avec RIA Services. Et po...
Cliquez pour lire la suite de l'article par Audrey ZUNE : VERSION ZUNE SOFTWARE V 4.2 ET LA SOCIALISATIONZUNE : VERSION ZUNE SOFTWARE V 4.2 ET LA SOCIALISATION par ROMELARD Fabrice
Une des nouveautés de la version V 3.0 était l'apparition de l'onglet Social qui ne fonctionnait que si le MarketPlace était activé sur son poste. Cela limitait donc son intérêt, car hors du cadre commercial USA-CANADA, peu de monde trouva...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice PRATIQUE DE SILVERLIGHT PAR ERIC AMBROSIPRATIQUE DE SILVERLIGHT PAR ERIC AMBROSI par MPOWARE
Je viens de finir la lecture du dernier livre d'
Eric Ambrosi
éditions PEARSON
Son livre donne une approche pratique de Silverlight qui sera aussi bien comprise par le développeur que par le designeur.
Tous les aspects du développement RIA sont abor...
Cliquez pour lire la suite de l'article par MPOWARE APPRENDRE à DéVELOPPER POUR LES MOBILES AVEC LA NOUVELLE GéNéRATION .NETAPPRENDRE à DéVELOPPER POUR LES MOBILES AVEC LA NOUVELLE GéNéRATION .NET par odewit
2 déclinaisons de Silverlight et 2 déclinaisons de Mono permettent dorénavant (ou permettront prochainement) de développer des applications .NET mobiles pour les principales plates-formes du marché :
Silverlight pour Symbian, basé sur Silverlight 2...
Cliquez pour lire la suite de l'article par odewit ZUNE : NOUVELLE VERSION DU ZUNE SOFTWARE - V 4.2ZUNE : NOUVELLE VERSION DU ZUNE SOFTWARE - V 4.2 par ROMELARD Fabrice
Avec la dernière génération du lecteur MP3 de Microsoft, le ZUNE HD, Microsoft a publié une nouvelle version du logiciel pour PC. Ainsi, je me suis décidé à installer celle-ci sur mon Tablet PC ACER, comme toujours le logiciel est donc tél...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
Academy System (10.9.4.0)ACADEMY SYSTEM (10.9.4.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Xilisoft Convertisseur Vidéo Ultimate (5.1.39.0305)XILISOFT CONVERTISSEUR VIDéO ULTIMATE (5.1.39.0305)Xilisoft Convertisseur Vidéo Ultimate est un outil puissant de conversion vidéo, facile à utilise... Cliquez pour télécharger Xilisoft Convertisseur Vidéo Ultimate Xilisoft DVD Ripper Ultimate (5.0.64.0304)XILISOFT DVD RIPPER ULTIMATE (5.0.64.0304)Xilisoft DVD Ripper Ultimate est un logiciel excellent pour copier et convertir DVD vers presque ... Cliquez pour télécharger Xilisoft DVD Ripper Ultimate Rigs of Rods (63.3)RIGS OF RODS (63.3)c'est un jeu de multi-simulation camions,autobus voitures, avions, bateaux, hélicoptère avec défo... Cliquez pour télécharger Rigs of Rods
|