Forum Programmation.c Programmer un démineur en C

Posté par  .
Étiquettes : aucune
1
9
juin
2009

Je dois programmer un démineur en C sans bibliothèque graphique.
Jusque là ça marche mais je bloque sur la fonction de dévoilement des cases vides.
Lorsqu'on choisit une case, s'il y a des mines autour, le programme affiche le nombre de mines
S'il y a une mines le programme affiche perdu
Mais q'il n'y a ni mines ni mines autour, il affiche seulement "0". Ce qui ne fait pas avancer le jeu.
Je voudrais que dans ce cas, le jeu dévoile les cases vides autour, et en frontière, le nb de mines. Et là ça buggue : j'ai des '0' à l'infini.
Je pense que le souci est dans la fonction 'Jouer'

#include
#include
#include

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
int NbMines;//le nombre de mines choisi par le joueur
int choix;//le choix effectué par le joueur pour découvrir ou placer un drapeau


//////////////////////////////
// FONCTION INITIALISATION ///
//////////////////////////////
void Init()
{
for(i=0;i
{
for(j=0;j
{
JEU[i][j]='-';//' 'implique case cachée
MINES[i][j]='0';
}
}
}

///////////////////////////////
// FONCTION PLACER LES MINES //
///////////////////////////////
void PlaceMines()
{
int CompteMines;//compteur de mines
for (CompteMines=0;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
}
}
}

////////////////////////////////////////
// FONCTION AFFICHER LA GRILLE DE JEU //
////////////////////////////////////////
void AfficheJeu()
{
printf("\n\n");
printf(" | 1 2 3 4 5 6 7 8 9 10\n");
printf("___|______________________________\n");
for(i=0;i
{
if(i
printf(" %d | ",i+1);
else
printf("%d | ",i+1);
for(j=0;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
{
if(i
printf(" %d | ",i+1);
else
printf("%d | ",i+1);
for(j=0;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);
}

}

//////////////////////////////////////////////////////////
// FONCTION JOUER dévoiler une case ou placer un drapeau//
//////////////////////////////////////////////////////////
void Jouer()
{
char NbMinesTxt[2]; // nombre de mines aux alentours
switch (choix)
{
case 1 :
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';
for(i=i-1;i
{
for(j=j-1;j
NbMinesAutour();
}
}
break;
case 2 : JEU[i][j]='D';
break;
}
}

///////////////////////////////////////////////////////////////
// FONCTION CHOISIR On demande au joueur de choisir une case //
///////////////////////////////////////////////////////////////
void Choisir()
{
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;
printf("\t1. Decouvrir une case\n");
printf("\t2. Placer un drapeau");
do
{
printf("\t\tVotre choix : ");
scanf("%d",&choix);
}
while (choix2);
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
int c;//compteur
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>=30);
printf("D'accord, vous avez choisi de jouer avec %d mines\n\n",NbMines);
PlaceMines();
printf("Voici la grille des mines pour controle:\n");
for(i=0;i
{
printf("\t\t\t");
for(j=0;j
{
printf("%c ",MINES[i][j]);
}
printf("\n");
}

printf("\n\nVoici votre grille : A vous de jouer !\n\n");
AfficheJeu();

for(c=0;c<(100-NbMines);c++)
{
Choisir();
Jouer();
AfficheJeu();
}
printf("\n\n\t\tBravo vous avez gagné !");

system("pause");
return 0;
}
  • # hmmmm

    Posté par  (site web personnel) . Évalué à 7.

    j'aurai combien comme note si je réponds ?
    ya pas les corrigés de l'année précédente ?
    et sinon, tu l'as mis sous quelle licence (libre) ton programme ?
  • # Parce que ça compile ??

    Posté par  . Évalué à 2.

    Parce que ça compile seulement, ça ?

    Manquent l'} de fermeture du else et celle de fermeture du switch, dans jouer() !

    Et accessoirement, le for ne sert absolument à rien.
  • # Remarques

    Posté par  (site web personnel) . Évalué à 7.

    1. Deja je te conseille d'utiliser des constantes pour la taille de la grille plutot que de mettre des 10 partout.
    2. Ensuite dans NbMinesAutour() tu as des if (i==10) ou j==10 qui ne seront jamais vrai, c'est 9 le maximum vu que tu commences à 0.
    3. Dans NbMinesAutour() tout le premier else peut etre fortement raccourci. Par exemple,
                                if(i>0)
                                {
                                          if(j>0 && MINES[i-1][j-1]=='M')
                                          N++;
                                          if(MINES[i-1][j]=='M')
                                          N++;
                                          if(j<9 && MINES[i-1][j+1]=='M')
                                          N++;
                                 }
                                          if(j>0 && MINES[i][j-1]=='M')
                                          N++;
                                          if(j<9 && MINES[i][j+1]=='M')
                                          N++;
                                 if(i<9)
                                 {
                                          if(j>0 && MINES[i+1][j-1]=='M')
                                          N++;
                                          if(MINES[i+1][j]=='M')
                                          N++;
                                          if(j < 9 && MINES[i+1][j+1]=='M')
                                          N++;
                                  }
      
    4. C'est pas beau que N soit globale, ca devrait juste être renvoyé par NbMinesAutour()
    5. Il manque la fin du code de Jouer(), qui est sans doute la ou est le problème donc ca va être difficile de t'aider plus
  • # pour avoir codé ce truc avant

    Posté par  . Évalué à 2.

    (en seconde, puis à nouveau en 1ere, et une nouvelle fois en fin de terminale)

    a) d'un point de vue de vue performance, il vaut mieux avoir les chiffres déjà calculé
    (quand tu place les mines tu fais un +1 partout autour; prévoir des linges/colonne de sentinelle ou vérifier les bornes )
    Mon premier démineur faisait le calcul à chaque découverte de case, c'était affreusement lent (ti-92 II, oui en seconde, vers la fin, je trouvais la 82 trop limité coté prog).

    le second (le plus rapide des 3 sur TI-92) faisait une liste de case à découvrir
    en gros


    decouvreXY(x,y)
    mat[i][j] = mat[i][j] +100
    if ( mat[i][j] == 0 ) {
    pour toute les case autour : Si mat[x][y] < 100 => ajouter x,y dans liste
    }
    else if ( mat[i][j] == 10 ) Kabooom


    Bon mon troisième code faisait du récursif, mais il était plus lent (mais de mon point de vue bien plus propre) (en gros je me passais de la liste)

    Voili voilou.

    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: pour avoir codé ce truc avant

      Posté par  . Évalué à 1.

      haha moi je l'avais fait sur TI 82, l'emplacement des mines était calcule lors du 1e coup, pour ne pas tomber sur 1 mine des le début
      • [^] # Re: pour avoir codé ce truc avant

        Posté par  . Évalué à 4.

        à ta place j'aurais calculé l'emplacement des mines lors du 1er coup afin de systématiquement tomber sur une mine au début ! ;)

        (on aurait sûrement perdu moins de temps sur ce jeu comme ca)
  • # CPlusOuMoinsPlusPlus?

    Posté par  (site web personnel) . Évalué à 2.

    #include
    #include
    #include

    T'as oublié quelque chose je crois.

    void PlaceMines()
    {
    int CompteMines;//compteur de mines
    for (CompteMines=0;CompteMines<9)

    Y a plus d'incrément dans C ?
    • [^] # Re: CPlusOuMoinsPlusPlus?

      Posté par  . Évalué à 2.

      Nan, mais il a inventé un nouveau truc, par contre :


      for (CompteMines=0;CompteMines<9)
      printf(" %d | ",i+1);
      else
      printf("%d | ",i+1);
    • [^] # Re: CPlusOuMoinsPlusPlus?

      Posté par  . Évalué à 1.

      il n'a pas oublié, c'est simplement détecté comme balise html (de la forme < ... >)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.