Teaching - 2i002 - (TME: sujets)


2i002 : Introduction à la programmation Objet

Exercice 1 : poule, renard, vipère mise en place

Les poules mangent des vipères, les vipères des renards et les renards des poules...

Classe Animal

  • Attributs
    • Un animal connait sa position (attribut int x et int y)
    • Un animal a un type (String) qui désignera poule, renard ou vipère
  • Constructeur: il prend en argument tous les attributs à initialiser
  • Accesseurs sur tous les attributs
  • méthode : public double distance(Animal a)
    calcule la distance vers un autre animal.
  • méthode : void move(int i, int j) déplace l'animal de i case en x et j case en y (déplacement relatif).
  • méthode : void move(Animal a) ne fait rien pour l'instant ici (plus tard, elle permettra de se rapprocher d'une cible ou de s'éloigner d'un ennemi)
    • si vous avez compris le principe des classes/méthode abstraites: déclarer la méthode abstrait, sinon, déclarer juste une méthode vide

Classes Poule, Renard, Vipère

Ces classes sont très proches.

  • Chaque classe gère un compteur static et un identifiant id pour les animaux de l'espèce.
  • Méthode toString(): retourne une lettre (p,r ou v) suivie de l'identifiant. Afin de garantir un affichage sur 3 caractères, vous utiliserez pour Poule:
 String.format("p%02d", id);
  • Méthode void afficher(): affiche le type, la position et l'identifiant de l'animal.

NB: ça peut valoir le coup de développer une méthode afficher dans la classe Animal qui affiche simplement je suis un animal

Classe de test

Créer différents animaux, les faire bouger et les afficher afin de tester le bon fonctionnement de vos méthodes.


Exercice 2: classe Faune

Attributs et constructeur

Il n'y a pas de Terrain explicite, la classe faune gère:

  • une constante donne la taille du terrain: TAILLE. Cette constante est déclarée public static final...

La classe Faune gère un tableau d'animaux.

  • la taille de la faune est:
    • soit gérée dans une constante NBANIMAUX (par exemple 21)
    • soit donnée en paramètre lors de la création de la Faune
    • A vous de choisir une solution
  • un attribut tab tableau d'animaux est initialisé dans le constructeur:
    • les trois espèce le peuplent de manière équilibrée (7 poules, 7 renards, 7 vipères par exemple)
    • les positions des animaux sont aléatoires: chaque coordonnées est tirée entre 0 et TAILLE-1.

Créer le constructeur de la classe Faune.

Affichage

Il n'y a pas de terrain explicite... Mais on souhaite tout de même réaliser des affichages pour vérifier que tout se passe bien!

Créer la méthode public String terrain() qui retourne une String contenant le terrain (les cases vides seront marquées par des ., les cases contenant des animaux seront affichées avec l'animal en question.

Proposition de protocole pour générer la String:

  1. Construire une String[][] terr de taille TAILLE x TAILLE contenant " . " dans chaque cellule
  2. Parcourir la liste d'animaux, pour chaque animal tab[i] mettre à jour la case terr[tab[i].getX()][tab[i].getY()]
  3. Construire une String s simple à partir de terr

Tester votre code à l'aide du main suivant:

public class TestFaune{
  public static void main(String[] args){
    Faune f = new Faune(); // Ou new Faune(21) suivant vos options
    System.out.println(f.terrain());
  }
}

Vous devez obtenir:

______________________________________________________________
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
|p00 .  .  .  .  . p03 .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  . r04 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  . r01 .  .  . v04 .  . v00 . v02 .  .  .  .  .  .  .  . |
| .  .  .  .  .  . v03 .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  . p05 .  .  .  .  .  .  .  . |
| .  . r02 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  . p01 .  .  . p06 .  .  .  .  .  .  .  . p02 .  . p04 . |
|r06 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . r03 . |
| .  . v06 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  . v05 .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  . v01 .  .  . r05 . r00 .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
| .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . |
______________________________________________________________

Recherche des plus proches voisins

Nous arrivons maintenant à la partie difficile: nous voulons trouver, pour un animal, quel est son plus proche voisin. La méthode aura la signature suivante:
public int getIndiceAnimalLePlusProche(Animal requete) qui retourne l'indice de l'animal le plus proche de celui passé en requête.

Proposition d'algorithme:

  • Initialiser dist_min=Double.POSITIVE_INFINITY (très grand) et index = -1
  • Pour tous les indices i=0 à tab.length
    • Si l'animal courant est celui de la requête (tab[i] == requete) Alors continue
    • Si l'animal courant est null Alors continue (si les animaux se dévorent, certains sont amenés à disparaitre...)
    • Si la distance entre tab[i] et requete est inférieure à dist_min
      • Mettre à jour l'indice et la dist_min

Créer une méthode void etatDeLaFaune() dans la classe Faune qui affiche l'animal le plus proche pour tous les animaux encore vivants du tableau tab

Classe de test

Dans la classe de test, vous effectuerez les opérations suivantes:

  • Création d'une faune
  • Affichage du Terrain
  • Affichage pour chaque animal de l'animal le plus proche (appel à la méthode précédente)
public class TestFaune{
  public static void main(String[] args){
    Faune f = new Faune(); // Ou new Faune(21) suivant vos options
    System.out.println(f.terrain()); // aff. terrain
    Animal[] tab = f.getTab(); // a ajouter pour les tests
    for(Animal a: tab){
      Animal plusProche = tab[f.getIndiceAnimalLePlusProche(a)];
      System.out.println(a + " a pour voisin le plus proche : "+ plusProche);
    }
  }
}
v01 a pour animal le plus proche r05
...

Exercice 3: écosystème

Dans les classes Poule Renard, Vipere

Pour chacun des animaux, écrire la méthode void move(Animal a):

  • tester le type de l'animal a avec getType()
    • si l'animal a est une proie, on déplace l'animal courant vers a
    • si l'animal a est un prédateur, on déplace l'animal courant loin de a
    • le déplacement maximal est d'une case (diagonales possibles)

Vous pourrez utiliser la syntaxe suivante pour éloigner l'animal courant de a:

 move((int) Math.signum(getX() - a.getX()), (int) Math.signum(getY() - a.getY()));

ou pour le rapprocher:

 move((int) Math.signum(-getX() + a.getX()), (int) Math.signum(-getY() + a.getY()));

NB: il est conseillé de faire un schéma pour comprendre la géométrie derrière cette formule.

Mise à jour de la classe Faune

Dans la classe Faune, ajouter une méthode void update() qui déplace tous les animaux et les fait se manger les uns les autres lorsqu'ils sont sur la même case (c'est à dire que vous constatez une distance de 0 entre 2 animaux).

Cette dernière méthode n'est pas évidente : je vous engage à mettre beaucoup de System.out.print afin de dire qui se déplace où et qui mange qui...

Protocole détaillé pour update():

  • Pour tous les animaux vivants du tableau tab
    • Chercher l'animal a le plus proche de tab[i]
    • Appliquer tab[i].move(a)
  • Pour tous les animaux
    • s'il y a un animal sur la même case
      • trouver qui mange qui et éliminer l'animal mangé (tab[i] = null)

NB: toute la subtilité (et la beauté de l'héritage) est dans l'appel tab[i].move(a). Chaque animal réagit en fonction de son espèce et de l'espèce de a.