Problème fonction récursive
Résolu
Salut à tous ! Je viens vers vous parce que j'ai un petit soucis dans un programme en C. Je suis en train de coder un démineur, et je souhaite créer une fonction capable de découvrir toutes les cases jusqu'à rencontrer une mine. C'est une fonction qu'un professeur m'avait fait coder il y a longtemps, mais en me repenchant dessus j'ai un soucis : bien qu'il n'y ai pas d'erreur de compilation, le programme plante au moment d'exécuter la fonction. La voici :
et voici la partie de code qui l'appelle :
Merci d'avance pour vos réponses
int DiscoverCells(int k, int n, int tab[NB_ROW][NB_COL]){
int l=0, m=0, nbMines=0;
if(tab[k][n]==MINE)return 10;
mSetPlayed(tab[k+m][n+l]);
for(m=-1;m<=1;m++){
for(l=-1;l<=1;l++){
if((k+m>=0)&&(n+l>=0)&&(k+m<NB_ROW)&&(n+l<NB_COL)&&(mCellValue(tab[k+m][n+l])!=MINE)){
nbMines+=DiscoverCells(k+m, n+l, tab);
return 1;
}
}
}
return nbMines;
}
et voici la partie de code qui l'appelle :
while(1){
for(k=0;k<NB_ROW;k++){
for(n=0;n<NB_COL;n++){
if(!mIsPlayed(tab[k][n])){
printf(".\t");
}
else if(mCellValue(tab[k][n])==9){
printf("%c\t", CELL_MINE_CHAR);
}
else{
printf("%d\t", mCellValue(tab[k][n]));
}
}
printf("\n\n");
}
scanf("%d", &l);
scanf("%d", &m);
DiscoverCells(l, m, tab);
}
Merci d'avance pour vos réponses
4 réponses
-
yg_be Messages postés 23437 Date d'inscription Statut Contributeur Dernière intervention Ambassadeur 1 588
bonjour, sans l'énoncé de l'exercice et sans commentaire, il est difficile de comprendre à quoi sert le code que tu as écrit.-
Merci de ta réponse. Pour l'énoncé de l'exercice, il s'agit juste de faire un démineur. Sinon voilà pour les commentaires :
while(1){ // On fait apparaitre le tableau à l'infini à chaque entrée de case. La condition doit être remplacée une fois que le programme contera les cases découvertes. //Le programme affiche le tableau en mettant des points à la place des cases cachées et des étoiles à la place des mines (si la case est découverte). for(k=0;k<NB_ROW;k++){ for(n=0;n<NB_COL;n++){ if(!mIsPlayed(tab[k][n])){ printf(".\t"); } else if(mCellValue(tab[k][n])==9){ printf("%c\t", CELL_MINE_CHAR); } else{ printf("%d\t", mCellValue(tab[k][n])); } } printf("\n\n"); } //Le joueur entre la case qu'il souhaite découvrir et le programme appelle la fonction qui sert à découvrir les cases alentour jusqu'à trouver une mine. scanf("%d", &l); scanf("%d", &m); DiscoverCells(l, m, tab); }
int DiscoverCells(int k, int n, int tab[NB_ROW][NB_COL]){ int l=0, m=0, nbMines=0; if(tab[k][n]==MINE)return 10; // si le joueur rentre les coordonnées d'une mine la fonction renvoi un code de Game Over mSetPlayed(tab[k+m][n+l]); //la fonction marque la case entrée en paramètres comme découverte (jouée) //La fonction se répète avec toutes les cases aux alentours jusqu'à rencontrer une mine ou un bord du tableau for(m=-1;m<=1;m++){ for(l=-1;l<=1;l++){ if((k+m>=0)&&(n+l>=0)&&(k+m<NB_ROW)&&(n+l<NB_COL)&&(mCellValue(tab[k+m][n+l])!=MINE)){ nbMines+=DiscoverCells(k+m, n+l, tab); return 1; } } } return nbMines; }
En espérant que ça convienne
-
-
C'est moi qui l'ai écrit, et c'est marqué à la ligne 5 de la fonction. mSetPlayed est une macro qui met un bit d'une variable à 1. Dans ce cas, il s'agit du 32ème bit d'une variable qui symbolise une case
-
yg_be Messages postés 23437 Date d'inscription Statut Contributeur Dernière intervention Ambassadeur 1 588
ajoute des printf dans ton programme, afin de mieux comprendre comment il se comporte. -
Bonjour,
Ce qui est bizarre c'est que dans le démineur, on découvre les cases une par une et donc il n'y a pas de récursivité. La seule exception, c'est quand on clique sur une case avec aucune mine adjacente (donc simCellValue[i][j] == 0
en admettant que j'ai bien compris ton code). Dans ce cas le jeu de démineur sous windows découvre les cases voisines et répète le processus pour les éventuelles cases.
Quelle que soit la répétition que tu veux faire, il faut s'assurer que- ta récursion exprime, à partir d'une case, quelle case explorer ;
- ta récursion se termine (n'engendre pas une boucle infinie) et idéalement ne re-déclenche pas des calculs déjà faits.
Si on se place dans le cas du démineur standard, si une case dont le nombre de bombes adjacentes 0 est dévoilée, alors on dévoile les cases voisines. Si l'une de ces cases voisine a également 0 bombe adjacentes, alors on répète le processus récursivement :
#include <stdio.h> #include <stdint.h> #include <stdlib.h> #define X 9 int min(int x, int y) { return x < y ? x : y; } int max(int x, int y) { return x > y ? x : y; } void display(int **tab, int **played, size_t num_rows, size_t num_cols) { for (size_t i = 0; i < num_rows; i++) { for (size_t j = 0; j < num_cols; j++) { if (played[i][j]) { if (tab[i][j] == X) { printf("*"); } else { printf("%d", tab[i][j]); } } else { printf("."); } } printf("\n"); } } int ** calloc_matrix(size_t num_rows, size_t num_cols) { int ** matrix = (int **) malloc(sizeof(int *) * num_rows); if (matrix) { for (size_t i = 0; i < num_rows; i++) { matrix[i] = (int *) calloc(sizeof(int), num_rows); } } return matrix; } void free_matrix(int ** matrix, size_t num_rows) { if (matrix) { for (size_t i = 0; i < num_rows; i++) { if (matrix[i]) { free(matrix[i]); } } free(matrix); } } void play(int **tab, int **played, size_t num_rows, size_t num_cols, size_t k, size_t l) { played[k][l] = 1; if (tab[k][l] == 0) { for (size_t i = max(0, k - 1); i < min(num_rows, k + 2); i++) { for (size_t j = max(0, l - 1); j < min(num_cols, l + 2); j++) { if (!played[i][j]) { play(tab, played, num_rows, num_cols, i, j); } } } } } int main(){ const size_t num_rows = 4; const size_t num_cols = 5; int ** played = calloc_matrix(num_rows, num_cols); // X == mine // autre valeur == nombre de mines adjacentes int ** tab = calloc_matrix(num_rows, num_cols); tab[0][0] = 0; tab[0][1] = 0; tab[0][2] = 1; tab[0][3] = 1; tab[0][4] = 1; tab[1][0] = 0; tab[1][1] = 0; tab[1][2] = 2; tab[1][3] = X; tab[1][4] = 2; tab[2][0] = 1; tab[2][1] = 1; tab[2][2] = 2; tab[2][3] = X; tab[2][4] = 2; tab[3][0] = X; tab[3][1] = 1; tab[3][2] = 1; tab[3][3] = 1; tab[3][4] = 1; printf("Before:\n"); display(tab, played, num_rows, num_cols); printf("\nAfter:\n"); play(tab, played, num_rows, num_cols, 0, 0); display(tab, played, num_rows, num_cols); free_matrix(tab, num_rows); free_matrix(played, num_rows); return 0; }
Résultat :
Before:
.....
.....
.....
.....
After:
001..
002..
112..
.....
Bonne chance-
-
Pour information, tu peux trier les messages par dates ce qui t'évitera de te faire avoir. Et les messages sont numérotés, donc s'il y a une flèche à droite du numéro, c'est que des messages sont apparus depuis.
Est-ce que la solution que je t'ai proposée te convient ? Est-ce que ton problème est résolu ? Si oui, voir ce lien. Et sinon, merci de nous indiquer ce qu'il reste à voir :-)
Bonne chance -
-
Ok :-)
Dans ce cas je clos le sujet, car d'une part tu ne sembles plus attendre d'aide de notre part dans l'immédiat, et d'autre part, je pense que la réponse que je t'ai donnée dans le message #12 répond à ton problème ou du moins est adaptable pour faire ce que tu veux.
Bien entendu, si tu as besoin d'aide, n'hésite pas à revenir poster un message dans cette discussion ;-) -