R APPORT DE VALIDATION
POURSUITE DE ROBOTS
T ABLE DES MATIÈRES
I.T
ESTS UNITAIRES! 3
‣A
DJACENCE" 3
M
ATRICE Dʼ
ADJACENCE" 3
L
ISTE Dʼ
ADJACENCE" 4
‣D
ICTIONNAIRE" 5
‣C
OORDONNÉES" 5
‣C
HAMP Dʼ
ACCESSIBILITÉ" 6
‣D
IJKSTRA" 6
II.T
ESTS FONCTIONNELS! 8
‣C
ARTE" 8
‣R
OBOT" 8
‣I
NTERFACE GRAPHIQUE" 10
I.T
ESTS UNITAIRES‣A
DJACENCENous avons créé une classe «Adjacence» regroupant la création dʼune matrice est dʼune liste dʼadjacence toutes deux se basant sur le même algorithme.
MATRICE DʼADJACENCE
Cʼest une matrice booléenne de taille nbCases*nbCases où nbCases correspond au nombre de cases de la carte :
private bytes[][] matrice;
private int nbCases;
La matrice est construite à partir de deux paramètres, le nombre de lignes et le nombre de colonnes que lʼont souhaite avoir sur la carte.
public Adjacence(int pLignes, int pColonnes){
nbCases = pLignes*pColonnes;
matrice = new bytes[nbCases][nbCases];
initMatrice(pColonnes);
}
private void initMatrice(int pIndice) {
for(int i = 0; i < (nbCases-1)/2; i++){
if((i+1)%pIndice != 0){
matrice[i][i+1] = 1;
matrice[i+1][i] = 1;
matrice[nbCases-i-2][nbCases-i-1] = 1;
matrice[nbCases-i-1][nbCases-i-2] = 1;
}
if(i < pIndice*(pIndice-2)){
matrice[i][i+pIndice] = true;
matrice[i+pIndice][i] = true;
matrice[nbCases-pIndice-i-1][nbCases-i-1] = 1;
matrice[nbCases-i-1][nbCases-pIndice-i-1] = 1;
} }
}
Essayons maintenant de créer une matrice de taille 3*3, une méthode «afficheMatrice()» est créée pour voir le résultat :
Adjacence adjacence = new Adjacence(3, 3);
System.out.println("Matrice d'adjacence :");
adjacence.afficheMatrice();
Notre algorithme fonctionne parfaitement et nous montre lʼensemble des voisins de chaque case ligne par ligne :
LISTE DʼADJACENCE
Implantons maintenant notre algorithme sous forme de liste dʼadjacence, nous allons avoir alors besoin dʼun tableau de listes chaînées dʼentiers :
private LinkedList<Integer>[] liste;
private int nbCases;
public Adjacence(int pLignes, int pColonnes){
nbCases = pLignes*pColonnes;
liste = new LinkedList[nbCases];
initListe(pColonnes);
}
private void initListe(int pIndice) { initListesChainees();
for(int i = 0; i < (nbCases-1)/2; i++) { if((i+1)%pIndice != 0){
liste[i].add(new Integer(i+1));
liste[i+1].add(new Integer(i));
liste[nbCases-i-2].add(new Integer(nbCases-i-1));
liste[nbCases-i-1].add(new Integer(nbCases-i-2));
}
if(i < pIndice*(pIndice-2)){
liste[i].add(new Integer(i+pIndice));
liste[i+pIndice].add(new Integer(i));
liste[nbCases-pIndice-i-1].add(new Integer(nbCases- i-1));
liste[nbCases-i-1].add(new Integer(nbCases-pIndice- i-1));
} }
}
private void initListesChainees() { for(int i = 0; i < nbCases; i++) {
liste[i] = new LinkedList();
} }
Essayons maintenant dʼafficher une carte de taille 3*3, et affichons notre liste dʼadjacence : Adjacence adjacence = new Adjacence(3, 3);
System.out.println("Liste d'adjacence :");
adjacence.afficheListe();
Le résultat est sans appel, on remarquera que la liste est plus lisible que la matrice :
Liste d'adjacence : 0[1, 3]
1[0, 2, 4]
2[1, 5]
3[0, 4, 6]
4[1, 3, 5, 7]
5[2, 4, 8]
6[3, 7]
7[4, 6, 8]
8[5, 7]
‣D
ICTIONNAIREPour notre dictionnaire nous avons utilisé la classe «HashMap», voici une série de test mettant en œuvre lʼutilisation de coordonnées et dʼautomate comme type générique :
//Dictionnaire des robots sur la carte
HashMap<IAutomate, ICoordonnees> dictionnaire = new HashMap();
//Création des robots
IAutomate robot = new Robot("Robot", 2, 2);
IAutomate terminator = new Robot("Terminator", 3, 3);
IAutomate c3po = new Robot("C3PO", 3, 3);
//Ajout des robots dans le dictionnaire
dictionnaire.put(robot, new Coordonnees(2, 2));
dictionnaire.put(terminator, new Coordonnees(4, 5));
dictionnaire.put(c3po, new Coordonnees(1, 0));
//Affichage du dictionnaire
System.out.println(dictionnaire);
//Supression d'un robot dictionnaire.remove(c3po);
//Affichage du dictionnaire
System.out.println(dictionnaire);
Résultat :
{Terminator=(4,5), C3PO=(1,0), Robot=(2,2)}
{Terminator=(4,5), Robot=(2,2)}
‣C
OORDONNÉESNous avons effectué une série de test pour lʼimplantation de notre interface «ICoordonnees» : //On prend deux coordonnées
ICoordonnees coord1 = new projet.outils.Coordonnees(2, 2);
ICoordonnees coord2 = new projet.outils.Coordonnees(5, 7);
//On calcul le vecteur coord1 > coord2
ICoordonnees vecteur = coord1.calculVecteur(coord2);
//On affiche le vecteur System.out.println(vecteur);
//On calcul un point avec une origine et un vecteur
ICoordonnees coord3 = new projet.outils.Coordonnees(1, 1);
coord3 = coord3.calculPoint(vecteur);
//On affiche le point
System.out.println(coord3);
//Nous avons une carte qui fait 6 colonnes de largeur int numCase = coord3.coordonneesEnNumero(6x);
//On affiche le numéro de case System.out.println(numCase);
Résultat :
‣C
HAMP Dʼ
ACCESSIBILITÉNous avons créé une classe test «Accessibilite» permettant de construire une matrice dʼaccessibilité à partir de notre algorithme. Une méthode «afficheAccess()» nous permet de visualiser le résultat :
Accessibilite acc = new Accessibilite(2);
System.out.println("Matrice d'accessibilite :");
acc.afficheAcess();
Dans notre exemple nous avons fixé un pas de 2, 3 et 4:
0 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0 1 1 1 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0
‣D
IJKSTRAPour Dijkstra, nous avons effectué nos test sur différentes cartes, avec un nombre de lignes et de colonnes différentes paires ou impaires.
Dans lʼexemple nous avons pris une carte de taille 5*4. Les cases orangées sont considérées comme interdites.
La première chose à faire est de créer la liste dʼadjacence de la carte afin dʼavoir accès aux voisins de chacune dʼentres elles.
Ensuite nous élaborons une liste de cases que lʼon souhaite parcourir pour trouver le plus court chemin de «Départ»
jusquʼà «Arrivée» cette liste doit être connexe auquel cas notre algorithme nous retournerait une exception.
Cʼest à dire que depuis une case de la liste donnée, il doit exister au moins un chemin vers toutes les autres cases de cette même liste et inversement.
Notre liste sera donc composée de toutes les cases nʼayant pas été marquées comme interdites.
Pour finir nous instancions la classe test «Dijkstra» avec comme paramètre : la liste de cases à parcourir
la liste dʼadjacence de la carte le point de départ et dʼarrivée
Nous appelons ensuite la méthode «getPlusCourtChemin()» qui nous retourne une liste dʼentiers correspondant au numéro de chaque cases à parcourir pour aller de «Départ» jusquʼà «Arrivée»
//Carte
Adjacence adjacence = new Adjacence(5, 4);
//Liste d'adjacence de la carte
LinkedList<Integer>[] listeAdj = adjacence.getListeAdjacence();
//Liste des noeuds à parcourir
LinkedList<Integer> listeDesNoeuds = new LinkedList();
//Noeuds de la liste listeDesNoeuds.add(19);
listeDesNoeuds.add(17);
listeDesNoeuds.add(15);
listeDesNoeuds.add(14);
// ... ect
listeDesNoeuds.add(13);
listeDesNoeuds.add(2);
listeDesNoeuds.add(1);
listeDesNoeuds.add(0);
// Recherche et affichage du plus court chemin try {
Dijkstra dij = new Dijkstra(listeDesNoeuds, listeAdj, 0, 8);
System.out.println(dij.getPlusCourtChemin());
}
catch(GrapheNonConnexeException e) { System.out.println(e);
} Résultat :
[0, 1, 2, 6, 7, 11, 15, 14, 13, 9, 8]
II.T
ESTS FONCTIONNELS‣C
ARTENotre carte implante lʼinterface «ICarte» lui permettant de déclarer lʼensemble des méthodes nécessaire à la gestion dʼobjets sur une carte à deux dimensions.
Notre carte est composée de plusieurs attributs indispensables à son bon fonctionnement : Un dictionnaire dʼobjets permettant dʼassocier des coordonnées à un objet.
Une liste dʼadjacence pour connaître la liste des voisins de chaque case.
Le nombre de lignes et de colonnes Le nombres dʼobjets
private ListeAdjacence listeAdj;
private Hashmap<Object, ICoordonnees> dictionnaire;
private int nbLignes;
private int nbColonnes;
private int nbObjets;
Lors de lʼinstance de notre classe, la construction se fait aisément comme ceci : public Carte(int pLignes, int pColonnes) {
nbLignes = pLignes;
nbColonnes = pColonnes;
dictionnaire = new HashMap<Object, ICoordonnees>
listeAdj = new ListeAdjacence(pLignes, pColonnes);
}
‣R
OBOTPour créer un robot il faut quʼil implante lʼinterface «IAutomate» afin de pouvoir effectuer lui même des actions sur la carte comme se déplacer ou encore repérer un objet.
Si nous voulons rendre visible le robot sur lʼinterface graphique celui-ci doit aussi implanter lʼinterface «IIcone».
Robot a plusieurs attributs permettant dʼêtre identifier en tant quʼunité de contrôle indépendant : La référence de la carte quʼil a rejoint
Deux matrices booléennes de vision et de déplacement Un icône pour le représenter sur lʼunité de visualisation Un nom
private String nom;
private boolean[][] matriceDep;
private boolean[][] matriceVision;
private ImageIcon icone;
private ICarte carte;
Notre constructeur prend ensuite en paramètre le nom de notre robot ainsi que deux entiers, un pour la pas de vision et lʼautre pour le pas de déplacement :
public Robot(String pNom, int pDep, int pVision) { nom = pNom;
matriceDep = Matrice.matriceDeplacement(pDep);
matriceVision = Matrice.matriceVision(pVision);
icone = new ImageIcon(ICONE);
}
Dans notre test nous allons créer une carte et ajouter deux robots dessus : //Création d'une carte
ICarte carte = new Carte(6, 3);
//Création des robots
IAutomate proie = new Robot("Proie", 3, 3);
IAutomate predateur = new Robot("Prédateur", 3, 3);
//Ajout des robots
carte.ajouter(proie, new Coordonnees(0, 1));
carte.ajouter(predateur, new Coordonnees(4, 2));
//On déplace le prédateur
carte.deplacer(predateur, new Coordonnees(4, 1));
//Le prédateur peut-il voir sa proie ?
System.out.println(carte.estVisible(predateur, proie));
//On supprime le prédateur carte.supprimer(predateur);
Etant donné que nos robots implantent lʼinterface «IAutomate», le code ci-dessous permet dʼavoir un résultat identique à la différence que cʼest le robot qui gère lui même ses actions :
//Création d'une carte
ICarte carte = new Carte(6, 3);
//Création des robots
IAutomate proie = new Robot("Proie", 3, 3);
IAutomate predateur = new Robot("Prédateur", 3, 3);
//Ajout des robots
proie.rejoindreCarte(carte, new Coordonnees(0, 1));
predateur.rejoindreCarte(carte, new Coordonnees(4, 2));
//On déplace le prédateur
predateur.seDeplacer(new Coordonnees(4, 1));
//Le prédateur peut-il voir sa proie ? System.out.println(predateur.voit(proie));
//On supprime le prédateur
predateur.quitterCarte(predateur);
Résultat :
Proie a rejoint la carte (0, 1) Prédateur a rejoint la carte (4, 2)
Prédateur se déplace de (4, 1) vers (4, 2) Prédateur ne peut pas voir Proie
Prédateur a quitté la carte.
‣I
NTERFACE GRAPHIQUEVoici le rendu de notre interface graphique développée sous «SWING/AWT»
Nous cliquons sur le bouton «DEMARRER», la course se lance correctement ...