Voila l'algorithme plus connu sous le nom de "A*" ou A star
Son but va etre de trouver le chemin le plus court entre deux points (AI pathfinding)
#include <iostream>
#include <windows.h>
#include <deque> // liste deque
using namespace std;
// CREATION OBJET qui représente les coordonnées d'un point
class point
{
public :
// CONSTRUCTION D'INITIALISATION
point( int a, int b, int c, int d ) { X = a, Y = b, Cout = c, rang = d; }
// COPIE
point( const point &a ) { X = a.X; Y = a.Y; Cout = a.Cout; rang = a.rang; }
// SURCHAGE OPERATEUR
point & operator = ( const point &a ) { X = a.X; Y = a.Y; Cout = a.Cout; rang = a.rang; return (*this);}
bool operator == ( const point &a ) { return ( a.X == X && a.Y == Y ); }
bool operator != ( const point &a ) { return !( (*this) == a ); }
bool operator < ( const point &a ) { return (Cout < a.Cout); }
bool operator > ( const point &a ) { return (Cout > a.Cout); }
bool operator <= ( const point &a ) { return (Cout <= a.Cout); }
bool operator >= ( const point &a ) { return (Cout >= a.Cout); }
// COORDONNEE X DU POINT
int X;
// COORDONNEE Y DU POINT
int Y;
// DISTANCE PAR RAPPORT A L'ARRIVEE
int Cout;
int rang;
};
// ALGORITHME A*
class AStar
{
public :
// CONSTRUCTION DE A* >> DEFINITION DES DEUX POINTS (DEPART ET ARRIVEE)
AStar( int xdepart, int ydepart, int xarrivee, int yarrivee ) : depart( xdepart, ydepart, 1000, 0 ), arrive( xarrivee, yarrivee, 0, 0 )
{
// SI DEPASSEMENT DES LIMITES
if( !( depart.X >= 0 && depart.Y < 30 ) )
depart.X = 2, depart.Y = 1;
if( !( arrive.X >= 0 && arrive.Y < 30 ) )
arrive.X = 28, arrive.Y = 28;
// INITIALISATION MAP (0 "MUR" ; 1 VIDE)
for( int a = 0; a < 30; ++a )
for( int b = 0; b < 30; ++b )
tb[a] = 1;
}
// CALCUL DE LA DISTANCE ENTRE LE POINT ET L'ARRIVEE
int CalculCout( int x, int y ) { return ((arrive.X - x)*(arrive.X - x) + (arrive.Y - y)*(arrive.Y - y)); }
// MAP POUR A* (30 ; 30)
void AjustMap( bool map[30][30] );
// FONCTION RECHERCHE (ENTRE POINT DE DEPART ET D'ARRIVEE)
void recherche();
// AFFICHAGE MAP
void affichemap();
private :
// TABLEAU MAP
bool tb [ 30 ][ 30 ];
// POINT DEPART CHEMIN
point depart;
// POINT ARRIVEE CHEMIN
point arrive;
// LISTE DE POINTS ENTRE ARRIVEE ET DEPART
deque<point> Chemin;
};
// MAP POUR A*
void AStar::AjustMap( bool tableau[30][30] )
{
for( int a = 0; a < 30; ++a )
for( int b = 0; b < 30; ++b )
tb[a] = tableau[a];
}
// RECHERCHE LE CHEMIN ENTRE LES DEUX POINTS
void AStar::recherche()
{
bool Interdit[30][30];// 0 = INFRANCHISSABLE
bool NonVisite[30][30];// 1 = INCONNU, FRANCHISSABLE
point temp( 0, 0, 0, 0 ), temp2( 0, 0, 0, 0 );
int compteur = 0;
int neme = 1;
// INITIALISATION DU TABLEAU SELON 0 OU 1
for( int a = 0; a < 30; ++a )
for( int b = 0; b < 30; ++b )
{
Interdit[a] = tb[a];
NonVisite[a] = tb[a];
}
deque<point> Open;// LISTE RAJOUTANT LES POINTS = PROGRESSION
Open.push_front( depart );
while( !Open.empty() )
{
temp = Open[0];
neme = temp.rang + 1;
for( int it = 0; it < Open.size(); ++it )// MEME RANG QUE TEMP (COUT LE PLUS FAIBLE)
if( tb[Open[it].Y][Open[it].X] && temp.Cout > Open[it].Cout && ( Open[ 0 ].rang == Open[ it ].rang ) )
{
temp = Open[it];
Open.erase( Open.begin() + it );
}
// AJOUT DU POINT AU CHEMIN
Chemin.push_front( temp );
// LE POINT RECUPERE EST AJUSTE DANS LA MATRICE DES POINTS CONNUS
NonVisite[ temp.Y ][ temp.X ] = 0;
// SI LE POINT EN COURS (TEMP) EST L'ARRIVEE
if( temp == arrive )
return;
else
{
// COMPTEUR DU NOMBRE DE VOISINS A TEMP
compteur = 0;
// TEST A L'OUEST DE TEMP => 0 OU 1 ?
if( temp.X - 1 >= 0 && tb[temp.Y][temp.X - 1] && NonVisite[temp.Y][temp.X - 1] && Interdit[temp.Y][temp.X - 1] )
{
// NOUVEAU VOISIN
temp2.X = temp.X - 1;
temp2.Y = temp.Y;
// CALCUL DE SON COUT
temp2.Cout = CalculCout( temp.X - 1, temp.Y );
temp2.rang = neme;
// AJOUT DANS LISTE OPEN
Open.push_front( temp2 );
// AJOUT VOISIN DU POINT EN COURS
++compteur;
NonVisite[temp.Y][temp.X - 1] = 0;
}
// TEST A L'EST DE TEMP => 0 OU 1 ?
if( temp.X + 1 < 30 && tb[temp.Y][temp.X + 1] && NonVisite[temp.Y][temp.X + 1] && Interdit[temp.Y][temp.X + 1] )
{
temp2.X = temp.X + 1;
temp2.Y = temp.Y;
temp2.Cout = CalculCout( temp.X + 1, temp.Y );
temp2.rang = neme;
Open.push_front( temp2 );
++compteur;
NonVisite[temp.Y][temp.X + 1] = 0;
}
// TEST AU NORD DE TEMP => 0 OU 1 ?
if( temp.Y - 1 >= 0 && tb[temp.Y - 1][temp.X] && NonVisite[temp.Y - 1][temp.X] && Interdit[temp.Y - 1][temp.X] )
{
temp2.X = temp.X;
temp2.Y = temp.Y - 1;
temp2.Cout = CalculCout( temp.X, temp.Y - 1 );
temp2.rang = neme;
Open.push_front( temp2 );
++compteur;
NonVisite[temp.Y - 1][temp.X] = 0;
}
// TEST AU SUD DE TEMP => 0 OU 1 ?
if( temp.Y + 1 < 30 && tb[temp.Y + 1][temp.X] && NonVisite[temp.Y + 1][temp.X] && Interdit[temp.Y + 1][temp.X] )
{
temp2.X = temp.X;
temp2.Y = temp.Y + 1;
temp2.Cout = CalculCout( temp.X, temp.Y + 1 );
temp2.rang = neme;
Open.push_front( temp2 );
++compteur;
NonVisite[temp.Y + 1][temp.X] = 0;
}
if( compteur == 0 )
{
Interdit[temp.Y][temp.X] = 0;
Chemin.pop_front();
}
}
}
// PAS DE SOLUTION
cout << "Aucun chemin n'a \202t\202 trouv\202";
Chemin.clear();
}
// AFFICHAGE DE LA MAP : D = DEPART ; A = ARRIVEE ; + = TRAJET ; 1 OU 0 = CASE VIDE OU PLEINE
void AStar::affichemap()
{
deque<point>::iterator it = Chemin.begin();
bool test = false;
for( int a = 0; a < 30; ++a )
{
for( int b = 0; b < 30; ++b )
{
test = false;
for( it = Chemin.begin(); it != Chemin.end(); ++it )
if( it->Y == a && it->X == b )
test = true;
if( a == depart.Y && b == depart.X )
{
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE HCmd = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(HCmd, &csbiInfo);
SetConsoleTextAttribute(HCmd, FOREGROUND_RED|FOREGROUND_INTENSITY);
// AFFICHAGE DU POINT DE DEPART
cout << 'D';
// ON REVIENT AU VERT SIMPLE
SetConsoleTextAttribute(HCmd, FOREGROUND_GREEN);
}
else
if( a == arrive.Y && b == arrive.X )
{
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE HCmd = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(HCmd, &csbiInfo);
SetConsoleTextAttribute(HCmd, FOREGROUND_RED|FOREGROUND_INTENSITY);
// AFFICHAGE DU POINT D'ARRIVEE
cout << 'A';
SetConsoleTextAttribute(HCmd, FOREGROUND_GREEN);
}
else
if( test )
{
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE HCmd = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(HCmd, &csbiInfo);
SetConsoleTextAttribute(HCmd, FOREGROUND_BLUE|FOREGROUND_INTENSITY);
cout << '+';
SetConsoleTextAttribute(HCmd, FOREGROUND_GREEN);
}
else
cout << tb[a];
}
cout << '\n';
}
}
int main()
{
// GENERATION DE LA MAP
bool tab[30][30] = { { 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0 },
{ 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0 },
{ 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0 },
{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0 },
{ 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 },
{ 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0 },
{ 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 },
{ 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1 },
{ 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0 },
{ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0 },
{ 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1 },
{ 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0 } };
// POSITIONNEMENT DES POINTS D ET A
// AStar a( x, y, x, y );
AStar a( 2, 1, 28, 28 ); // <<<<<<<<< A CHANGER PAR SIMPLE CURIOSITE
a.AjustMap( tab );
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE HCmd = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(HCmd, &csbiInfo);
SetConsoleTextAttribute(HCmd, FOREGROUND_GREEN);
// AFFICHAGE TEXTE
cout << "AI pathfinding - IA recherche chemin [Algorithme A*] par neo_00110010101" << endl << endl;
cout << "Map \205 l'origine :" << endl << endl;
// AFFICHAGE MAP
a.affichemap();
// RECHERCHE DU CHEMIN LE PLUS COURT ENTRE D ET A
a.recherche();
cout << endl << "Voici le r\202sultat de l'algorithme A* :" << endl << endl;
// AFFICHAGE MAP
a.affichemap();
cout << endl << endl;
// QUITTER LE PROGRAMME
int touche;
cout << "ou [ENTER]" << endl;
cin >> touche;
return 0;
}