Problème de permutation d'éléments dans un tableau dynamique 2d

Fermé
BlacK-Sunrise Messages postés 3 Date d'inscription jeudi 22 novembre 2012 Statut Membre Dernière intervention 23 novembre 2012 - 22 nov. 2012 à 18:39
 Utilisateur anonyme - 23 nov. 2012 à 18:12
Bonjour,

Je suis actuellement en train de programmer le taquin et il se trouve que j'ai un problème de permutations dans mon tableau.
Après avoir créé, initialisé, mélangé et affiché le tableau le programme recherche le nombre de déplacements possible. Un fois trouvé, il affiche ce nombre ainsi qu'une liste dénombrant les possibilités de déplacements. Lorsque l'utilisateur entre un des chiffres listé, le programme effectue le déplacement choisi.
Le problème c'est que lorsque je veux permuter la case vide (représenté par un "0") avec celle d'en dessous (si c'est possible) la permutation s'effectue avec une troisième case, celle en dessous à droite de la case vide.
Autre problème, lorsque je souhaite permuter 2 cases lorsqu'elles se situent sur un des côtés du plateau de jeu j'ai des déplacements impossibles.

Voici comment j'ai défini et comment j'affiche le plateau de jeu :

int **creer_plateau(int nb_ligne, int nb_colonne){
    int i, j;
    int tmp = 0, randval_i = 0, randval_j = 0;

    int **plateau = new int*[nb_ligne];
    for (i = 0; i < nb_ligne; i++) plateau[i] = new int[nb_colonne];


    for(i = 0; i < nb_ligne; i++)
        for (j = 0; j < nb_colonne; j++) plateau[i][j] = i * nb_colonne + j;

    for(i = 0; i < nb_ligne; i++) {
        for(j = 0; j < nb_colonne; j++) {
            /* On choisit une i et une j aléatoirement */
            randval_i = rand() % nb_ligne;
            randval_j = rand() % nb_colonne;
            /* On permute */
            tmp = plateau[i][j];
            plateau[i][j] = plateau[randval_i][randval_j];
            plateau[randval_i][randval_j] = tmp;
        }
    }
    return (plateau);
}

void afficher_plateau(int **plateau, int nb_ligne, int nb_colonne) {
    int i, j;
    for(i = 0; i < nb_ligne; i++) {
        for(j = 0; j < nb_colonne; j++) {
            if( plateau[i][j] == 0) cout << " |<>| ";
            else if ( (plateau[i][j]>= 10) ) cout << " |" << plateau[i][j] << "| ";
            else cout << " | " << plateau[i][j] << "| ";
        }
        cout << endl;
    }
}


et ici, comment j'ai défini la fonction de déplacement des cases :

void deplacements(int **plateau, int nb_ligne, int nb_colonne, int deplacement){
    int i, j, temp;

    for(i = 0; i < nb_ligne; i++) {
        for(j = 0; j < nb_colonne; j++) {
            if (plateau[i][j] == 0)
            {
                /* cas en haut a gauche */
                if ( (((i-1) < 0 ) && ((j-1) < 0)) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }

                else if ( (((i-1) < 0 ) && ((j-1) < 0)) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }

                /* cas en haut a droite */
                else if ( (((i-1) < 0 ) && ((j+1) >= nb_colonne)) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }

                else if ( (((i-1) < 0 ) && ((j+1) >= nb_colonne)) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }

                /* cas en bas a gauche */
                else if ( (((i+1) >= nb_ligne ) && ((j-1) < 0)) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }

                else if ( (((i+1) >= nb_ligne ) && ((j-1) < 0)) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }

                /* cas en haut a droite */
                else if ( (((i+1) >= nb_ligne ) && ((j+1) >= nb_colonne)) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }

                else if ( (((i+1) >= nb_ligne ) && ((j+1) >= nb_colonne)) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }

                /* cas coté haut */
                else if ( ((i-1) < 0 ) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }

                else if ( ((i-1) < 0 ) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }

                else if ( ((i-1) < 0 ) && (deplacement == 3 ) ){ temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }


                /* cas coté bas */
                else if ( ((i+1) >= nb_ligne) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }

                else if ( ((i+1) >= nb_ligne) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }

                else if ( ((i+1) >= nb_ligne) && (deplacement == 3) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }

                /* cas coté gauche */
                else if ( ((j-1) < 0 ) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }

                else if ( ((j-1) < 0 ) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }

                else if ( ((j-1) < 0 ) && (deplacement == 3) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }

                /* cas coté droit */
                else if ( ((j+1) >= nb_colonne) && (deplacement == 1) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }

                else if ( ((j+1) >= nb_colonne) && (deplacement == 2) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }

                else if ( ((j+1) >= nb_colonne) && (deplacement == 3) ) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }

                else
                {
                    if (deplacement == 1) { temp = plateau[i][j]; plateau[i][j] = plateau[i-1][j]; plateau[i-1][j] = temp; }
                    else if (deplacement == 2) { temp = plateau[i][j]; plateau[i][j] = plateau[i+1][j]; plateau[i+1][j] = temp; }
                    else if (deplacement == 3) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j-1]; plateau[i][j-1] = temp; }
                    else if (deplacement == 4) { temp = plateau[i][j]; plateau[i][j] = plateau[i][j+1]; plateau[i][j+1] = temp; }
                }
            }
        }
    }
}


Voila, j'espère que vous pourrez m'aider.

Merci d'avance


A voir également:

4 réponses

Utilisateur anonyme
22 nov. 2012 à 22:41
Bonsoir

Oh la la ! Une grande suite de if... else if .. comme ça, ça doit être très fatigant à écrire. Il y avait sûrement beaucoup plus simple à faire.
Déjà, la première simplification serait d'écrire une fonction pour permuter 2 éléments, ça t'éviterait de réécrire 3 affectations à chaque fois.

Mais bon, je suppose que tu as bien vérifié les cas (pas moi) et que ça devrait marcher comme ça... à un détail près.
Tu boucles sur toutes les cases de ton tableau et tu testes si tu tombes sur la case vide. Là tu fais l'échange entre ta case vide et sa voisine. Jusque là tout va bien.
Mais tu devrais t'arrêter là.
Or, tes boucles continuent. Et tu peux retomber sur ton zéro plus loin : tu vas refaire le mouvement encore !
Fais un 'return;' dès que tu fais une permutation pour éviter ce problème.
1
BlacK-Sunrise Messages postés 3 Date d'inscription jeudi 22 novembre 2012 Statut Membre Dernière intervention 23 novembre 2012
23 nov. 2012 à 15:02
Ahh ! Merci beaucoup ça marche !

Et oui je pense qu'avec une fonction pour les permutations se serais plus simple ^^' je vais essayer d'en faire une.

Encore merci.
0
BlacK-Sunrise Messages postés 3 Date d'inscription jeudi 22 novembre 2012 Statut Membre Dernière intervention 23 novembre 2012
23 nov. 2012 à 17:31
Rebonjour,

Je me tourne à nouveau vers vous parce que j'ai un nouveau problème concernant les permutations dans mon programme. Je voudrais compter le nombre de permutations possibles dans le tableau afin de savoir si le jeu est soluble mais le problème est que j'obtiens une "erreur de segmentation".

Voila la fonction :

int plateau_soluble(int **&plateau_copie, int nb_ligne, int nb_colonne){

    int i, j, k = 0, l, m;
    int nb_permutations = 0;
    int pos_case_vide;

    for(i = (nb_ligne-1); i >= 0; i--){
        for(j = (nb_colonne-1); j >= 0; j--)
            if(plateau_copie[i][j] != i*j){

                for(l = 0; l < (nb_ligne); l++){
                    for(m = 0; m < (nb_colonne); m++)
                        if(plateau_copie[l][m] == i*j){
                            break;
                        }
                }
            k = plateau_copie[i][j];
            plateau_copie[i][j] = plateau_copie[l][m];
            plateau_copie[l][m] = k;
            nb_permutations++;
            }
            cout << plateau_copie[i][j] << " " ;
    }

    for(i = 0; i < (nb_ligne); i++)
        for(j = 0; j < (nb_colonne); j++)
            if(plateau_copie[i][j] == 0){
                pos_case_vide = plateau_copie[i][j];
                break;
            }

    return (nb_permutations%2 == (i+j)%2);
}



Et la création du plateau :

int **creer_plateau_copie(int **plateau, int nb_ligne, int nb_colonne){
    int i, j;
    int **plateau_copie = new int*[nb_ligne];
    for(i = 0; i < nb_ligne; i++) plateau_copie[i] = new int[nb_colonne];

    for(i = 0; i < nb_ligne; i++) {
        for(j = 0; j < nb_colonne; j++) {
            plateau_copie[i][j] = plateau[i][j];
        }
    }
    return (plateau_copie);
}




A nouveau j'espère que vous serez en mesure de m'aider,

Merci d'avance.
0
Utilisateur anonyme
23 nov. 2012 à 18:12
Je n'ai pas cherché à comprendre tes algorithmes - ou plutôt si, mais comme je me suis tout de suite perdu, j'ai abandonné.
En ce qui concerne ton erreur de segmentation, elle vient d'un dépassement des indices.
Ce dépassement vient d'une mauvaise utilisation de break;
Tu as raisonné comme si break te faisait ressortir du nombre de boucles qui t'arrange (4 dans le premier cas, 2 dans le second) alors que break ne fait ressortir que d'un seul niveau. Donc la boucle de rang immédiatement supérieur continue, et tu finis par ressortir du for (l) avec l=nb_ligne; dès que tu te sers de plateau_copie[l][m]; derrière, tu as un dépassement d'indice.

Question subsidiaire : à quoi sert pos_case_vide = plateau_copie[i][j]; puisque tu n'utilises jamais pos_case_vide ?
0