Demineur en langage C
Fermé
midnightweb
Messages postés
10
Date d'inscription
mardi 16 décembre 2008
Statut
Membre
Dernière intervention
22 mars 2011
-
8 juin 2009 à 17:28
midnightweb - 14 juin 2009 à 21:14
midnightweb - 14 juin 2009 à 21:14
A voir également:
- Algorithme démineur inversé
- Annuaire inversé - Guide
- Ecran inversé - Guide
- Slash inversé ✓ - Forum MacOS
- Comment taper le anti slash? ✓ - Forum Programmation
- Annuaire inversé suisse ✓ - Forum Mobile
7 réponses
midnightweb
Messages postés
10
Date d'inscription
mardi 16 décembre 2008
Statut
Membre
Dernière intervention
22 mars 2011
2
8 juin 2009 à 19:07
8 juin 2009 à 19:07
#include <stdio.h> #include <stdlib.h> #include <time.h> char JEU[10][10];//grille de jeu int i,j;//i les lignes, j les colonnes char MINES[10][10];//la grille avec les mines int N;//Nombre de mines autour //////////////////////////////////////// // FONCTION AFFICHER LA GRILLE DE JEU // //////////////////////////////////////// void AfficheJeu() { printf(" | 1 2 3 4 5 6 7 8 9 10\n"); printf("___|______________________________\n"); for(i=0;i<10;i++) { if(i<9) printf(" %d | ",i+1); else printf("%d | ",i+1); for(j=0;j<10;j++) { printf("%c ",JEU[i][j]); } printf("\n"); } } ///////////////////////////////////////////// // FONCTION CALCULER LE NB DE MINES AUTOUR // ///////////////////////////////////////////// int NbMinesAutour() { N=0; if(MINES[i][j]=='M') { printf("Vous avez perdu !!!\n\n"); printf(" | 1 2 3 4 5 6 7 8 9 10\n"); printf("___|______________________________\n"); for(i=0;i<10;i++) { if(i<9) printf(" %d | ",i+1); else printf("%d | ",i+1); for(j=0;j<10;j++) printf("%c ",MINES[i][j]); printf("\n"); } } else { if (i==0) { if (j==0) { if(MINES[i][j+1]=='M') N++; if(MINES[i+1][j]=='M') N++; if(MINES[i+1][j+1]=='M') N++; } else { if(j==10) { if(MINES[i][j-1]=='M') N++; if(MINES[i+1][j-1]=='M') N++; if(MINES[i+1][j]='M') N++; } else { if(MINES[i][j-1]=='M') N++; if(MINES[i][j+1]=='M') N++; if(MINES[i+1][j-1]=='M') N++; if(MINES[i+1][j]=='M') N++; if(MINES[i+1][j+1]=='M') N++; } } } else { if (i==10) { if (j==0) { if(MINES[i-1][j]=='M') N++; if(MINES[i-1][j+1]=='M') N++; if(MINES[i][j+1]=='M') N++; } else { if(j==10) { if(MINES[i-1][j-1]=='M') N++; if(MINES[i-1][j]=='M') N++; if(MINES[i][j-1]=='M') N++; } else { if(MINES[i-1][j-1]=='M') N++; if(MINES[i-1][j]=='M') N++; if(MINES[i-1][j+1]=='M') N++; if(MINES[i][j-1]=='M') N++; if(MINES[i][j+1]=='M') N++; } } } else { if(MINES[i-1][j-1]=='M') N++; if(MINES[i-1][j]=='M') N++; if(MINES[i-1][j+1]=='M') N++; if(MINES[i][j-1]=='M') N++; if(MINES[i][j+1]=='M') N++; if(MINES[i+1][j-1]=='M') N++; if(MINES[i+1][j]=='M') N++; if(MINES[i+1][j+1]=='M') N++; } } return(N); } } int main() { int NbMines;//le nombre de mines choisi par le joueur char NbMinesTxt[2]; // nombre de mines aux alentours int CompteMines;//compteur de mines int choix;//le choix effectué par le joueur pour découvrir ou placer un drapeau int c;//le compteur de la boucle srand(time(NULL)); //Afficher le début du jeu printf(" ________________________________\n"); printf("| |\n"); printf("| Jeu du demineur |\n"); printf("|________________________________|\n\n"); //initialisation des deux grilles for(i=0;i<10;i++) { for(j=0;j<10;j++) { JEU[i][j]=' ';//' 'implique case cachée MINES[i][j]='0'; } } //demander à l'utilisateur de choisir un nombre de mines do { printf("\nCombien de mines voulez-vous ?\n\n"); scanf("%d",&NbMines); } while(NbMines>=30); printf("D'accord, vous avez choisi de jouer avec %d mines\n\n",NbMines); ////////////////////////////// // Initialisation des mines // ////////////////////////////// for (CompteMines=0;CompteMines<NbMines;CompteMines++) { i=rand()%10;//on choisit la ligne de manière aléatoire j=rand()%10;//on choisit la colonne de manière aléatoire if(MINES[i][j]=='0')//On vérifie que la case est libre { MINES[i][j]='M';//on place un M pour indiquer qu'il y a une mine } else { NbMines++;//Sinon, il y a déjà un M et il faut faire un tour de plus } } //Pour vérifier on affiche la grille des mines printf("Voici la grille des mines :\n"); for(i=0;i<10;i++) { for(j=0;j<10;j++) { printf("%c ",MINES[i][j]); } printf("\n"); } //////////////////////////// // Démarrage de la partie // //////////////////////////// //On affiche le jeu au joueur printf("\n\nVoici votre grille : A vous de jouer !\n\n"); printf(" | 1 2 3 4 5 6 7 8 9 10\n"); printf("___|______________________________\n"); for(i=0;i<10;i++) { if(i<9) printf(" %d | ",i+1); else printf("%d | ",i+1); for(j=0;j<10;j++) { JEU[i][j]='-';//'-'implique case cachée printf("%c ",JEU[i][j]); } printf("\n"); } //On demande au joueur de choisir une case //la case est définie par sa ligne i et sa colonne j for(c=0;c<(100-NbMines);c++) { printf("\n\nVeuillez entrer la case choisie (numero de ligne [espace] numero de colonne):\t"); scanf("%d %d",&i,&j); printf("Vous avez choisi la case (%d,%d).\ Que voulez-vous faire ?\n",i,j); i=i-1; j=j-1; // Demander au joueur ce qu'il veut faire printf("\t1. Decouvrir une case\n"); printf("\t2. Placer un drapeau"); do { printf("\t\tVotre choix : "); scanf("%d",&choix); } while (choix<0 || choix>2); // Choix : dévoiler une case ou placer un drapeau switch (choix) { case 1 : //fonction devoile mines autour NbMinesAutour(); if (N!=0)//Il y a des mines autour { printf("%d\n\n",N); sprintf(NbMinesTxt,"%d",N); JEU[i][j]=NbMinesTxt[0]; } else//Il n'y a pas de mines autour { JEU[i][j]='0'; printf("%c",JEU[i][j]); } break; case 2 : JEU[i][j]='D'; break; } //AFFICHER LA GRILLE AfficheJeu(); } printf("\n\n\t\tBravo vous avez gagné !"); system("pause"); return 0; }
Question:
Alors qui se propose de déboguer ce programme de 280 lignes non indenté ???
Réflexions:
Pas de candidat ???
Bizarre autant qu'étrange... ;-))
Comment cela peut-il se faire ???
Alors qui se propose de déboguer ce programme de 280 lignes non indenté ???
Réflexions:
Pas de candidat ???
Bizarre autant qu'étrange... ;-))
Comment cela peut-il se faire ???
midnightweb
Messages postés
10
Date d'inscription
mardi 16 décembre 2008
Statut
Membre
Dernière intervention
22 mars 2011
2
8 juin 2009 à 19:05
8 juin 2009 à 19:05
Ok, Ok,
Je revoie ma copie
Sauf que mon programme est correctement indenté. Quand je publie le post, tout se réaligne !
Je revoie ma copie
Sauf que mon programme est correctement indenté. Quand je publie le post, tout se réaligne !
C'est un peu long à lire;;; et je n'ai pas tout lu ;-)
Somme toute, j'ai envie de faire une remarque: pourquoi choisir de mettre '0' et 'M' pour remplir le tableau des mines? Je pense que c'est maladroit; j'ai bien compris que ce choix a été fait pour un affichage facile, mais c'est le seul gain que l'on ait alors que c'est la boucle qui revient le moins souvent.
Mettre 0 (zéro) et un (un) est beaucoup plus facile pour les tests car 0 est faux et 1 est vrai.
Un exemple de simplification:
Bonne continuation.
Somme toute, j'ai envie de faire une remarque: pourquoi choisir de mettre '0' et 'M' pour remplir le tableau des mines? Je pense que c'est maladroit; j'ai bien compris que ce choix a été fait pour un affichage facile, mais c'est le seul gain que l'on ait alors que c'est la boucle qui revient le moins souvent.
Mettre 0 (zéro) et un (un) est beaucoup plus facile pour les tests car 0 est faux et 1 est vrai.
Un exemple de simplification:
if(j==10) { if(MINES[i][j-1]=='M') N++; if(MINES[i+1][j-1]=='M') N++; if(MINES[i+1][j]='M') N++; } else { if(MINES[i][j-1]=='M') N++; if(MINES[i][j+1]=='M') N++; if(MINES[i+1][j-1]=='M') N++; if(MINES[i+1][j]=='M') N++; if(MINES[i+1][j+1]=='M') N++; }devient:
if (j == 10) { if (MINES[i][j-1] || MINES[i+1][j-1] || MINES[i+1][j]) N++; } else { if (MINES[i][j-1] || MINES[i][j+1] || MINES[i+1][j-1] || MINES[i+1][j] || MINES[i+1][j+1]) N++; }D'autre part, par convention les variables sont notées en minuscule.
Bonne continuation.
J'ai essayé la simplification que tu m'as proposé mais ça ne marche pas ! le compteur ne s'incrémente qu'une fois
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Exact, je n'avais pas bien lu...
J'ai choisi de travailler sur plusieurs tableaux et d'agrandir les tableaux en ayant un bord qui permet de ne pas faire de test de débordement d'index. Voici une adaptation de ton programme, il n'est pas parfait dans sa conclusion (on peut faire d'autres choix), mais il fonctionne bien:
Bonne continuation.
J'ai choisi de travailler sur plusieurs tableaux et d'agrandir les tableaux en ayant un bord qui permet de ne pas faire de test de débordement d'index. Voici une adaptation de ton programme, il n'est pas parfait dans sa conclusion (on peut faire d'autres choix), mais il fonctionne bien:
#include <stdio.h> #include <stdlib.h> #include <time.h> #define TAILLE 10 #define NB_MINES_MIN 10 char jeu [TAILLE+2][TAILLE+2]; // Grille de jeu char mines [TAILLE+2][TAILLE+2]; // Grille avec les mines char autour[TAILLE+2][TAILLE+2]; // Grille donnant le nbre de mines autour char temp [TAILLE+2][TAILLE+2]; // Grille temporaire pour le calcul de la case jouée ////////////////////////////// // FONCTION INITIALISATION /// ////////////////////////////// void init() { int i, j; for (i=0; i<TAILLE+2; i++) for (j=0; j<TAILLE+2; j++) { jeu [i][j] = '-'; // ' 'implique case cachée mines[i][j] = 0; autour[i][j] = 0; } } /////////////////////////////// // FONCTION PLACER LES MINES // /////////////////////////////// void placeMines(int nbMines) { int i, j; while(nbMines) { int i = rand()%TAILLE + 1; // On choisit la ligne de manière aléatoire int j = rand()%TAILLE + 1; // On choisit la colonne de manière aléatoire if (!mines[i][j]) // On vérifie ie que la case est libre { mines[i][j] = 1; // On place un 1 pour indiquer qu'il y a une mine nbMines--; // Une mine de moins à placer printf("\nmine: lig=%d, col=%d", i, j); } } for (i=1; i<=TAILLE; i++) // Met le tableau 'autour' à jour for (j=1; j<=TAILLE; j++) autour[i][j] = mines[i-1][j-1] + mines[i-1][j] + mines[i-1][j+1] + mines[i ][j-1] + mines[i ][j+1] + mines[i+1][j-1] + mines[i+1][j] + mines[i+1][j+1]; } //////////////////////////////////////// // FONCTION AFFICHER LA GRILLE DE JEU // //////////////////////////////////////// void afficheJeu() { int i, j; printf("\n\n"); printf(" | 1 2 3 4 5 6 7 8 9 10\n"); printf("___|______________________________\n"); for (i=1 ;i<=TAILLE; i++) { if (i < 10) printf(" %d | ", i); else printf("%d | ", i); for (j=1; j<=TAILLE; j++) printf("%c ", jeu[i][j]); printf("\n"); } } ////////////////////////////////////////////////////////// // FONCTION JOUER dévoiler une case ou placer un drapeau// ////////////////////////////////////////////////////////// int jouer(int choix, int lig, int col) { int i, j, m, n; switch (choix) { case 1 : for (i=0; i<TAILLE+2; i++) for (j=0; j<TAILLE+2; j++) temp[i][j] = 0; if (mines[lig][col]) return 1; // Perdu, on est tombé sur une mine case 0 : temp[lig][col] = autour[lig][col] + '0'; for (i=1; i<=TAILLE; i++) for (j=1; j<=TAILLE; j++) if (temp[i][j] == '0') { temp[i][j] = ' '; for (m=i-1; m<=i+1; m++) for (n=j-1; n<=j+1; n++) if ( !((m == i) && (n == j)) && (m) && (m <= TAILLE) && (n) && (n <= TAILLE) && (!temp[m][n]) ) // Pour éviter de retester la même case et les bords jouer(0, m, n); } for (i=1; i<=TAILLE; i++) // Recopie de temp dans jeu for (j=1; j<=TAILLE; j++) if (temp[i][j]) if (jeu[i][j] == '-') jeu[i][j] = temp[i][j]; break; case 2 : jeu[lig][col] = 'D'; break; } return 0; } /////////////////////////////////////////////////////////////// // FONCTION CHOISIR On demande au joueur de choisir une case // /////////////////////////////////////////////////////////////// int choisir(int *lig, int* col) { int choix; printf("\n\nVeuillez entrer la case choisie (numero de ligne [espace] numero de colonne):\t"); scanf("%d %d", lig, col); printf("Vous avez choisi la case (%d, %d).: Que voulez-vous faire ?\n", *lig, *col); printf("\t1. Decouvrir une case\n"); printf("\t2. Placer un drapeau"); do { printf("\t\tVotre choix : "); scanf("%d", &choix); } while (choix<0 || choix>2); return choix; } //////////////////////////////////////////////////////////////////////////////// int main() { int lig, col; // Mémorise la case jouée int choix; // Mémorise le choix int nbMines = 0; // Nombre de mines choisi par le joueur int nbCaseJouee, nbDrapeau, nbDrapeauOK; // Pour le test de fin de jeu srand(time(NULL)); //Afficher le début du jeu printf(" ________________________________\n"); printf("| |\n"); printf("| jeu du demineur |\n"); printf("|________________________________|\n\n"); init(); do { printf("\nCombien de mines voulez-vous ?\n\n"); scanf("%d", &nbMines); } while( (nbMines < NB_MINES_MIN) || (nbMines >= (TAILLE*TAILLE)) ); printf("D'accord, vous avez choisi de jouer avec %d mines\n\n", nbMines); placeMines(nbMines); printf("Voici la grille des mines pour controle:\n"); int i, j; for (i=1; i<=TAILLE; i++) { printf("\t\t\t"); for (j=1; j<=TAILLE; j++) if (mines[i][j]) printf("M "); else printf(". "); printf("\n"); } printf("\n"); for (i=1; i<=TAILLE; i++) { printf("\t\t\t"); for (j=1; j<=TAILLE; j++) printf("%c ", autour[i][j]+'0'); printf("\n"); } printf("\n\nVoici votre grille : A vous de jouer !\n\n"); afficheJeu(); while (1) { choix = choisir(&lig, &col); if (jouer(choix, lig, col)) { printf("\n\n\t\tDommage vous avez perdu !"); return 0; } afficheJeu(); // Test de la fin du jeu nbCaseJouee = nbDrapeau = nbDrapeauOK = 0; for (i=1; i<=TAILLE; i++) for (j=1; j<=TAILLE; j++) { if (jeu[i][j] != '-') nbCaseJouee++; if (jeu[i][j] == 'D') { nbDrapeau++; if (mines[i][j]) nbDrapeauOK++; } } if ( (nbDrapeau == nbMines) && (nbDrapeauOK == nbMines) ) break; // Les drapeaux correspondent bien à toutes les mines et à elles seules if (nbCaseJouee >= (TAILLE*TAILLE)) { printf("\n\n\t\tDommage vous avez perdu !"); return 0; } } printf("\n\n\t\tBravo vous avez gagné !"); //system("pause"); return 0; }
Bonne continuation.
midnightweb
Messages postés
10
Date d'inscription
mardi 16 décembre 2008
Statut
Membre
Dernière intervention
22 mars 2011
2
9 juin 2009 à 21:26
9 juin 2009 à 21:26
Merci Loupius, je n'en demandais pas tant !
J'ai travaillé dans le même sens en ajoutant un rang autour de la grille de jeu : ça permet de simplifier la recherche de mines autour.
Merci pour le code, je regarde ça demain et je verrai ce que je peux adapter à mon programme.
A+
J'ai travaillé dans le même sens en ajoutant un rang autour de la grille de jeu : ça permet de simplifier la recherche de mines autour.
Merci pour le code, je regarde ça demain et je verrai ce que je peux adapter à mon programme.
A+
Bonjour Loupius,
Je ne comprends pas bien pourquoi dans la fonction jouer on a case 1, case 0 et case 2 alors que la fonction choisir ne propose que les choix 1 et 2. A quoi correspond case 0 ?
Je ne comprends pas bien pourquoi dans la fonction jouer on a case 1, case 0 et case 2 alors que la fonction choisir ne propose que les choix 1 et 2. A quoi correspond case 0 ?
je voudrais que lorsque le nombre de mines autour de la case choisie est égal à 0, on dévoile toutes les cases égales à 0 autour de cette case jusqu'à ce qu'on arrive à une case indiquant un nombre de mines, pour réaliser cette demande, j'utilise la récursion; c'est logique car on recommence la même démarche jusqu'à trouver une case non vide, mais il ne faut pas remettre à zéro la grille temporaire sur laquelle on travaille; c'est ce différencie entre le switch '0' et le switch '1'.
8 juin 2009 à 22:48
Mais ça buggue encore et toujours quand il n'y a aucune mine détectée dans le proche voisinage ...
Je déprime là