IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement 2D, 3D et Jeux Discussion :

2D C++ : Améliorer Recherche chemin le plus court


Sujet :

Développement 2D, 3D et Jeux

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut 2D C++ : Améliorer Recherche chemin le plus court
    Bonjour,
    Je souhaiterais améliorer l'algorithme A* en reprenant le source
    http://khayyam.developpez.com/articles/algo/astar

    Le code est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
     
     
     
    struct noeud{
        float cout_g, cout_h, cout_f;
        pair<int,int> parent;    // 'adresse' du parent (qui sera toujours dans la map fermée
    };
     
    typedef map< pair<int,int>, noeud> l_noeud;
     
    class CClient :  public CPosition    // Point de raliement entre chaque deplacement de clients,... //
    {
    public:
            CClient();
            void CreateZone(TPaintBox *pBox, TMemo *aMemo, std::vector<CClient> &aClient, CClient *TClient, long X, long Y, int pWidth, int pHeight);
            void Process(CClient *TClient);
            void retrouver_chemin(CClient *pClient);
          //  void DisplayWay(CClient *pClient, pair<int,int>& p);
            void ajouter_cases_adjacentes(CClient *pClient, pair<int,int>&);
            bool deja_present_dans_liste(pair<int,int>, l_noeud&);
            pair<int,int> meilleur_noeud(l_noeud&);
            void ajouter_liste_fermee(CClient *pClient, pair<int,int>&);
            int Rayon;
            TPoint *Limited1;  // Point de limitation //
            TPoint *Limited2;
            TPoint *arrivee;
            pair <int, int> courant; // Courant = progression du point
            noeud depart;
            l_noeud liste_ouverte;  // Points a retenir //
            l_noeud liste_fermee;
            list<TPoint> chemin;    // CHemin de retour //
    };
     
    /////////////////////////////////////////////////////
    void CClient::Process(CClient *TClient)
    {
            if( !((TClient->courant.first == TClient->arrivee->x) && (TClient->courant.second == TClient->arrivee->y))
                &&
               (!TClient->liste_ouverte.empty())
             ){
            // on cherche le meilleur noeud de la liste ouverte, on sait qu'elle n'est pas vide donc il existe
            TClient->courant = TClient->meilleur_noeud(TClient->liste_ouverte);
            // on le passe dans la liste fermee, il ne peut pas déjà y être
            TClient->ajouter_liste_fermee(TClient,TClient->courant);
     
            TClient->ajouter_cases_adjacentes(TClient,TClient->courant);
            pBoxTerre->Canvas->Pixels[TClient->courant.first ][TClient->courant.second] = clRed;
     
            }
     
                if ((TClient->courant.first == TClient->arrivee->x) && (TClient->courant.second == TClient->arrivee->y)){
            TClient->retrouver_chemin(TClient);
     
            }
            else{
            // PAS DE SOLUTION
            }
     
    }
     
    void CClient::ajouter_cases_adjacentes(CClient *pClient, pair <int,int>& n)
    {
        noeud tmp;
     
        // on met tous les noeud adjacents dans la liste ouverte (+vérif)
        for (int i=n.first-1; i<=n.first+1; i++){
            if ((i<pClient->Limited1->x) || (i>=pClient->Limited2->x)) continue;
            for (int j=n.second-1; j<=n.second+1; j++){
     
                if ((j<pClient->Limited1->y) || (j>=pClient->Limited2->y)) continue;
                if ((i==n.first) && (j==n.second))  continue;   // case actuelle n
                //if (pBoxTerre->Canvas->Pixels[i][j] == StringToColor("0x00FFFFFF") || pBoxTerre->Canvas->Pixels[i][j]==clFire || pBoxTerre->Canvas->Pixels[i][j]==clFireC ||  pBoxTerre->Canvas->Pixels[i][j]==StringToColor("0x00BAA16F")) continue;  // ACHANGER      /*pBoxTerre->Canvas->Pixels[i][j]!=clWhite ||*/
                    // obstacle, terrain non franchissable
                if (pBoxTerre->Canvas->Pixels[i][j]==clBlack) continue;
                pair<int,int> it(i,j);
     
                if (!pClient->deja_present_dans_liste(it, pClient->liste_fermee)){
                    /* le noeud n'est pas déjà présent dans la liste fermée */
     
                    tmp.cout_g = pClient->liste_fermee[n].cout_g + distance(i,j,n.first,n.second);
                    tmp.cout_h = distance(i,j,arrivee->x,arrivee->y);
                    tmp.cout_f = tmp.cout_g + tmp.cout_h;
                    tmp.parent = n;
     
                    if (pClient->deja_present_dans_liste(it, pClient->liste_ouverte)){
                        /* le noeud est déjà présent dans la liste ouverte, il faut comparer les couts */
                        if (tmp.cout_f < pClient->liste_ouverte[it].cout_f){
                            /* si le nouveau chemin est meilleur, on update */
                            pClient->liste_ouverte[it]=tmp;
                        }
     
                        /* le noeud courant a un moins bon chemin, on ne change rien */
                    }else{
                        /* le noeud n'est pas présent dans la liste ouverte, on l'ajoute */
                        pClient->liste_ouverte[pair<int,int>(i,j)]=tmp;
                    }
                }
            }
        }
    }
    bool CClient::deja_present_dans_liste(pair<int,int> n, l_noeud& l){
        l_noeud::iterator i = l.find(n);
        if (i==l.end())
            return false;
        else
            return true;
    }
     
    pair<int,int> CClient::meilleur_noeud(l_noeud& l){
        float m_coutf = l.begin()->second.cout_f;
        pair<int,int> m_noeud = l.begin()->first;
     
        for (l_noeud::iterator i = l.begin(); i!=l.end(); i++)
            if (i->second.cout_f< m_coutf){
                m_coutf = i->second.cout_f;
                m_noeud = i->first;
            }
     
        return m_noeud;
    }
    void CClient::ajouter_liste_fermee(CClient *pClient, pair<int,int>& p){
        noeud& n = pClient->liste_ouverte[p];
        pClient->liste_fermee[p]=n;
     
        // il faut le supprimer de la liste ouverte, ce n'est plus une solution explorable
        if (pClient->liste_ouverte.erase(p)==0)
            {pClient->liste_ouverte.erase(p); }
        return;
    }
    void CClient::retrouver_chemin(CClient *pClient){
        // l'arrivée est le dernier élément de la liste fermée.
        l_noeud::iterator i = pClient->liste_fermee.end();
        i--;
     
        noeud& tmp = i->second;
     
        TPoint n;
        pair<int,int> prec;
        n.x = pClient->arrivee->x;
        n.y = pClient->arrivee->y;
        prec.first  = tmp.parent.first;
        prec.second = tmp.parent.second;
        pClient->chemin.push_front(n);
     
        while (prec != pair<int,int>(pClient->depart.parent.first,pClient->depart.parent.second)){
            n.x = prec.first;
            n.y = prec.second;
            pClient->chemin.push_front(n);
            tmp = pClient->liste_fermee[tmp.parent];
            prec.first  = tmp.parent.first;
            prec.second = tmp.parent.second;
            pBoxTerre->Canvas->Pixels[prec.first ][prec.second] = clBlue;
        }
    }
    J'appelle la fonction membre Process avec un Timer.
    Mais avec la multitude de possibilités, je voudrais rechercher les noeuds au fur et à mesure que le "Client" avance sans reprendre toute la liste .
    Mais plus on progresse dans le chemin plus le procédé prend de temps : pair<int,int> CClient::meilleur_noeud(l_noeud& l) prend en compte de plus en plus de noeud.
    Auriez-vous une idée de ce qui pourrait être optimiser ou encore s'il y a une autre facon de procédé?!

    Merci
    N'hésitez pas à me dire si il y a quelque chose que vous n'avez pas compris ...

  2. #2
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    C'est bon : il suffisait de supprimer la liste ouverte au fur et à mesure...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    TClient->courant = TClient->meilleur_noeud(TClient->liste_ouverte);
            // on le passe dans la liste fermee, il ne peut pas déjà y être
            TClient->ajouter_liste_fermee(TClient,TClient->courant);
           TClient->liste_ouverte.clear();
            TClient->ajouter_cases_adjacentes(TClient,TClient->courant);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Recherche de chemin le plus court
    Par Batou69 dans le forum Algorithmes et structures de données
    Réponses: 38
    Dernier message: 23/06/2011, 10h11
  2. Recherche algorithme de plus court chemin
    Par WileECoyote dans le forum Intelligence artificielle
    Réponses: 1
    Dernier message: 20/02/2011, 15h44
  3. recherche du chemin le plus court entre 2 points
    Par ram-0000 dans le forum Boost
    Réponses: 4
    Dernier message: 31/03/2009, 00h22
  4. chemin le plus court
    Par fabetvince dans le forum Algorithmes et structures de données
    Réponses: 13
    Dernier message: 21/04/2006, 13h38
  5. algorithme de Ford (recherche chemin le plus court)
    Par abstraite dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 19/05/2005, 10h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo