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
A voir également:
- Problème fonction récursive
- Fonction si et - Guide
- Fonction miroir - Guide
- Fonction moyenne excel - Guide
- Fonction remplacer sur word - Guide
- Fonction somme excel - Guide
4 réponses
yg_be
Messages postés
24281
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 585
bonjour, sans l'énoncé de l'exercice et sans commentaire, il est difficile de comprendre à quoi sert le code que tu as écrit.
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
24281
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 585
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 si
Quelle que soit la répétition que tu veux faire, il faut s'assurer que
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 :
Résultat :
Bonne chance
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 si
mCellValue[i][j] == 0en 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
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 ;-)
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 ;-)
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
As-tu partagé ton programme complet?