1

Salut a tous!

Il y a quelques temps de ça j'avais créé un path finding basé sur A* pour des programmes C.
Je viens de le recoder sous forme d'une classe C++.
//  --------------------------------------------------------------------------------------- // //                A* Path Finding C++ class                                                 // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project: The API project for C and C++ programming (A.I.)                                // // ---------------------------------------------------------------------------------------- // #ifndef PATH_H      #define PATH_H      #include <stdlib.h>      #include <string.h>      /*MACRO*/      /*ENUMERATIONS*/      enum PATH_MODE {PATH_short = 0, PATH_best};      enum PATH_BOOL {PATH_error = -1, PATH_false, PATH_true};      /*STRUCTURES*/      typedef struct      {           unsigned long x;           unsigned long y;           unsigned long z;      }PATH_POINT;      typedef struct      {           unsigned int *data;           unsigned long width;           unsigned long height;           unsigned long deep;      }PATH_MAP;      typedef struct      {           void* parent;           void* son;           unsigned long F;           unsigned long G;           unsigned long H;           PATH_POINT point;           bool isClosed;      }PATH_NODE;      class CPath      {           public:                /*PROTOTYPES 2D*/                CPath ( unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned int* , PATH_MODE = PATH_best , bool = false );                /*PROTOTYPES 3D*/                CPath ( unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned int* , PATH_MODE = PATH_best , bool = false );                /*COMMUN*/                CPath(  );                ~CPath( );                //Retourne true si l'objet est initialisé                bool isInitialized( void );                //Informations au sujet de la classe                char* getName ( void ){ return "A* Path Finding C++";};                char* getVersion ( void ){ return "2.0.1.0";};                char* getCopyright ( void ){ return "Copyright (c) 2005 Spomky.Dev (http://www.spomky.com/)";};                //Lance la recherche                PATH_BOOL search( void );                //Retourne true si la recherche a été fructueuse                PATH_BOOL isSuccess ( void );                //Efface la recherche                void freePath ( void );                //Change le point de départ                PATH_BOOL setStartPoint( PATH_POINT* );                //Change le point d'arrivé                PATH_BOOL setEndPoint( PATH_POINT* );                //Change la carte et ses dimensions                PATH_BOOL setNewMap( unsigned long , unsigned long , unsigned int* );                PATH_BOOL setNewMap( unsigned long , unsigned long , unsigned long , unsigned int* );                //Change le mode de recherche                PATH_BOOL setSearchMode( PATH_MODE );                //Change la limite H&V                PATH_BOOL setHVMode( bool );                //Change le type de points                PATH_BOOL set3DMode( bool );                //Retourne le point de départ                PATH_BOOL getStartPoint( PATH_POINT* );                //Retourne le point d'arrivé                PATH_BOOL getEndPoint( PATH_POINT* );                //Retourne les dimensions de la carte                PATH_BOOL getMapSize( unsigned long* , unsigned long* );                PATH_BOOL getMapSize( unsigned long* , unsigned long* , unsigned long* );                //Retourne le mode de recherche                PATH_BOOL getSearchMode( PATH_MODE* );                //Retourne la limite H&V                PATH_BOOL getHVMode( void );                //Change le type de points                PATH_BOOL get3DMode( void );                //Fonctions permettant de récupérer les points du chemin trouvé                PATH_BOOL getFirstPoint( PATH_POINT* );                PATH_BOOL getLastPoint( PATH_POINT* );                PATH_BOOL getCurrentPoint( PATH_POINT* );                PATH_BOOL gotoFirstPoint( void );                PATH_BOOL gotoLastPoint( void );                PATH_BOOL gotoNextPoint( void );                PATH_BOOL gotoPreviousPoint( void );                //Fonctions permettant de naviguer parmi les erreurs                const char* getError( unsigned long );                unsigned long getErrorNumber( void );                void clearAllErrors( void );           private:                /*PROTOTYPES 2D*/                bool isGoodWay(unsigned long, unsigned long);                PATH_NODE* add_node(unsigned long, unsigned long, PATH_NODE*);                PATH_NODE* isNodeInList(unsigned long, unsigned long);                bool isNewFGHBetterThanOld(unsigned long, unsigned long, PATH_NODE*, PATH_NODE*);                /*PROTOTYPES 3D*/                bool isGoodWay(unsigned long, unsigned long, unsigned long);                PATH_NODE* add_node(unsigned long, unsigned long, unsigned long, PATH_NODE*);                PATH_NODE* isNodeInList(unsigned long, unsigned long, unsigned long);                bool isNewFGHBetterThanOld(unsigned long, unsigned long, unsigned long, PATH_NODE*, PATH_NODE*);                /*COMMUN*/                /*Pour le calcul*/                PATH_NODE* getBestNode( void );                void setFGH( PATH_NODE* );                void buildFullPath( void );                PATH_MAP map;                PATH_MODE search_mode;                PATH_POINT start_point;                PATH_POINT end_point;                bool use_hv_move_only;                /*Pour la recherche*/                PATH_NODE** node_list;                PATH_NODE* node_end;                PATH_NODE* node_current;                unsigned long node_number;                /*Pour les vérifications*/                bool is_Searched;                bool is_Success;                bool is_3D;                bool is_MapInitialized;                bool is_StartPointInitialized;                bool is_EndPointInitialized;                /*Pour les erreurs*/                bool addNewError( const char* );                char **error_list;                unsigned long error_number;                /*Autres*/                void clearAllNodes( void );      }; #endif //  --------------------------------------------------------------------------------------- // //                A* Path Finding C++ Class                                                 // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project: The API project for C and C++ programming (A.I.)                                // // ---------------------------------------------------------------------------------------- // #include "path.h" CPath::CPath (  ) {      this->node_list = NULL;      this->node_end = NULL;      this->node_number = 0;      this->error_number = 0;      this->error_list = NULL;      this->start_point.x = 0;      this->start_point.y = 0;      this->start_point.z = 0;      this->end_point.x = 0;      this->end_point.y = 0;      this->end_point.z = 0;      this->map.width = 0;      this->map.height = 0;      this->map.data = NULL;      this->search_mode = PATH_best;      this->is_MapInitialized = false;      this->is_StartPointInitialized = false;      this->is_EndPointInitialized = false;      this->is_3D = false;      this->is_Searched = false;      return; } CPath::CPath ( unsigned long Xs, unsigned long Ys, unsigned long Xe, unsigned long Ye, unsigned long width, unsigned long height, unsigned int *map, PATH_MODE mode, bool hv_move ) {      if ( map == NULL || width == 0 || height == 0 )           return;      this->node_list = NULL;      this->node_end = NULL;      this->node_number = 0;      this->map.data = map;      this->map.width = width;      this->map.height = height;      this->start_point.x = Xs;      this->start_point.y = Ys;      this->end_point.x = Xe;      this->end_point.y = Ye;      this->use_hv_move_only = hv_move;      this->search_mode = mode;      this->error_number = 0;      this->error_list = NULL;      this->is_Searched = false;      if( this->add_node(this->start_point.x, this->start_point.y, NULL) )      {           this->is_MapInitialized = true;           this->is_StartPointInitialized = true;           this->is_EndPointInitialized = true;           this->is_3D = false;           this->node_current = this->node_list[0];           return;      }      return; } CPath::CPath ( unsigned long Xs, unsigned long Ys, unsigned long Zs, unsigned long Xe, unsigned long Ye, unsigned long Ze, unsigned long width, unsigned long height, unsigned long deep, unsigned int *map, PATH_MODE mode, bool hv_move ) {      if ( map == NULL || width == 0 || height == 0  || deep == 0 )           return;      this->node_list = NULL;      this->node_end = NULL;      this->node_number = 0;      this->map.data = map;      this->map.width = width;      this->map.height = height;      this->map.deep = deep;      this->start_point.x = Xs;      this->start_point.y = Ys;      this->start_point.z = Zs;      this->end_point.x = Xe;      this->end_point.y = Ye;      this->end_point.z = Ze;      this->use_hv_move_only = hv_move;      this->search_mode = mode;      this->is_Searched = false;      if ( this->add_node(this->start_point.x, this->start_point.y, this->start_point.z, NULL) )      {           this->is_MapInitialized = true;           this->is_StartPointInitialized = true;           this->is_EndPointInitialized = true;           this->is_3D = true;           this->node_current = this->node_list[0];           return;      }      return; } CPath::~CPath ( ) {      this->freePath(); } PATH_NODE* CPath::add_node(unsigned long x, unsigned long y, PATH_NODE* parent) {      bool isgoodpath;      if (this->use_hv_move_only)      {           if (parent != NULL && abs(x-parent->point.x)+abs(y-parent->point.y) != 1)                return NULL;      }      if ((isgoodpath = !this->isGoodWay(x,y)))           return NULL;      if (!(this->node_list = (PATH_NODE**)realloc(this->node_list,(this->node_number+1)*sizeof(PATH_NODE*))))           return NULL;      if (!(this->node_list[this->node_number] = (PATH_NODE*)malloc(sizeof(PATH_NODE))))      {           this->node_list = (PATH_NODE**)realloc(this->node_list,this->node_number*sizeof(PATH_NODE*));           return NULL;      }      this->node_list[this->node_number]->parent = parent;      this->node_list[this->node_number]->point.x = x;      this->node_list[this->node_number]->point.y = y;      this->node_list[this->node_number]->isClosed = isgoodpath;      if (x ==this->end_point.x && y == this->end_point.y)           this->node_end = this->node_list[this->node_number];      this->setFGH(this->node_list[this->node_number]);      ++(this->node_number);      return this->node_list[this->node_number-1]; } PATH_NODE* CPath::add_node(unsigned long x, unsigned long y, unsigned long z, PATH_NODE* parent) {      bool isgoodpath;      if (this->use_hv_move_only)      {           if (parent != NULL && abs(x-parent->point.x)+abs(y-parent->point.y)+abs(z-parent->point.z) != 1)                return NULL;      }      if ((isgoodpath = !this->isGoodWay(x,y,z)))           return NULL;      if (!(this->node_list = (PATH_NODE**)realloc(this->node_list,(this->node_number+1)*sizeof(PATH_NODE*))))           return NULL;      if (!(this->node_list[this->node_number] = (PATH_NODE*)malloc(sizeof(PATH_NODE))))      {           this->node_list = (PATH_NODE**)realloc(this->node_list,this->node_number*sizeof(PATH_NODE*));           return NULL;      }      this->node_list[this->node_number]->parent = parent;      this->node_list[this->node_number]->point.x = x;      this->node_list[this->node_number]->point.y = y;      this->node_list[this->node_number]->point.z = z;      this->node_list[this->node_number]->isClosed = isgoodpath;      if (x == this->end_point.x && y == this->end_point.y && z == this->end_point.z )           this->node_end = this->node_list[this->node_number];      this->setFGH(this->node_list[this->node_number]);      ++(this->node_number);      return this->node_list[this->node_number-1]; } PATH_NODE* CPath::getBestNode( void ) {      if (this->node_number == 0)           return NULL;      PATH_NODE* found = NULL;      unsigned int cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if ((found != NULL && this->node_list[cptr]->isClosed == false && found->F > this->node_list[cptr]->F) || (found == NULL && this->node_list[cptr]->isClosed == false))                found = this->node_list[cptr];      }      return found; } PATH_NODE* CPath::isNodeInList(unsigned long X, unsigned long Y) {      unsigned long cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if (this->node_list[cptr]->point.x == X && this->node_list[cptr]->point.y == Y)                return this->node_list[cptr];      }      return NULL; } PATH_NODE* CPath::isNodeInList(unsigned long X, unsigned long Y, unsigned long Z) {      unsigned long cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if (this->node_list[cptr]->point.x == X && this->node_list[cptr]->point.y == Y && this->node_list[cptr]->point.z == Z)                return this->node_list[cptr];      }      return NULL; } //Calcule F = G + H du noeud passé en argument void CPath::setFGH(PATH_NODE* Son) {      if (Son->parent == NULL)      {           Son->H = 0;           Son->G = 0;           Son->F = 0;      }      else      {           if (!this->is_3D)           {                Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)) * 10;                if (this->search_mode == PATH_short)                {                     if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 2)                          Son->G = 14 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 1)                          Son->G = 10 + ((PATH_NODE*)Son->parent)->G;                }                else                {                     if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 2)                          Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x]*14 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 1)                          Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x]*10 + ((PATH_NODE*)Son->parent)->G;                }           }           else           {                if (this->search_mode == PATH_short)                {                     Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)+abs(Son->point.z - this->end_point.z)) * 10;                     if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 3)                          Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*17 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 2)                          Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*14 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 1)                          Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*10 + ((PATH_NODE*)Son->parent)->G;                }                else                {                     Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)+abs(Son->point.z - this->end_point.z)) * 10;                     if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 3)                          Son->G = 17 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 2)                          Son->G = 14 + ((PATH_NODE*)Son->parent)->G;                     else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 1)                          Son->G = 10 + ((PATH_NODE*)Son->parent)->G;                }           }           Son->F = Son->G + Son->H;      } } // Renvoi vrai si le nouveau parent du noeud est meilleur que l'ancien bool CPath::isNewFGHBetterThanOld(unsigned long X, unsigned long Y, PATH_NODE* old, PATH_NODE* parent) {      if (old->parent == parent)           return false;      unsigned long newG = 0;      if (this->search_mode == PATH_short)      {           if (parent->point.x == X && parent->point.y == Y)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 2)                newG = this->map.data[Y*this->map.width+X]*14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 1)                newG = this->map.data[Y*this->map.width+X]*10 + parent->G;      }      else      {           if (parent->point.x == X && parent->point.y == Y)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 2)                newG = 14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 1)                newG = 10 + parent->G;      }      if (newG < old->G)           return true;      return false; } bool CPath::isNewFGHBetterThanOld(unsigned long X, unsigned long Y, unsigned long Z, PATH_NODE* old, PATH_NODE* parent) {      if (old->parent == parent)           return false;      unsigned long newG = 0;      if (this->search_mode == PATH_short)      {           if (parent->point.x == X && parent->point.y == Y && parent->point.z == Z)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 3)                newG = 17 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 2)                newG = 14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 1)                newG = 10 + parent->G;      }      else      {           if (parent->point.x == X && parent->point.y == Y && parent->point.z == Z)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 3)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*17 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 2)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 1)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*10 + parent->G;      }      if (newG < old->G)           return true;      return false; } PATH_BOOL CPath::search( void ) {      if ( !this->isInitialized() )      {           this->addNewError("The object is not initialized");           return PATH_error;      }      if ( this->is_Searched )      {           this->addNewError("The search have already been done");           return PATH_error;      }      if (!this->is_3D)      {           if (!this->isGoodWay(this->end_point.x, this->end_point.y))                return PATH_false;      }      else      {           if (!this->isGoodWay(this->end_point.x, this->end_point.y, this->end_point.z))                return PATH_false;      }      PATH_NODE* PATH_current_node,* temp;      int ligne, colonne, etage;      do      {           //Récuperer le meilleur noeud de la PATH_node_liste ouverte           if ((PATH_current_node = getBestNode()) != NULL)           {                // Le mettre dans la PATH_node_liste fermée                PATH_current_node->isClosed = true;                // Analyser ses 8 voisins                for(ligne = -1; ligne < 2; ++ligne)                {                     for(colonne = -1; colonne < 2; ++colonne)                     {                          if (this->is_3D)                          {                               for(etage = -1; etage < 2; ++etage)                               {                                    temp = this->isNodeInList(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage);                                    if (temp == NULL)                                    {                                         this->add_node(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage, PATH_current_node);                                    }                                    else                                    //Sinon                                    {                                         if (this->isNewFGHBetterThanOld(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage,temp,PATH_current_node))                                         {                                              temp->parent = PATH_current_node;                                              if (temp->isClosed == false)                                                   this->setFGH(temp);                                         }                                    }                               }                          }                          else                          {                               temp = isNodeInList(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne);                               if (temp == NULL)                               {                                    this->add_node(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node);                               }                               else                               {                                    if (isNewFGHBetterThanOld(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne,temp,PATH_current_node))                                    {                                         temp->parent = PATH_current_node;                                         if (temp->isClosed == false)                                              this->setFGH(temp);                                    }                               }                          }                     }                }           }      }      while(this->node_end == NULL && (PATH_current_node = getBestNode()) != NULL);      is_Searched = true;      if (this->node_end == NULL)           return (PATH_BOOL)(this->is_Success = false);      buildFullPath();      return (PATH_BOOL)(this->is_Success = true); } void CPath::buildFullPath() {      if (this->node_end == NULL)           return;      PATH_NODE* temp = this->node_end;      this->node_end->son = NULL;      do      {           ((PATH_NODE*)temp->parent)->son = temp;           temp = (PATH_NODE*)temp->parent;      }      while (temp->parent != NULL); } bool CPath::isGoodWay(unsigned long X, unsigned long Y) {      if (Y >= this->map.height || X >= this->map.width)           return false;      return this->map.data[Y*this->map.width+X]; } bool CPath::isGoodWay(unsigned long X, unsigned long Y, unsigned long Z) {      if (Y >= this->map.height || X >= this->map.width || Z >= this->map.deep)           return false;      return this->map.data[Y*this->map.width+X*this->map.height+Z]; } void CPath::freePath ( void ) {      if (this->isInitialized() == false)           return;      this->node_end = NULL;      this->node_current = NULL;      this->is_3D = false;      this->is_Searched = false;      this->map.data = NULL;      this->map.width = 0;      this->map.height = 0;      this->start_point.x = 0;      this->start_point.y = 0;      this->end_point.x = 0;      this->end_point.y = 0;      this->use_hv_move_only = false;      this->search_mode = PATH_short;      this->is_MapInitialized = false;      this->is_StartPointInitialized = false;      this->is_EndPointInitialized = false;      this->clearAllNodes();      this->clearAllErrors(); } PATH_BOOL CPath::isSuccess ( void ) {      if ( !this->is_Searched )      {           this->addNewError("The search have not been done");           return PATH_error;      }      return (PATH_BOOL)this->is_Success; } PATH_BOOL CPath::getFirstPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_list[0]->point.x;      value->y = this->node_list[0]->point.y;      value->z = this->node_list[0]->point.z;      return PATH_true; } PATH_BOOL CPath::getLastPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_end->point.x;      value->y = this->node_end->point.y;      value->z = this->node_end->point.z;      return PATH_true; } PATH_BOOL CPath::getCurrentPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_current->point.x;      value->y = this->node_current->point.y;      value->z = this->node_current->point.z;      return PATH_true; } PATH_BOOL CPath::gotoNextPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      if (this->node_current->son == NULL)           return PATH_false;      this->node_current = (PATH_NODE*)this->node_current->son;      return PATH_true; } PATH_BOOL CPath::gotoPreviousPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      if (this->node_current->parent == NULL)           return PATH_false;      this->node_current = (PATH_NODE*)this->node_current->parent;      return PATH_true; } PATH_BOOL CPath::gotoFirstPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      this->node_current = this->node_list[0];      return PATH_true; } PATH_BOOL CPath::gotoLastPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      this->node_current = this->node_end;      return PATH_true; } PATH_BOOL CPath::setStartPoint( PATH_POINT* value ) {      if (this->is_Searched)      {           this->addNewError("You need to free the object before changing start point");           return PATH_error;      }      if ( value->x > this->map.width || value->y > this->map.height || value->z > this->map.deep )      {           this->addNewError("The new point is out of the map");           return PATH_error;      }      if (this->is_3D)      {           if ( !this->isGoodWay(value->x, value->y, value->z) )           {                this->addNewError("The new point is not a good point");                return PATH_error;           }           if ( value->x == this->end_point.x && value->y == this->end_point.y && value->z == this->end_point.z )           {                this->addNewError("The new start point is the same as the final one");                return PATH_error;           }      }      else      {           if ( !this->isGoodWay(value->x, value->y) )           {                this->addNewError("The new point is not a good point");                return PATH_error;           }           if ( value->x == this->end_point.x && value->y == this->end_point.y )           {                this->addNewError("The new start point is the same as the final one");                return PATH_error;           }      }      //this->clearAllNodes();      this->start_point.x = value->x;      this->start_point.y = value->y;      this->start_point.z = value->z;      this->node_list[0]->point.x = value->x;      this->node_list[0]->point.y = value->y;      this->node_list[0]->point.z = value->z;      if (this->node_number == 0 && this->is_3D);           this->add_node(this->start_point.x, this->start_point.y, NULL);      if (this->node_number == 0 && !this->is_3D);           this->add_node(this->start_point.x, this->start_point.y, this->start_point.z, NULL);      this->is_StartPointInitialized = true;      return PATH_true; } PATH_BOOL CPath::setEndPoint( PATH_POINT* value ) {      if (this->is_Searched)      {           this->addNewError("You need to free the object before changing final point");           return PATH_error;      }      if ( value->x > this->map.width || value->y > this->map.height || value->z > this->map.deep )      {           this->addNewError("The new point is out of the map");           return PATH_error;      }      if (this->is_3D)      {           if ( !this->isGoodWay(value->x, value->y, value->z) )           {                this->addNewError("The new point is not a good point");                return PATH_error;           }           if ( value->x == this->start_point.x && value->y == this->start_point.y && value->z == this->start_point.z )           {                this->addNewError("The new final point is the same as the start one");                return PATH_error;           }      }      else      {           if ( !this->isGoodWay(value->x, value->y) )           {                this->addNewError("The new point is not a good point");                return PATH_error;           }           if ( value->x == this->start_point.x && value->y == this->start_point.y )           {                this->addNewError("The new final point is the same as the start one");                return PATH_error;           }      }      this->end_point.x = value->x;      this->end_point.y = value->y;      this->end_point.z = value->z;      if (this->node_number == 0 && this->is_3D);           this->add_node(this->end_point.x, this->end_point.y, NULL);      if (this->node_number == 0 && !this->is_3D);           this->add_node(this->end_point.x, this->end_point.y, this->end_point.z, NULL);      this->is_EndPointInitialized = true;      return PATH_true; } PATH_BOOL CPath::setNewMap( unsigned long width , unsigned long height , unsigned int* map ) {      if (this->is_Searched)      {           this->addNewError("You need to free the object before changing the map");           return PATH_error;      }      if ( this->start_point.x > width || this->start_point.y > height )      {           this->addNewError("The start point is out of the new map");           return PATH_error;      }      if ( this->end_point.x > width || this->end_point.y > height )      {           this->addNewError("The final point is out of the new map");           return PATH_error;      }      if ( width == 0 || height == 0 || map == NULL)      {           this->addNewError("The size of the new map is not valid or data are void");           return PATH_error;      }      if ( this->is_3D )      {           this->addNewError("This is the 2D function but the object is set as 3D");           return PATH_error;      }      this->map.width = width;      this->map.height = height;      this->map.data = map;      this->is_MapInitialized = true;      return PATH_true; } PATH_BOOL CPath::setNewMap( unsigned long width , unsigned long height , unsigned long deep , unsigned int* map ) {      if (this->is_Searched)      {           this->addNewError("You need to free the object before changing the map");           return PATH_error;      }      if ( this->start_point.x > width || this->start_point.y > height || this->start_point.z > deep )      {           this->addNewError("The start point is out of the new map");           return PATH_error;      }      if ( this->end_point.x > width || this->end_point.y > height || this->end_point.z > deep )      {           this->addNewError("The final point is out of the new map");           return PATH_error;      }      if ( width == 0 || height == 0 || deep == 0 || map == NULL)      {           this->addNewError("The size of the new map is not valid or data are void");           return PATH_error;      }      if ( !this->is_3D )      {           this->addNewError("This is the 3D function but the object is set as 2D");           return PATH_error;      }      this->map.width = width;      this->map.height = height;      this->map.deep = deep;      this->map.data = map;      this->is_MapInitialized = true;      return PATH_true; } PATH_BOOL CPath::setSearchMode( PATH_MODE mode ) {      this->search_mode = mode;      return PATH_true; } PATH_BOOL CPath::setHVMode( bool mode ) {      this->use_hv_move_only = mode;      return PATH_true; } PATH_BOOL CPath::set3DMode( bool mode ) {      this->is_3D = mode;      return PATH_true; } PATH_BOOL CPath::getStartPoint( PATH_POINT* value ) {      if ( !this->is_StartPointInitialized )      {           this->addNewError("The start point is not initialized");           return PATH_error;      }      *value = this->start_point;      return PATH_true; } PATH_BOOL CPath::getEndPoint( PATH_POINT* value ) {      if ( !this->is_EndPointInitialized )      {           this->addNewError("The final point is not initialized");           return PATH_error;      }      *value = this->end_point;      return PATH_true; } PATH_BOOL CPath::getMapSize( unsigned long* width , unsigned long* height ) {      if ( !this->is_MapInitialized )      {           this->addNewError("The map is not initialized");           return PATH_error;      }      if ( this->is_3D )      {           this->addNewError("This is the 2D function but the object is set as 3D");           return PATH_error;      }      *width = this->map.width;      *height = this->map.height;      return PATH_true; } PATH_BOOL CPath::getMapSize( unsigned long* width , unsigned long* height , unsigned long* deep ) {      if ( !this->is_MapInitialized )      {           this->addNewError("The map is not initialized");           return PATH_error;      }      if ( !this->is_3D )      {           this->addNewError("This is the 3D function but the object is set as 2D");           return PATH_error;      }      *width = this->map.width;      *height = this->map.height;      *deep = this->map.deep;      return PATH_true; } PATH_BOOL CPath::getSearchMode( PATH_MODE* value ) {      return (PATH_BOOL)this->search_mode; } PATH_BOOL CPath::getHVMode( void ) {      return (PATH_BOOL)this->use_hv_move_only; } PATH_BOOL CPath::get3DMode( void ) {      return (PATH_BOOL)this->is_3D; } bool CPath::isInitialized ( void ) {      return ( this->is_MapInitialized && this->is_StartPointInitialized && this->is_EndPointInitialized ); } const char* CPath::getError( unsigned long num ) {      if ( this->error_number == 0 )           return false;      if ( num > this->error_number )           return false;      return this->error_list[num]; } unsigned long CPath::getErrorNumber( void ) {      return this->error_number; } bool CPath::addNewError( const char* msg ) {      if (!(this->error_list = (char**)realloc(this->error_list,(this->error_number+1)*sizeof(char*))))           return false;      if (!(this->error_list[this->error_number] = (char*)malloc(sizeof(char)*(strlen(msg)+1))))      {           this->error_list = (char**)realloc(this->error_list,this->error_number*sizeof(char*));           return false;      }      strcpy(error_list[this->error_number],msg);      ++(this->error_number);      return true; } void CPath::clearAllErrors( void ) {      unsigned long cptr;      if ((this->error_number))      {           for (cptr = 0; cptr < this->error_number; ++cptr)                free(this->error_list[cptr]);           free(this->error_list);      }      this->error_number = 0; } void CPath::clearAllNodes( void ) {      unsigned int cptr;      if ((this->node_number))      {           for (cptr = 0; cptr < this->node_number; ++cptr)                free(this->node_list[cptr]);           free(this->node_list);      }      this->node_number = 0; }

J'ai trouvé quelques bugs (dont certains qui font planter le programme) mais dans l'ensemble ça fonctionne bien.

Je mets des exemples d'utilisation bientôt.
Pour le moment je n'ai que celui-ci : //  --------------------------------------------------------------------------------------- // //                A* Path Finding Demo                                                      // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project:                                                                                 // // ---------------------------------------------------------------------------------------- // //Inclusion des librairies de base #include <stdlib.h> #include <stdio.h> //Inclusion de la classe #include "../path.h" int main(int argc, char *argv[]); //La carte utilisée //Elle fait 10 de large pour 10 de haut unsigned int map[] = {                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,0,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,}; int main(int argc, char *argv[]) {      //On a besoin des coordonnées de départ et d'arrivée (4 arg) + méthode de recherche (rapide ou meilleur) + utilisation ou non des seuls mouvements verticaux      if (argc != 7)      {           printf("Usage : demo Xstart Ystart Xend Yend search_mode hv_only\n\n \                     search_mode : 0 or 1\n \                     hv_only : 0 or 1\n\n");           exit(EXIT_FAILURE);      }      //On créé l'objet      CPath chemin(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), 10, 10, (unsigned int*)&map, (PATH_MODE)atoi(argv[5]), atoi(argv[6]));      //On affiche un texte simple en utilisant les fonctions de la classe      printf("%s version %s\n%s\n\n",chemin.getName(),chemin.getVersion(),chemin.getCopyright());      if (chemin.isInitialized())      {           //On lance la recherche           if (chemin.search() == PATH_true)           {                //Et si ça marche on affiche les points du chemin                printf("I found a way!\n");                PATH_POINT result;                chemin.getFirstPoint(&result);                printf("{%i,%i}\n",result.x,result.y);                while ( chemin.gotoNextPoint() )                {                     chemin.getCurrentPoint(&result);                     printf("{%i,%i}\n",result.x,result.y);                }           }           else           {                printf("I did not found any way!\n");           }      }      printf("Nombre d'erreur(s) : %i\n",chemin.getErrorNumber());      unsigned long compteur;      for (compteur=0;compteur<chemin.getErrorNumber();compteur++)      {           printf("\tErreur n°%i : %s\n",compteur+1,chemin.getError(compteur));      }      exit(1); }

2

ça m'intéresse. je vais le porter en java (pas trop dur smile )

3

Sinon, pour ca (problemes de graphes), la BGL (Boost Graph Library) est vraiment bien !

http://www.boost.org/libs/graph/doc/AStarVisitor.html

4

En fait pour ce qui est de la représentation graphique je souhaiterai plutôt utiliser cette classe avec OpenGL.
D'autant plus que je ne connais pas la BGL et que la classe permet des calculs 3D.

D'ailleurs à ce sujet je vais diviser la classe en 2 : une 2D et une 3D
Il y a le test "if(this->is_3D)" qui se trouve dans la boucle de recherche et donc qui est inutilement répété.

5

t'aurais pu avoir un objet qui a pour but de traiter uniquement le graphe (avec la structure de donnée et qq algos - plugés en foncteurs ?) et puis des classes de represetnation...

6

oué mais en 2D 3D les coordinences sont pas les mêmes donc dans la fonction qui teste les voisins, on doit distinguer 2D ou 3D, donc ça ralentit et il vaut mieux séparer smile

7

mumble templates mumble inline mumble...

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

8

^^
programmtion générique rulez

9

squalyl^2 :
oué mais en 2D 3D les coordinences sont pas les mêmes donc dans la fonction qui teste les voisins, on doit distinguer 2D ou 3D, donc ça ralentit et il vaut mieux séparer smile

Oui c'est pour ça que je vais séparer en 2 classes.
Dans la version C j'utilisais #define USE_3D. Qu'il soit défini ou non, les fonctions étaient optimisée. Là ce n'est plus le cas.
Pollux :
mumble templates mumble inline mumble...
spectras :
^^
programmtion générique rulez

Je n'y ai jamais touché a vrai dire. J'avoue que ça me rebute encore un peu... sick

10

c'est bien dommage... ca facilite bien des choses (genre la maintenabilité)

11

Je viens de faire un deuxième exemple.
Cette fois-ci il génère une map aléatoire de 70x70 et l'affiche au moyen d'OpenGL (oui ça sert à rien mais depuis le temps que je voulais m'y mettre aussi...)
#include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <time.h> #include "../path.h" #define ESCAPE 27 int window; #define MAP_W 70 #define MAP_H 70 unsigned int map[MAP_H*MAP_W]; CPath *chemin_ = NULL; unsigned int max (unsigned int a, unsigned int b) {      if (a > b)           return a;      else           return b; } void InitGL(int Width, int Height)             // We call this right after our OpenGL window is created. {      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);          // This Will Clear The Background Color To Black      glClearDepth(1.0);                    // Enables Clearing Of The Depth Buffer      glDepthFunc(GL_LESS);                    // The Type Of Depth Test To Do      glEnable(GL_DEPTH_TEST);               // Enables Depth Testing      glShadeModel(GL_SMOOTH);               // Enables Smooth Color Shading      glMatrixMode(GL_PROJECTION);      glLoadIdentity();                    // Reset The Projection Matrix      gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);     // Calculate The Aspect Ratio Of The Window      glMatrixMode(GL_MODELVIEW); } /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ void ReSizeScene(int Width, int Height) {      if (Height==0)                    // Prevent A Divide By Zero If The Window Is Too Small           Height=1;      glViewport(0, 0, Width, Height);          // Reset The Current Viewport And Perspective Transformation      glMatrixMode(GL_PROJECTION);      glLoadIdentity();      gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW); } void DrawQuad(unsigned long x, unsigned long y) {      glBegin(GL_QUADS);           glVertex3f(x,MAP_H-(y),0.0f);           glVertex3f(x,MAP_H-(y+1),0.0f);           glVertex3f(x+1,MAP_H-(y+1),0.0f);           glVertex3f(x+1,MAP_H-(y),0.0f);      glEnd(); } /* The main drawing function. */ void DrawScene() {      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      glLoadIdentity();      glColor3f(0.0f,1.0f,0.0f);      glTranslatef((GLfloat)(MAP_W/-2.0f),(GLfloat)(MAP_H/-2.0f),(GLfloat)(-1.3f*max(MAP_H,MAP_W)));      glBegin(GL_LINES);      for (unsigned int width_ = 0;width_ <= MAP_W; width_++)      {           glVertex3f(width_,0,0.0f);           glVertex3f(width_,MAP_H,0.0f);      }      glEnd();      glBegin(GL_LINES);      for (unsigned int height_ = 0;height_ <= MAP_H; height_++)      {           glVertex3f(0,height_,0.0f);           glVertex3f(MAP_W,height_,0.0f);      }      glEnd();      glColor3f(1.0f,0.0f,0.0f);      for (unsigned int width_ = 0;width_ < MAP_W; width_++)      {           for (unsigned int height_ = 0;height_ < MAP_H; height_++)           {                if (map[height_*MAP_W+width_] == 0)                     DrawQuad(width_,height_);           }      }      glColor3f(0.0f,0.0f,1.0f);      PATH_POINT result;      chemin_->gotoFirstPoint();      do      {           chemin_->getCurrentPoint(&result);           DrawQuad(result.x,result.y);      }      while ( chemin_->gotoNextPoint() );      // we need to swap the buffer to display our drawing.      glutSwapBuffers(); } /* The function called whenever a key is pressed. */ void keyPressed(unsigned char key, int x, int y)  {      /* sleep to avoid thrashing this procedure */      usleep(100);      /* If escape is pressed, kill everything. */      if (key == ESCAPE)      {            /* shut down our window */           glutDestroyWindow(window);                  /* exit the program...normal termination. */           exit(0);                        } } int main(int argc, char** argv) {      if (argc != 7)      {           printf("Usage : demo Xstart Ystart Xend Yend search_mode hv_only\n\n \                     search_mode : 0 or 1\n \                     hv_only : 0 or 1\n\n");           exit(EXIT_FAILURE);      }      //Randomize function      time_t t;      srand((unsigned) time(&t));      for (unsigned int cptr = 0 ; cptr<MAP_W*MAP_H;cptr++)      {           map[cptr]=1;           short test=rand();           if (test < 20000)                map[cptr]=1;           else                map[cptr]=0;      }      CPath chemin(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), MAP_W, MAP_H, (unsigned int*)&map, (PATH_MODE)atoi(argv[5]), atoi(argv[6]));      //On affiche un texte simple en utilisant les fonctions de la classe      printf("%s version %s\n%s\n\n",chemin.getName(),chemin.getVersion(),chemin.getCopyright());      if (chemin.isInitialized())      {           //On lance la recherche           if (chemin.search() == PATH_true)           {                chemin_ = &chemin;                glutInit(&argc, argv);                glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);                glutInitWindowSize(640, 480);                glutInitWindowPosition(0, 0);                window = glutCreateWindow("Demo number 2 (Spomky.Dev)");                glutDisplayFunc(&DrawScene);                glutFullScreen();                glutIdleFunc(&DrawScene);                glutReshapeFunc(&ReSizeScene);                glutKeyboardFunc(&keyPressed);                InitGL(640, 480);                glutMainLoop();           }           else           {                printf("I did not found any way!\n");           }      }      else      {           printf("I can not initialize!\n");      }      return 0; }

lglut -lGL -lGLUPour compiler : g++ demo2.cpp ../path.cpp -I/usr/include/ -L/usr/X11R6/lib -
: Xdébut Ydébut Xfin Yfin 0 HVLes paramètres pour exécuter

*le 5ième argument ne sert pas ici
*HV est soit 0 soit 1, s'il vaut 1 le path finding ne pourra faire que des déplacements horizontaux et verticaux

En bleu le chemin, en rouge les obstacles
capture3.png
NOTA : Je vais faire un exemple avec une map 3D pour voir si tout va bien
EDIT : capture d'écran et fautes

12

affichée en opengl avec des cubes transparents? oui

13

Un truc comme ça?
capture4.png

J'ai modifié les classes.
Il y en a deux maintenant : CPath2D et CPath3D
Elles sont liées à une claase mère CPath qui contient les fonctions communes

Les codes sources ndif path.h//  --------------------------------------------------------------------------------------- // //                A* Path Finding C++ Class                                                 // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project: The API project for C and C++ programming (A.I.)                                // // ---------------------------------------------------------------------------------------- // #ifndef PATH_H      #define PATH_H      #include <stdlib.h>      #include <string.h>      /*MACRO*/      /*ENUMERATIONS*/      enum PATH_MODE {PATH_short = 0, PATH_best};      enum PATH_BOOL {PATH_error = -1, PATH_false, PATH_true};      /*STRUCTURES*/      typedef struct      {           unsigned long x;           unsigned long y;           unsigned long z;      }PATH_POINT;      typedef struct      {           unsigned int *data;           unsigned long width;           unsigned long height;           unsigned long deep;      }PATH_MAP;      typedef struct      {           void* parent;           void* son;           unsigned long F;           unsigned long G;           unsigned long H;           PATH_POINT point;           bool isClosed;      }PATH_NODE;      class CPath      {           public:                /*COMMUN*/                //CPath( );                ~CPath( );                //Retourne true si l'objet est initialisé                bool isInitialized( void );                //Informations au sujet de la classe                char* getName ( void ){ return "A* Path Finding C++";};                char* getVersion ( void ){ return "2.0.3.0";};                char* getCopyright ( void ){ return "Copyright (c) 2005 Spomky.Dev (http://www.spomky.com/)";};                //Retourne true si la recherche a été fructueuse                PATH_BOOL isSuccess ( void );                //Efface la recherche                void freePath ( void );                //Retourne le point de départ                PATH_BOOL getStartPoint( PATH_POINT* );                //Retourne le point d'arrivé                PATH_BOOL getEndPoint( PATH_POINT* );                //Retourne le mode de recherche                PATH_BOOL getSearchMode( PATH_MODE* );                //Retourne la limite H&V                PATH_BOOL getHVMode( void );                //Fonctions permettant de récupérer les points du chemin trouvé                PATH_BOOL getFirstPoint( PATH_POINT* );                PATH_BOOL getLastPoint( PATH_POINT* );                PATH_BOOL getCurrentPoint( PATH_POINT* );                PATH_BOOL gotoFirstPoint( void );                PATH_BOOL gotoLastPoint( void );                PATH_BOOL gotoNextPoint( void );                PATH_BOOL gotoPreviousPoint( void );                //Fonctions permettant de naviguer parmi les erreurs                const char* getError( unsigned long );                unsigned long getErrorNumber( void );                void clearAllErrors( void );           protected:                /*COMMUN*/                /*Pour le calcul*/                PATH_NODE* getBestNode( void );                void buildFullPath( void );                PATH_MAP map;                PATH_MODE search_mode;                PATH_POINT start_point;                PATH_POINT end_point;                bool use_hv_move_only;                /*Pour la recherche*/                PATH_NODE** node_list;                PATH_NODE* node_end;                PATH_NODE* node_current;                unsigned long node_number;                /*Pour les vérifications*/                bool is_Searched;                bool is_Success;                bool is_MapInitialized;                bool is_StartPointInitialized;                bool is_EndPointInitialized;                /*Pour les erreurs*/                bool addNewError( const char* );                char **error_list;                unsigned long error_number;                /*Autres*/                void clearAllNodes( void );      };      class CPath2D : public CPath      {           public:                CPath2D ( unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned int* , PATH_MODE = PATH_best , bool = false );                //Lance la recherche                PATH_BOOL search( void );                //Change la carte et ses dimensions                PATH_BOOL setNewMap( unsigned long , unsigned long , unsigned int* );                //Retourne les dimensions de la carte                PATH_BOOL getMapSize( unsigned long* , unsigned long* );           private:                bool isGoodWay(unsigned long, unsigned long);                PATH_NODE* add_node(unsigned long, unsigned long, PATH_NODE*);                PATH_NODE* isNodeInList(unsigned long, unsigned long);                bool isNewFGHBetterThanOld(unsigned long, unsigned long, PATH_NODE*, PATH_NODE*);                void setFGH( PATH_NODE* );      };      class CPath3D : public CPath      {           public:                CPath3D ( unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned long , unsigned int* , PATH_MODE = PATH_best , bool = false );                //Lance la recherche                PATH_BOOL search( void );                //Change la carte et ses dimensions                PATH_BOOL setNewMap( unsigned long , unsigned long , unsigned long , unsigned int* );                //Retourne les dimensions de la carte                PATH_BOOL getMapSize( unsigned long* , unsigned long* , unsigned long* );           private:                bool isGoodWay(unsigned long, unsigned long, unsigned long);                PATH_NODE* add_node(unsigned long, unsigned long, unsigned long, PATH_NODE*);                PATH_NODE* isNodeInList(unsigned long, unsigned long, unsigned long);                bool isNewFGHBetterThanOld(unsigned long, unsigned long, unsigned long, PATH_NODE*, PATH_NODE*);                void setFGH( PATH_NODE* );      }; #e  0; } path.cpp//  --------------------------------------------------------------------------------------- // //                A* Path Finding C++ Class                                                 // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project: The API project for C and C++ programming (A.I.)                                // // ---------------------------------------------------------------------------------------- // #include "path.h" CPath2D::CPath2D ( unsigned long Xs, unsigned long Ys, unsigned long Xe, unsigned long Ye, unsigned long width, unsigned long height, unsigned int *map, PATH_MODE mode, bool hv_move ) {      if ( map == NULL || width == 0 || height == 0 )           return;      this->node_list = NULL;      this->node_end = NULL;      this->node_number = 0;      this->map.data = map;      this->map.width = width;      this->map.height = height;      this->start_point.x = Xs;      this->start_point.y = Ys;      this->end_point.x = Xe;      this->end_point.y = Ye;      this->use_hv_move_only = hv_move;      this->search_mode = mode;      this->error_number = 0;      this->error_list = NULL;      this->is_Searched = false;      if( this->add_node(this->start_point.x, this->start_point.y, NULL) )      {           this->is_MapInitialized = true;           this->is_StartPointInitialized = true;           this->is_EndPointInitialized = true;           this->node_current = this->node_list[0];           return;      }      return; } CPath3D::CPath3D ( unsigned long Xs, unsigned long Ys, unsigned long Zs, unsigned long Xe, unsigned long Ye, unsigned long Ze, unsigned long width, unsigned long height, unsigned long deep, unsigned int *map, PATH_MODE mode, bool hv_move ) {      if ( map == NULL || width == 0 || height == 0  || deep == 0 )           return;      this->node_list = NULL;      this->node_end = NULL;      this->node_number = 0;      this->map.data = map;      this->map.width = width;      this->map.height = height;      this->map.deep = deep;      this->start_point.x = Xs;      this->start_point.y = Ys;      this->start_point.z = Zs;      this->end_point.x = Xe;      this->end_point.y = Ye;      this->end_point.z = Ze;      this->use_hv_move_only = hv_move;      this->search_mode = mode;      this->is_Searched = false;      if ( this->add_node(this->start_point.x, this->start_point.y, this->start_point.z, NULL) )      {           this->is_MapInitialized = true;           this->is_StartPointInitialized = true;           this->is_EndPointInitialized = true;           this->node_current = this->node_list[0];           return;      }      return; } CPath::~CPath ( ) {      this->freePath(); } PATH_NODE* CPath2D::add_node(unsigned long x, unsigned long y, PATH_NODE* parent) {      bool isgoodpath;      if (this->use_hv_move_only)      {           if (parent != NULL && abs(x-parent->point.x)+abs(y-parent->point.y) != 1)                return NULL;      }      if ((isgoodpath = !this->isGoodWay(x,y)))           return NULL;      if (!(this->node_list = (PATH_NODE**)realloc(this->node_list,(this->node_number+1)*sizeof(PATH_NODE*))))           return NULL;      if (!(this->node_list[this->node_number] = (PATH_NODE*)malloc(sizeof(PATH_NODE))))      {           this->node_list = (PATH_NODE**)realloc(this->node_list,this->node_number*sizeof(PATH_NODE*));           return NULL;      }      this->node_list[this->node_number]->parent = parent;      this->node_list[this->node_number]->point.x = x;      this->node_list[this->node_number]->point.y = y;      this->node_list[this->node_number]->isClosed = isgoodpath;      if (x ==this->end_point.x && y == this->end_point.y)           this->node_end = this->node_list[this->node_number];      this->setFGH(this->node_list[this->node_number]);      ++(this->node_number);      return this->node_list[this->node_number-1]; } PATH_NODE* CPath3D::add_node(unsigned long x, unsigned long y, unsigned long z, PATH_NODE* parent) {      bool isgoodpath;      if (this->use_hv_move_only)      {           if (parent != NULL && abs(x-parent->point.x)+abs(y-parent->point.y)+abs(z-parent->point.z) != 1)                return NULL;      }      if ((isgoodpath = !this->isGoodWay(x,y,z)))           return NULL;      if (!(this->node_list = (PATH_NODE**)realloc(this->node_list,(this->node_number+1)*sizeof(PATH_NODE*))))           return NULL;      if (!(this->node_list[this->node_number] = (PATH_NODE*)malloc(sizeof(PATH_NODE))))      {           this->node_list = (PATH_NODE**)realloc(this->node_list,this->node_number*sizeof(PATH_NODE*));           return NULL;      }      this->node_list[this->node_number]->parent = parent;      this->node_list[this->node_number]->point.x = x;      this->node_list[this->node_number]->point.y = y;      this->node_list[this->node_number]->point.z = z;      this->node_list[this->node_number]->isClosed = isgoodpath;      if (x == this->end_point.x && y == this->end_point.y && z == this->end_point.z )           this->node_end = this->node_list[this->node_number];      this->setFGH(this->node_list[this->node_number]);      ++(this->node_number);      return this->node_list[this->node_number-1]; } PATH_NODE* CPath::getBestNode( void ) {      if (this->node_number == 0)           return NULL;      PATH_NODE* found = NULL;      unsigned int cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if ((found != NULL && this->node_list[cptr]->isClosed == false && found->F > this->node_list[cptr]->F) || (found == NULL && this->node_list[cptr]->isClosed == false))                found = this->node_list[cptr];      }      return found; } PATH_NODE* CPath2D::isNodeInList(unsigned long X, unsigned long Y) {      unsigned long cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if (this->node_list[cptr]->point.x == X && this->node_list[cptr]->point.y == Y)                return this->node_list[cptr];      }      return NULL; } PATH_NODE* CPath3D::isNodeInList(unsigned long X, unsigned long Y, unsigned long Z) {      unsigned long cptr;      for (cptr = 0; cptr < this->node_number; ++cptr)      {           if (this->node_list[cptr]->point.x == X && this->node_list[cptr]->point.y == Y && this->node_list[cptr]->point.z == Z)                return this->node_list[cptr];      }      return NULL; } //Calcule F = G + H du noeud passé en argument void CPath2D::setFGH(PATH_NODE* Son) {      if (Son->parent == NULL)      {           Son->H = 0;           Son->G = 0;           Son->F = 0;      }      else      {           Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)) * 10;           if (this->search_mode == PATH_short)           {                if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 2)                     Son->G = 14 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 1)                     Son->G = 10 + ((PATH_NODE*)Son->parent)->G;           }           else           {                if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 2)                     Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x]*14 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) == 1)                     Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x]*10 + ((PATH_NODE*)Son->parent)->G;           }           Son->F = Son->G + Son->H;      } } //Calcule F = G + H du noeud passé en argument void CPath3D::setFGH(PATH_NODE* Son) {      if (Son->parent == NULL)      {           Son->H = 0;           Son->G = 0;           Son->F = 0;      }      else      {           if (this->search_mode == PATH_short)           {                Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)+abs(Son->point.z - this->end_point.z)) * 10;                if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 3)                     Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*17 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 2)                     Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*14 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 1)                     Son->G = this->map.data[Son->point.y*this->map.width+Son->point.x*this->map.height+Son-> point.z]*10 + ((PATH_NODE*)Son->parent)->G;           }           else           {                Son->H = (abs(Son->point.x - this->end_point.x)+abs(Son->point.y - this->end_point.y)+abs(Son->point.z - this->end_point.z)) * 10;                if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 3)                     Son->G = 17 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 2)                     Son->G = 14 + ((PATH_NODE*)Son->parent)->G;                else if (abs(Son->point.x - ((PATH_NODE*)Son->parent)->point.x) + abs(Son->point.y - ((PATH_NODE*)Son->parent)->point.y) + abs(Son->point.z - ((PATH_NODE*)Son->parent)->point.z) == 1)                     Son->G = 10 + ((PATH_NODE*)Son->parent)->G;           }           Son->F = Son->G + Son->H;      } } // Renvoi vrai si le nouveau parent du noeud est meilleur que l'ancien bool CPath2D::isNewFGHBetterThanOld(unsigned long X, unsigned long Y, PATH_NODE* old, PATH_NODE* parent) {      if (old->parent == parent)           return false;      unsigned long newG = 0;      if (this->search_mode == PATH_short)      {           if (parent->point.x == X && parent->point.y == Y)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 2)                newG = this->map.data[Y*this->map.width+X]*14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 1)                newG = this->map.data[Y*this->map.width+X]*10 + parent->G;      }      else      {           if (parent->point.x == X && parent->point.y == Y)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 2)                newG = 14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) == 1)                newG = 10 + parent->G;      }      if (newG < old->G)           return true;      return false; } bool CPath3D::isNewFGHBetterThanOld(unsigned long X, unsigned long Y, unsigned long Z, PATH_NODE* old, PATH_NODE* parent) {      if (old->parent == parent)           return false;      unsigned long newG = 0;      if (this->search_mode == PATH_short)      {           if (parent->point.x == X && parent->point.y == Y && parent->point.z == Z)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 3)                newG = 17 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 2)                newG = 14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 1)                newG = 10 + parent->G;      }      else      {           if (parent->point.x == X && parent->point.y == Y && parent->point.z == Z)                return false;           if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 3)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*17 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 2)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*14 + parent->G;           else if (abs(parent->point.x - X) + abs(parent->point.y - Y) + abs(parent->point.z - Z) == 1)                newG = this->map.data[Y*this->map.width+X*this->map.height+Z]*10 + parent->G;      }      if (newG < old->G)           return true;      return false; } PATH_BOOL CPath2D::search( void ) {      if ( !this->isInitialized() )      {           this->addNewError("The object is not initialized");           return PATH_error;      }      if ( this->is_Searched )      {           this->addNewError("The search have already been done");           return PATH_error;      }      if (!this->isGoodWay(this->end_point.x, this->end_point.y))           return PATH_false;      PATH_NODE* PATH_current_node,* temp;      int ligne, colonne;      do      {           //Récuperer le meilleur noeud de la PATH_node_liste ouverte           if ((PATH_current_node = getBestNode()) != NULL)           {                // Le mettre dans la PATH_node_liste fermée                PATH_current_node->isClosed = true;                // Analyser ses 8 voisins                for(ligne = -1; ligne < 2; ++ligne)                {                     for(colonne = -1; colonne < 2; ++colonne)                     {                          temp = isNodeInList(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne);                          if (temp == NULL)                          {                               this->add_node(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node);                          }                          else                          {                               if (isNewFGHBetterThanOld(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne,temp,PATH_current_node))                               {                                    temp->parent = PATH_current_node;                                    if (temp->isClosed == false)                                         this->setFGH(temp);                               }                          }                     }                }           }      }      while(this->node_end == NULL && (PATH_current_node = getBestNode()) != NULL);      is_Searched = true;      if (this->node_end == NULL)           return (PATH_BOOL)(this->is_Success = false);      buildFullPath();      return (PATH_BOOL)(this->is_Success = true); } PATH_BOOL CPath3D::search( void ) {      if ( !this->isInitialized() )      {           this->addNewError("The object is not initialized");           return PATH_error;      }      if ( this->is_Searched )      {           this->addNewError("The search have already been done");           return PATH_error;      }      if (!this->isGoodWay(this->end_point.x, this->end_point.y, this->end_point.z))           return PATH_false;      PATH_NODE* PATH_current_node,* temp;      int ligne, colonne, etage;      do      {           //Récuperer le meilleur noeud de la PATH_node_liste ouverte           if ((PATH_current_node = getBestNode()) != NULL)           {                // Le mettre dans la PATH_node_liste fermée                PATH_current_node->isClosed = true;                // Analyser ses 8 voisins                for(ligne = -1; ligne < 2; ++ligne)                {                     for(colonne = -1; colonne < 2; ++colonne)                     {                          for(etage = -1; etage < 2; ++etage)                          {                               temp = this->isNodeInList(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage);                               if (temp == NULL)                               {                                    this->add_node(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage, PATH_current_node);                               }                               else                               //Sinon                               {                                    if (this->isNewFGHBetterThanOld(PATH_current_node->point.x+colonne, PATH_current_node->point.y+ligne, PATH_current_node->point.z+etage,temp,PATH_current_node))                                    {                                         temp->parent = PATH_current_node;                                         if (temp->isClosed == false)                                              this->setFGH(temp);                                    }                               }                          }                     }                }           }      }      while(this->node_end == NULL && (PATH_current_node = getBestNode()) != NULL);      is_Searched = true;      if (this->node_end == NULL)           return (PATH_BOOL)(this->is_Success = false);      buildFullPath();      return (PATH_BOOL)(this->is_Success = true); } void CPath::buildFullPath() {      if (this->node_end == NULL)           return;      PATH_NODE* temp = this->node_end;      this->node_end->son = NULL;      do      {           ((PATH_NODE*)temp->parent)->son = temp;           temp = (PATH_NODE*)temp->parent;      }      while (temp->parent != NULL); } bool CPath2D::isGoodWay(unsigned long X, unsigned long Y) {      if (Y >= this->map.height || X >= this->map.width)           return false;      return this->map.data[Y*this->map.width+X]; } bool CPath3D::isGoodWay(unsigned long X, unsigned long Y, unsigned long Z) {      if (Y >= this->map.height || X >= this->map.width || Z >= this->map.deep)           return false;      return this->map.data[Y*this->map.width+X*this->map.height+Z]; } void CPath::freePath ( void ) { //     if (this->isInitialized() == false) //          return;      this->is_Searched = false;      this->map.width = 0;      this->map.height = 0;      this->start_point.x = 0;      this->start_point.y = 0;      this->end_point.x = 0;      this->end_point.y = 0;      this->use_hv_move_only = false;      this->search_mode = PATH_short;      this->is_MapInitialized = false;      this->is_StartPointInitialized = false;      this->is_EndPointInitialized = false;      this->clearAllNodes();      this->clearAllErrors();      this->map.data = NULL;      this->node_end = NULL;      this->node_current = NULL; } PATH_BOOL CPath::isSuccess ( void ) {      if ( !this->is_Searched )      {           this->addNewError("The search have not been done");           return PATH_error;      }      return (PATH_BOOL)this->is_Success; } PATH_BOOL CPath::getFirstPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_list[0]->point.x;      value->y = this->node_list[0]->point.y;      value->z = this->node_list[0]->point.z;      return PATH_true; } PATH_BOOL CPath::getLastPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_end->point.x;      value->y = this->node_end->point.y;      value->z = this->node_end->point.z;      return PATH_true; } PATH_BOOL CPath::getCurrentPoint( PATH_POINT* value ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      value->x = this->node_current->point.x;      value->y = this->node_current->point.y;      value->z = this->node_current->point.z;      return PATH_true; } PATH_BOOL CPath::gotoNextPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      if (this->node_current->son == NULL)           return PATH_false;      this->node_current = (PATH_NODE*)this->node_current->son;      return PATH_true; } PATH_BOOL CPath::gotoPreviousPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      if (this->node_current->parent == NULL)           return PATH_false;      this->node_current = (PATH_NODE*)this->node_current->parent;      return PATH_true; } PATH_BOOL CPath::gotoFirstPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      this->node_current = this->node_list[0];      return PATH_true; } PATH_BOOL CPath::gotoLastPoint( void ) {      if (!this->is_Searched && !this->is_Success)      {           this->addNewError("The search have not been done or does not succed");           return PATH_error;      }      this->node_current = this->node_end;      return PATH_true; } PATH_BOOL CPath::getStartPoint( PATH_POINT* value ) {      if ( !this->is_StartPointInitialized )      {           this->addNewError("The start point is not initialized");           return PATH_error;      }      *value = this->start_point;      return PATH_true; } PATH_BOOL CPath::getEndPoint( PATH_POINT* value ) {      if ( !this->is_EndPointInitialized )      {           this->addNewError("The final point is not initialized");           return PATH_error;      }      *value = this->end_point;      return PATH_true; } PATH_BOOL CPath2D::getMapSize( unsigned long* width , unsigned long* height ) {      if ( !this->is_MapInitialized )      {           this->addNewError("The map is not initialized");           return PATH_error;      }      *width = this->map.width;      *height = this->map.height;      return PATH_true; } PATH_BOOL CPath3D::getMapSize( unsigned long* width , unsigned long* height , unsigned long* deep ) {      if ( !this->is_MapInitialized )      {           this->addNewError("The map is not initialized");           return PATH_error;      }      *width = this->map.width;      *height = this->map.height;      *deep = this->map.deep;      return PATH_true; } PATH_BOOL CPath::getSearchMode( PATH_MODE* value ) {      return (PATH_BOOL)this->search_mode; } PATH_BOOL CPath::getHVMode( void ) {      return (PATH_BOOL)this->use_hv_move_only; } bool CPath::isInitialized ( void ) {      return ( this->is_MapInitialized && this->is_StartPointInitialized && this->is_EndPointInitialized ); } const char* CPath::getError( unsigned long num ) {      if ( this->error_number == 0 )           return false;      if ( num > this->error_number )           return false;      return this->error_list[num]; } unsigned long CPath::getErrorNumber( void ) {      return this->error_number; } bool CPath::addNewError( const char* msg ) {      if (!(this->error_list = (char**)realloc(this->error_list,(this->error_number+1)*sizeof(char*))))           return false;      if (!(this->error_list[this->error_number] = (char*)malloc(sizeof(char)*(strlen(msg)+1))))      {           this->error_list = (char**)realloc(this->error_list,this->error_number*sizeof(char*));           return false;      }      strcpy(error_list[this->error_number],msg);      ++(this->error_number);      return true; } void CPath::clearAllErrors( void ) {      unsigned long cptr;      if ((this->error_number))      {           for (cptr = 0; cptr < this->error_number; ++cptr)                free(this->error_list[cptr]);           free(this->error_list);      }      this->error_number = 0; } void CPath::clearAllNodes( void ) {      unsigned int cptr;      if ((this->node_number))      {           for (cptr = 0; cptr < this->node_number; ++cptr)                free(this->node_list[cptr]);           free(this->node_list);      }      this->node_number = SS); } demo3.cpp//  --------------------------------------------------------------------------------------- // //                A* Path Finding Demo #3                                                   // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project:                                                                                 // // ---------------------------------------------------------------------------------------- // #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <time.h> #include "../path.h" #define ESCAPE 27 int window; #define MAP_W 10 #define MAP_H 10 #define MAP_D 10 unsigned int map[MAP_H*MAP_W*MAP_D]; CPath3D *chemin_ = NULL; GLfloat xROT=0,yROT=0,zROT=0; unsigned int max (unsigned int a, unsigned int b) {      if (a > b)           return a;      else           return b; } void InitGL(int Width, int Height)             // We call this right after our OpenGL window is created. {      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);          // This Will Clear The Background Color To Black      glClearDepth(1.0);                    // Enables Clearing Of The Depth Buffer      glDepthFunc(GL_LESS);                    // The Type Of Depth Test To Do      glEnable(GL_DEPTH_TEST);               // Enables Depth Testing      glShadeModel(GL_SMOOTH);               // Enables Smooth Color Shading      glMatrixMode(GL_PROJECTION);      glLoadIdentity();                    // Reset The Projection Matrix      gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);     // Calculate The Aspect Ratio Of The Window      glMatrixMode(GL_MODELVIEW); } /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ void ReSizeScene(int Width, int Height) {      if (Height==0)                    // Prevent A Divide By Zero If The Window Is Too Small           Height=1;      glViewport(0, 0, Width, Height);          // Reset The Current Viewport And Perspective Transformation      glMatrixMode(GL_PROJECTION);      glLoadIdentity();      gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW); } void DrawCube(GLfloat x, GLfloat y, GLfloat z) {      glBegin(GL_QUADS);           glVertex3f(x,y,z);           glVertex3f(x,y+1,z);           glVertex3f(x+1,y+1,z);           glVertex3f(x+1,y,z);           glVertex3f(x,y,z+1);           glVertex3f(x,y+1,z+1);           glVertex3f(x+1,y+1,z+1);           glVertex3f(x+1,y,z+1);           glVertex3f(x,y,z);           glVertex3f(x,y,z+1);           glVertex3f(x+1,y,z+1);           glVertex3f(x+1,y,z);           glVertex3f(x,y+1,z);           glVertex3f(x,y+1,z+1);           glVertex3f(x+1,y+1,z+1);           glVertex3f(x+1,y+1,z);           glVertex3f(x,y,z);           glVertex3f(x,y+1,z);           glVertex3f(x,y+1,z+1);           glVertex3f(x,y,z+1);           glVertex3f(x+1,y,z);           glVertex3f(x+1,y+1,z);           glVertex3f(x+1,y+1,z+1);           glVertex3f(x+1,y,z+1);      glEnd(); } void DrawGrid(void) {      glBegin(GL_LINES);      for (unsigned int width_ = 0;width_ <= MAP_W; width_++)      {           for (unsigned int deep_ = 0;deep_ <= MAP_D; deep_++)           {                glVertex3f(width_-MAP_W/2.0f,-MAP_H/2.0f,deep_-MAP_D/2.0f);                glVertex3f(width_-MAP_W/2.0f,MAP_H/2.0f,deep_-MAP_D/2.0f);           }      }      glEnd();      glBegin(GL_LINES);      for (unsigned int width_ = 0;width_ <= MAP_W; width_++)      {           for (unsigned int height_ = 0;height_ <= MAP_H; height_++)           {                glVertex3f(width_-MAP_W/2.0f,height_-MAP_H/2.0f,-MAP_D/2.0f);                glVertex3f(width_-MAP_W/2.0f,height_-MAP_H/2.0f,MAP_D/2.0f);           }      }      glEnd();      glBegin(GL_LINES);      for (unsigned int deep_ = 0;deep_ <= MAP_D; deep_++)      {           for (unsigned int height_ = 0;height_ <= MAP_H; height_++)           {                glVertex3f(-MAP_W/2.0f,height_-MAP_H/2.0f,deep_-MAP_D/2.0f);                glVertex3f(MAP_W/2.0f,height_-MAP_H/2.0f,deep_-MAP_D/2.0f);           }      }      glEnd(); } /* The main drawing function. */ void DrawScene() {      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      glLoadIdentity();      gluLookAt ((GLfloat)(MAP_W*1.5f), (GLfloat)(MAP_H*1.5f), (GLfloat)(MAP_D*1.5f), 0.0f, 0.0f, 0.0f, 0.0f, 1.0, 0.0f);      //glTranslatef((GLfloat)(MAP_W/-2.0f),(GLfloat)(MAP_H/-2.0f),(GLfloat)(MAP_D/-2.0f));      glRotatef(xROT,1.0f,0.0f,0.0f);      glRotatef(yROT,0.0f,1.0f,0.0f);      glRotatef(zROT,0.0f,0.0f,1.0f);      glEnable(GL_BLEND);      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      glLineStipple(1, 0xF0FF);      glEnable(GL_LINE_STIPPLE);      glColor4f(0.5f,0.5f,0.5f,0.5f);      DrawGrid();      glDisable(GL_LINE_STIPPLE);            glColor4f(1.0f,0.5f,0.75f,0.2f);      for (unsigned int width_ = 0;width_ < MAP_W; width_++)      {           for (unsigned int height_ = 0;height_ < MAP_H; height_++)           {                for (unsigned int deep_ = 0;deep_ < MAP_D; deep_++)                {                     if (map[height_*MAP_W+width_*MAP_H+deep_] == 0)                          DrawCube(width_-MAP_W/2.0f,height_-MAP_H/2.0f,deep_-MAP_D/2.0f);                }           }      }      PATH_POINT result;      chemin_->gotoFirstPoint();      glColor3f(0.0f,1.0f,0.0f);      chemin_->getCurrentPoint(&result);      DrawCube(result.x-MAP_W/2.0f,result.y-MAP_H/2.0f,result.z-MAP_D/2.0f);      glColor3f(0.0f,0.0f,1.0f);      glBegin(GL_LINES);      do      {           chemin_->getCurrentPoint(&result);           DrawCube(result.x-MAP_W/2.0f,result.y-MAP_H/2.0f,result.z-MAP_D/2.0f);      }      while ( chemin_->gotoNextPoint() );      glEnd();      //glLoadIdentity();      glBegin(GL_LINES);           glColor3f(1.0f,0.0f,0.0f);           glVertex3f(0,0,0);           glVertex3f(1000,0,0);           glColor3f(1.0f,1.0f,0.0f);           glVertex3f(0,0,0);           glVertex3f(0,1000,0);           glColor3f(0.0f,0.0f,1.0f);           glVertex3f(0,0,0);           glVertex3f(0,0,1000);      glEnd();      glDisable(GL_BLEND);      // we need to swap the buffer to display our drawing.      glutSwapBuffers(); } /* The function called whenever a key is pressed. */ void keyPressed(unsigned char key, int x, int y) {      /* sleep to avoid thrashing this procedure */      usleep(100);      /* If escape is pressed, kill everything. */      switch (key)      {           case 27:                /* shut down our window */                glutDestroyWindow(window);                 /* exit the program...normal termination. */                exit(EXIT_SUCCESS);                break;           case 113:                yROT++;                break;           case 100:                yROT--;                break;           case 122:                xROT++;                break;           case 115:                xROT--;                break;           case 97:                xROT=0;                yROT=0;                zROT=0;                break;           default :                //printf("Touche : %i",key);                break;      }           if (xROT < 0.0f)                xROT = 359.0f;           if (yROT < 0.0f)                yROT = 359.0f;           if (xROT > 359.0f)                xROT = 0.0f;           if (yROT > 359.0f)                yROT = 0.0f; } int main(int argc, char** argv) {      if (argc != 9)      {           printf("Usage : demo Xstart Ystart Zstart Xend Yend Zend search_mode hv_only\n\n \                     search_mode : 0 or 1\n \                     hv_only : 0 or 1\n\n");           exit(EXIT_FAILURE);      }      //Randomize function      time_t t;      srand((unsigned) time(&t));      for (unsigned int cptr = 0 ; cptr<MAP_W*MAP_H*MAP_D;cptr++)      {           short test=rand();           if (test < 30000)                map[cptr]=1;           else                map[cptr]=0;      }      CPath3D chemin(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]), atoi(argv[6]), MAP_W, MAP_H, MAP_D, (unsigned int*)&map, (PATH_MODE)atoi(argv[7]), atoi(argv[8]));      //On affiche un texte simple en utilisant les fonctions de la classe      printf("%s version %s\n%s\n\n",chemin.getName(),chemin.getVersion(),chemin.getCopyright());      if (chemin.isInitialized())      {           //On lance la recherche           if (chemin.search() == PATH_true)           {                PATH_POINT result;                chemin.getFirstPoint(&result);                printf("{%i,%i,%i}\n",result.x,result.y,result.z);                while ( chemin.gotoNextPoint() )                {                     chemin.getCurrentPoint(&result);                printf("{%i,%i,%i}\n",result.x,result.y,result.z);                }                chemin_ = &chemin;                glutInit(&argc, argv);                glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);                glutInitWindowSize(640, 480);                glutInitWindowPosition(0, 0);                window = glutCreateWindow("Demo number 3 (Spomky.Dev)");                glutDisplayFunc(&DrawScene);                glutFullScreen();                glutIdleFunc(&DrawScene);                glutReshapeFunc(&ReSizeScene);                glutKeyboardFunc(&keyPressed);                InitGL(640, 480);                glutMainLoop();           }           else           {                printf("I did not found any way!\n");           }      }      else      {           printf("I can not initialize!\n");      }      return(EXIT_SUCCE

Z/S et Q/D permettent de tourner la map
A remet l'angle de vue à celui de départ

14

on voit pas le coté 3D du chemin là... c'est dommage smile

15

J'espère qu'on voit mieux cette fois-ci?
capture5.png

16

17

Spomky : tu n'aurais pas la meme chose, mais en C et pour de la 2D grin
avatar
pourquoi la mort ? parce qu'elle nous est si douce, au contraire de la vie :)

18

Devoir à rendre spotted ^^

19

Si bien sûr! endif path.h //  --------------------------------------------------------------------------------------- // //                A* Path Finding Library                                                   // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project:                                                                                 // // ---------------------------------------------------------------------------------------- // #ifndef PATH_H      #define PATH_H      // Défini si les calculs sont à faire dans un environnement 3D      // Préférez la définition lors de la compilation      //#define USE_3D_NODES      // Nom du projet      #define PATH_NAME "A* Path Finding"      // Version du projet      #define PATH_VERSION_STRING "1.2.4.0"      #define PATH_VERSION 1,2,4,0      // Pour rendre le code plus clair      #define FALSE 0      #define TRUE 1      enum {PATH_short = 0, PATH_best};      typedef struct      {           void* parent;           void* son;           unsigned long F;           unsigned long G;           unsigned long H;           unsigned long x;           unsigned long y;           #ifdef USE_3D_NODES                unsigned long z;           #endif           int isClosed;      }NODE;      typedef struct      {           unsigned long Xs,Ys;           unsigned long Xe,Ye;           unsigned int *map;           unsigned long width;           unsigned long height;           #ifdef USE_3D_NODES                unsigned long Zs,Ze;                unsigned long deep;           #endif           unsigned int make_full_path, search_mode, use_hv_move_only;           unsigned long node_number;           NODE** list;           NODE* end_node;      }PATH;      int PATH_init(PATH *);      int PATH_search(PATH *);      void PATH_quit(PATH *); # if } path.c //  --------------------------------------------------------------------------------------- // //                A* Path Finding Library                                                   // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project:                                                                                 // // ---------------------------------------------------------------------------------------- // #include <stdlib.h> #include "path.h" // Définitions propres au path finding #ifndef USE_3D_NODES      int PATH_isGoodWay(PATH*, unsigned long, unsigned long);      NODE* PATH_add_node(PATH*, unsigned long, unsigned long, NODE*);      NODE* PATH_isNodeInList(PATH*, unsigned long, unsigned long);      int PATH_isNewFGHBetterThanOld(PATH*, unsigned long, unsigned long, NODE*, NODE*); #else      int PATH_isGoodWay(PATH*, unsigned long, unsigned long, unsigned long);      NODE* PATH_add_node(PATH*, unsigned long, unsigned long, unsigned long, NODE*);      NODE* PATH_isNodeInList(PATH*, unsigned long, unsigned long, unsigned long);      int PATH_isNewFGHBetterThanOld(PATH*, unsigned long, unsigned long, unsigned long, NODE*, NODE*); #endif NODE* PATH_getBestNode(PATH*); void PATH_setFGH(PATH *, NODE*); void PATH_buildFullPath(PATH*); #ifndef USE_3D_NODES NODE* PATH_add_node(PATH *path, unsigned long x, unsigned long y, NODE* parent) #else NODE* PATH_add_node(PATH *path, unsigned long x, unsigned long y, unsigned long z, NODE* parent) #endif {      int isgoodpath;      #ifdef USE_3D_NODES           if (path->use_hv_move_only)           {                if (parent != NULL && abs(x-parent->x)+abs(y-parent->y)+abs(z-parent->z) != 1)                     return NULL;           }           if ((isgoodpath = !PATH_isGoodWay(path,x,y,z)))                return NULL;      #else           if (path->use_hv_move_only)           {                if (parent != NULL && abs(x-parent->x)+abs(y-parent->y) != 1)                     return NULL;           }           if ((isgoodpath = !PATH_isGoodWay(path,x,y)))                return NULL;      #endif      if (!(path->list = (NODE**)realloc(path->list,(path->node_number+1)*sizeof(NODE*))))           return NULL;      if (!(path->list[path->node_number] = (NODE*)malloc(sizeof(NODE))))      {           path->list = (NODE**)realloc(path->list,path->node_number*sizeof(NODE*));           return NULL;      }      path->list[path->node_number]->parent = parent;      path->list[path->node_number]->x = x;      path->list[path->node_number]->y = y;      path->list[path->node_number]->isClosed = isgoodpath;      #ifdef USE_3D_NODES           path->list[path->node_number]->z = z;           if (x == path->Xe && y == path->Ye && z == path->Ze )                path->end_node = path->list[path->node_number];      #else           if (x ==path-> Xe && y == path->Ye)                path->end_node = path->list[path->node_number];      #endif      PATH_setFGH(path, path->list[path->node_number]);      ++(path->node_number);      return path->list[path->node_number-1]; } NODE* PATH_getBestNode(PATH *path) {      if (path->node_number == 0)           return NULL;      NODE* found = NULL;      unsigned int cptr;      for (cptr = 0; cptr < path->node_number; ++cptr)      {           if ((found != NULL && path->list[cptr]->isClosed == FALSE && found->F > path->list[cptr]->F) || (found == NULL && path->list[cptr]->isClosed == FALSE))                found = path->list[cptr];      }      return found; } //Vérifie si le noeud de coordonnées X,Y est présent dans la PATH_liste ouverte #ifndef USE_3D_NODES NODE* PATH_isNodeInList(PATH *path, unsigned long X, unsigned long Y) #else NODE* PATH_isNodeInList(PATH *path, unsigned long X, unsigned long Y, unsigned long Z) #endif {      unsigned long cptr;      for (cptr = 0; cptr < path->node_number; ++cptr)      {           #ifndef USE_3D_NODES           if (path->list[cptr]->x == X && path->list[cptr]->y == Y)           #else           if (path->list[cptr]->x == X && path->list[cptr]->y == Y && path->list[cptr]->z == Z)           #endif                return path->list[cptr];      }      return NULL; } //Calcule F = G + H du noeud passé en argument void PATH_setFGH(PATH *path, NODE* Son) {      if (Son->parent == NULL)      {           Son->H = 0;           Son->G = 0;           Son->F = 0;      }      else      {           #ifndef USE_3D_NODES                Son->H = (abs(Son->x - path->Xe)+abs(Son->y - path->Ye)) * 10;                if (path->search_mode == PATH_short)                {                     if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) == 2)                          Son->G = 14 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) == 1)                          Son->G = 10 + ((NODE*)Son->parent)->G;                }                else                {                     if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) == 2)                          Son->G = path->map[Son->y*path->width+Son->x]*14 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) == 1)                          Son->G = path->map[Son->y*path->width+Son->x]*10 + ((NODE*)Son->parent)->G;                }           #else                if (path->search_mode == PATH_short)                {                     Son->H = (abs(Son->x - path->Xe)+abs(Son->y - path->Ye)+abs(Son->z - path->Ze)) * 10;                     if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 3)                          Son->G = path->map[Son->y*path->width+Son->x*path->height+Son->z]*17 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 2)                          Son->G = path->map[Son->y*path->width+Son->x*path->height+Son->z]*14 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 1)                          Son->G = path->map[Son->y*path->width+Son->x*path->height+Son->z]*10 + ((NODE*)Son->parent)->G;                }                else                {                     Son->H = (abs(Son->x - path->Xe)+abs(Son->y - path->Ye)+abs(Son->z - path->Ze)) * 10;                     if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 3)                          Son->G = 17 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 2)                          Son->G = 14 + ((NODE*)Son->parent)->G;                     else if (abs(Son->x - ((NODE*)Son->parent)->x) + abs(Son->y - ((NODE*)Son->parent)->y) + abs(Son->z - ((NODE*)Son->parent)->z) == 1)                          Son->G = 10 + ((NODE*)Son->parent)->G;                }           #endif           Son->F = Son->G + Son->H;      } } // Renvoi vrai si le nouveau parent du noeud est meilleur que l'ancien #ifndef USE_3D_NODES int PATH_isNewFGHBetterThanOld(PATH *path, unsigned long X, unsigned long Y, NODE* old, NODE* parent) #else int PATH_isNewFGHBetterThanOld(PATH *path, unsigned long X, unsigned long Y, unsigned long Z, NODE* old, NODE* parent) #endif {      if (old->parent == parent)           return FALSE;      unsigned long newG = 0;      #ifndef USE_3D_NODES           if (path->search_mode == PATH_short)           {                if (parent->x == X && parent->y == Y)                     return FALSE;                if (abs(parent->x - X) + abs(parent->y - Y) == 2)                     newG = path->map[Y*path->width+X]*14 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) == 1)                     newG = path->map[Y*path->width+X]*10 + parent->G;           }           else           {                if (parent->x == X && parent->y == Y)                     return FALSE;                if (abs(parent->x - X) + abs(parent->y - Y) == 2)                     newG = 14 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) == 1)                     newG = 10 + parent->G;           }      #else           if (path->search_mode == PATH_short)           {                if (parent->x == X && parent->y == Y && parent->z == Z)                     return FALSE;                if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 3)                     newG = 17 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 2)                     newG = 14 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 1)                     newG = 10 + parent->G;           }           else           {                if (parent->x == X && parent->y == Y && parent->z == Z)                     return FALSE;                if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 3)                     newG = path->map[Y*path->width+X*path->height+Z]*17 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 2)                     newG = path->map[Y*path->width+X*path->height+Z]*14 + parent->G;                else if (abs(parent->x - X) + abs(parent->y - Y) + abs(parent->z - Z) == 1)                     newG = path->map[Y*path->width+X*path->height+Z]*10 + parent->G;           }      #endif      if (newG < old->G)           return TRUE;      return FALSE; } // Voilà l'accomplissement du path finding int PATH_search(PATH *path) {      #ifndef USE_3D_NODES           if (!PATH_isGoodWay(path, path->Xe, path->Ye))                return FALSE;      #else           if (!PATH_isGoodWay(path, path->Xe, path->Ye, path->Ze))                return FALSE;      #endif      NODE* PATH_current_node,* temp;      int ligne, colonne;      #ifdef USE_3D_NODES           int etage;      #endif      //Faire tant que le point d'arrivée n'est pas atteint et tant qu'il existe un noeud dans la PATH_liste ouverte      do      {           //Récuperer le meilleur noeud de la PATH_liste ouverte           if ((PATH_current_node = PATH_getBestNode(path)) != NULL)           {                // Le mettre dans la PATH_liste fermée                PATH_current_node->isClosed = TRUE;                // Analyser ses 8 voisins                for(ligne = -1; ligne < 2; ++ligne)                {                     for(colonne = -1; colonne < 2; ++colonne)                     {                     #ifdef USE_3D_NODES                     for(etage = -1; etage < 2; ++etage)                     {                     #endif                          //Si le voisin n'est pas dans la PATH_liste ouverte                          //On l'ajoute s'il ne fait pas partie de la PATH_liste fernée non plus                          #ifndef USE_3D_NODES                          temp = PATH_isNodeInList(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne);                          if (temp == NULL)                          {                               PATH_add_node(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne, PATH_current_node);                          #else                          temp = PATH_isNodeInList(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne, PATH_current_node->z+etage);                          if (temp == NULL)                          {                               PATH_add_node(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne, PATH_current_node->z+etage, PATH_current_node);                          #endif                          }                          else                          //Sinon                          {                               //On vérifie si depuis le noeud actuel le chemin est meilleur                               #ifndef USE_3D_NODES                               if (PATH_isNewFGHBetterThanOld(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne,temp,PATH_current_node))                               #else                               if (PATH_isNewFGHBetterThanOld(path, PATH_current_node->x+colonne, PATH_current_node->y+ligne, PATH_current_node->z+etage,temp,PATH_current_node))                               #endif                               {                                    //Si c'est le cas on change le parent                                    temp->parent = PATH_current_node;                                    //Et on recalcule F = G + H                                    if (temp->isClosed == FALSE)                                         PATH_setFGH(path, temp);                               }                          }                     #ifdef USE_3D_NODES                     }                     #endif                     }                }           }      }      //Tant que l'arrivée ne fait pas partie de la PATH_liste et tant qu'un chemin existe      while(path->end_node == NULL && (PATH_current_node = PATH_getBestNode(path)) != NULL);      //Si le noeud de fin pointe sur NULL cela signifie qu'il n'a pas été atteint donc qu'aucun chemin n'existe      if (path->end_node == NULL)           return FALSE;    //Sinon un chemin a été trouvé      if (path->make_full_path)           PATH_buildFullPath(path);      return TRUE; } void PATH_quit(PATH *path) {      if (path == NULL)           return;      unsigned int cptr;      if (!(path->node_number))           return;      for (cptr = 0; cptr < path->node_number; ++cptr)           free(path->list[cptr]);      free(path->list);      path->end_node = NULL;      path->node_number = 0; } void PATH_buildFullPath(PATH *path) {      if (path->end_node == NULL)           return;      NODE* temp = path->end_node;      path->end_node->son = NULL;      do      {           ((NODE*)temp->parent)->son = temp;           temp = (NODE*)temp->parent;      }      while (temp->parent != NULL); } int PATH_init(PATH *path) {      #ifndef USE_3D_NODES           if ( path == NULL || path->map == NULL || path->list != NULL || path->end_node != NULL || path->node_number != 0 || path->width == 0 || path->height == 0 )                return FALSE;           if (path->Xe == path->Xs && path->Ye == path->Ys)                return FALSE;           if( PATH_add_node(path, path->Xs, path->Ys, NULL) )                return TRUE;           return FALSE;      #else           if ( path == NULL || path->map == NULL || path->list != NULL || path->end_node != NULL || path->node_number != 0 || path->width == 0 || path->height == 0  || path->deep == 0 )                return FALSE;           if (path->Xe == path->Xs && path->Ye == path->Ys && path->Ze == path->Zs)                return FALSE;           if ( PATH_add_node(path, path->Xs, path->Ys, path->Zs, NULL) )                return TRUE;           return FALSE;      #endif } #ifndef USE_3D_NODES int PATH_isGoodWay(PATH *path, unsigned long X, unsigned long Y) #else int PATH_isGoodWay(PATH *path, unsigned long X, unsigned long Y, unsigned long Z) #endif {      #ifndef USE_3D_NODES           if (Y >= path->height || X >= path->width)                return FALSE;           return path->map[Y*path->width+X];      #else           if (Y >= path->height || X >= path->width || Z >= path->deep)                return FALSE;           return path->map[Y*path->width+X*path->height+Z];      #end   } } demo1.c //  --------------------------------------------------------------------------------------- // //                A* Path Finding Demo                                                      // //                    Copyright (c) 2005 Spomky.Dev                                         // //                       <http://www.spomky.com/>                                           // // ---------------------------------------------------------------------------------------- // //  This program is free software; you can redistribute it and/or modify                    // //  it under the terms of the GNU General Public License as published by                    // //  the Free Software Foundation; either version 2 of the License, or                       // //  (at your option) any later version.                                                     // //                                                                                          // //  You may not change or alter any portion of this comment or credits                      // //  of supporting developers from this source code or any supporting                        // //  source code which is considered copyrighted (c) material of the                         // //  original comment or credit authors.                                                     // //                                                                                          // //  This program is distributed in the hope that it will be useful,                         // //  but WITHOUT ANY WARRANTY; without even the implied warranty of                          // //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                           // //  GNU General Public License for more details.                                            // //                                                                                          // //  You should have received a copy of the GNU General Public License                       // //  along with this program; if not, write to the Free Software                             // //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA                // // ---------------------------------------------------------------------------------------- // // Author: Florent MORSELLI (webmaster@spomky.com)                                          // // URL:  http://www.spomky.com                                                              // // Project:                                                                                 // // ---------------------------------------------------------------------------------------- // #include <stdlib.h> #include <stdio.h> #include "../path.h" #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 int main(int argc, char *argv[]); void printPath(PATH*); void printMap(PATH*); unsigned int map[] = {     1,9,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,9,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,9,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,9,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,9,1,1,1,1,1,1,1,0,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1,                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; int main(int argc, char *argv[]) {      printf("This software is a demonstration of "PATH_NAME" (version "PATH_VERSION_STRING")\n" \      "Copyright (c) 2005 Spomky.Dev (http://spomky.com/)\n\n");      if (argc != 8)      {           printf("Usage : demo Xstart Ystart Xend Yend search_mode hv_only full_path\n\n \                     search_mode : 0 ou 1\n \                     hv_only : 0 ou 1\n \                     full_path : 0 ou 1\n\n");           exit(EXIT_FAILURE);      }      // on crée une nouvelle variable de type PATH      PATH chemin1;      // on défini se qui doit l'être      chemin1.map = (unsigned int*)&map;      chemin1.width = 32;      chemin1.height = 18;      chemin1.Xs = atoi(argv[1]);      chemin1.Ys = atoi(argv[2]);      chemin1.Xe = atoi(argv[3]);      chemin1.Ye = atoi(argv[4]);      chemin1.search_mode = atoi(argv[5]);      chemin1.use_hv_move_only = atoi(argv[6]);      chemin1.make_full_path = atoi(argv[7]);      // on initialise      if (PATH_init(&chemin1))      {           printf("\nLa map :\n");           printMap(&chemin1);           // on recherche le chemin           if (PATH_search(&chemin1))           {                printf("I found a way to go from %d,%d to %d,%d!\n",atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));                printf("\nLe chemin :\n");                printPath(&chemin1);                printf("I analysed %d nodes\n",chemin1.node_number);                printf("The total cost is %d\n",chemin1.end_node->F);           }           else           {                printf("I did not found any way!\n");           }      }      else           printf("I can not do anything!\n");      // on détruit le chemin      PATH_quit(&chemin1);      exit(EXIT_SUCCESS); } void printPath(PATH *path) {      if (path->end_node == NULL)           return;      unsigned int x,y;      unsigned int res=0;      for(y=0;y<path->height;++y)      {           for(x=0;x<path->width;++x)           {                res=0;                NODE* temp = path->end_node;                while (temp != NULL)                {                     if (temp->x == x && temp->y == y)                     {                          printf("*");                          res=1;                     }                     temp = (NODE*)temp->parent;                }                if (res == 0)                {                     if (path->map[y*path->width+x])                          printf(" ");//%d",path->map[y*path->width+x]);                     else                          printf("O");                }           }           printf("\n");      } } void printMap(PATH* path) {      unsigned int x,y;      for(y=0;y<path->height;++y)      {           for(x=0;x<path->width;++x)           {                if (path->map[y*path->width+x])                     printf("%d",path->map[y*path->width+x]);                else                     printf("*");           }           printf("\n");    

(cf mon ancien sujet ici)

20

merci beaucoup grin
avatar
pourquoi la mort ? parce qu'elle nous est si douce, au contraire de la vie :)