Note
Cet exercice est proposé a été initialement proposé sur le forum Zeste de savoir. Ce dépôt contient une nouvelle version avec l'intégration du concept de "design pattern".
M. Peisson, aquariophile accompli, vous demande de faire un programme de simulation pour son prochain aquarium : il compte y mettre un certain nombre d'espèces de poissons rares et chères, et n'a pas envie qu'au bout de deux mois son précieux investissement se transforme en désert…
Objectif de développement est de concevoir un programme qui fera la chose suivante :
- (extrait de cahier des charges) "Je devrai pouvoir mettre des poissons et des plantes dans mon aquarium virtuel, et faire passer le temps pour savoir si tout se passe bien."
Dans une premier temps, le programme devra être en 2 phases :
- l'initialisation : les poissons et les algues sont ajoutés dans l'aquarium
- Le temps qui passe : on résouds les actions d'un tour, et un rapport de la situation est fait.
Tip
Pour chacune des étapes vous pourrez établir un diagramme de classe qui vous aidera au cours de développements.
Il s'agit de la base du programme : avoir un aquarium rempli.
L'aquarium contient des poissons et des algues, un nombre quelconque de chaque.
L'algue ne fait rien : c'est une algue, elle se contente d'exister ou non.
Le poisson, lui, a un nom (monsieur Peisson aime ses poissons et leur donne un nom à chacun) et un sexe (mâle ou femelle).
L'aquarium a une méthode une méthode pour ajouter un poisson (avec son nom et son sexe), et une autre méthode pour ajouter une algue.
L'aquarium a une méthode pour faire passer le temps : à chaque nouveau tour, on fait toutes les actions (ce qui n'est pas très passionnant pour l'instant puisqu'il n'y en a aucune) et on affiche sur la console :
- le nombre d'algues présentes
- la liste des poissons avec leur nom et leur sexe.
En fait, des poissons tous identiques, c'est pas très passionnant.
Dans le magasin où se fournit monsieur Peisson, on trouve des poissons carnivores et d'autres herbivores.
Il y a six races de poissons :
- Poissons carnivores :
- Mérou,
- Thon,
- Poisson-clown.
- Poissons herbivores :
- Sole,
- Bar,
- Carpe.
Chaque poisson peut donc manger (il s'agit d'une méthode) : selon s'il est herbivore ou carnivore, il mange soit une algue (paramètre : algue), soit un autre poisson (paramètre : un poisson quel qu'il soit).
Nos poissons sont des goinfres : à chaque tour, tous les poissons mangent, et ils mangent tout ce qu'ils ont commencé.
En clair, ça veut dire que ce qui et mangé disparaît purement et simplement. Attention : un poisson ne peut pas se manger lui-même, et un poisson mangé ne peut rien faire. L'algue ou le poisson mangé est choisi au hasard.
Tip
// 1- Initialiser le générateur de nombres aléatoires.
// (une seule fois pour tout le programme suffit)
Random r = new Random();
// 2- Récupérer le prochain entier entre 0 (inclus) et n (exclus) :
int x = r.nextInt(n); // On a des méthodes de ce genre pour tous les types primitifs : nextDouble(), nextBoolean(), ...Tip
Lors de la suppression d'un poisson à l'intérieur d'un boucle vous allez, peut-être, rencontrer une erreur. Si c'est le cas il vous est conseillé de consulter la ressource disponible ici.
Tout ça est beaucoup trop brutal, introduisons la notion de points de vie (PV).
Les poissons et les algues sont des êtres vivants.
Tous les êtres vivants commencent avec 10 PV. Un être vivant qui arrive à 0 PV meurt.
Chaque algue grandit à chaque tour : elle gagne 1 PV. Une algue mangée par un poisson perds 2 PV.
A chaque tour qui passe, le poisson a de plus en plus faim : il perds 1 PV.
Un poisson qui a suffisamment faim (5 PV ou moins) cherche à manger.
Les herbivores n'ont pas trop de problème, mais les algues ne sont pas très nourrissantes : +3 PV.
Les carnivores mangent de la bonne viande de poisson, qui fait gagner +5 PV.
Un carnivore attaque chaque tour un poisson au hasard : il n'a qu'une seule chance.
Hélas pour lui, il ne peut ni se manger lui-même, ni manger un poisson de son espèce.
Se faire mordre fait très mal et fait perdre 4 PV.
Tous les êtres vivants naissent à l'âge de 0 tours. Les êtres vivants qui ont plus de 20 tours meurent de vieillesse.
On peut acheter des poissons et des algues à un âge quelconque (autrement dit : poissons et algues peuvent être instanciées avecc des âges arbitraires, ceci est à prendre en compte dans les constructeurs).
Notre aquarium précédent est condamné à être désert au bout de 20 tours, ou alors il faut remettre sans arrêt des algues et des poissons. Pas très intéressant, non ? Nous avons des poissons mâles et femelles ? Faisons-les se reproduire !
Un poisson qui n'a pas faim va aller voir un autre poisson (au hasard). Si ce poisson est de même race et de sexe opposé, les deux poissons se reproduisent et donnent naissance à un troisième poisson, de même race et de sexe aléatoire. Il n'a qu'un seul essai par tour.
Concernant les algues, c'est plus simple : Une algue qui a 10 PV ou plus se sépare en deux pour donner naissance à une algue deux fois plus petite, donc avec deux fois moins de PV. Évidemment l'algue parente perds la moitié de ses PV dans le processus, mais garde son âge.
Oui, la sexualité des poisson est horriblement compliquée. Pourquoi ? Parce qu'ils ne sont pas simplement "mâle" ou "femelle" !
On distingue :
- Le poisson mono-sexué : ces poissons naissent mâle ou femelle et n'en changent plus.
- Le poisson hermaphrodite avec l'âge : Ce poisson passe les 10 premiers tours de sa vie en tant que mâle et les 10 suivants en tant que femelle.
- Le poisson hermaphrodite opportuniste : Ce poisson va rencontrer un membre de son espèce. Si ce membre est de même sexe que lui, notre poisson change de sexe pour pouvoir se reproduire.
Nous avons déjà des races herbivores et carnivores, ce qui nous donne le tableau suivant : 1: Pour ceux que ça intéresse, cette histoire de poisson hermaphrodites est parfaitement exacte… par contre je ne garantis pas le classement des races dans le tableau suivant :
| Poisson | Herbivore | Carnivore |
|---|---|---|
| Mono-sexué | Carpe | Thpn |
| Hermaphrodite avec l'âge | Bar | Mérou |
| Hermaphrodite opportuniste | Sole | Poisson-clown |
Monsieur Peisson voudrait pouvoir sauvegarder l'état actuel de la simulation (par exemple au tour 35) dans un fichier (par exemple un .poisson) pour pouvoir la reprendre plus tard.
Tip
Pour mener à bien la sauvegarde rapide d'un ou plusieurs objets il est possible d'utiliser la sérialisation binaire. Ressource pour en apprendre plus sur la sérialisation binaire.
Monsieur Peisson voudrait que les rapports de ce qui s'est passé dans le tour s'enregistrent dans un fichier en plus d'être affichés sur la console.
Par exemple, si un poisson mange un autre il faut que dans un fichier une ligne apparaisse, par exemple :
09:50:00 Tour 1 - Le poisson Bob (Mérou) mange le poisson Brigitte (Thon). RIP.
Tip
Ce mécanisme de sauvegarde d'historique des actions peut être vu comme la journalisation (ou "logging") dans un fichier. Ressource pour apprendre à mettre en place la journalisation dans un fichier
Monsieur Peisson est aquariophile mais pas développeur, et n'a pas envie de re-compiler le programme à chaque fois qu'il veut changer les poissons et les algues introduits au début. De toutes façons, il ne sait pas ce qu'est "recompiler".
Il veut bien lancer le programme en ligne de commande, mais il veut pouvoir écrire les poissons et les algues dans un fichier texte dont il passerait le nom au programme.
Il accepte cependant de vous faciliter le travaille et est d'accord pour éditer ses listes de poissons et algues dans un fichier JSON.
Il fournit un exemple de fichier (les lignes qui commencent par // sont des commentaires et n'apparaitrons jamais dans le fichier).
{
"algues": [
{ "quantite": 1, "age": 10 },
{ "quantite": 10, "age": 4 }
],
"poissons": [
{ "nom": "Lin", "race": "Morue", "age": 10 },
{ "nom": "Anaclet", "race": "Poisson-clown", "age": 1 },
{ "nom": "Évariste", "race": "Thon", "age": 3 }
]
}Tip
La sérialisation/désérialisation JSON n'est pas nativement supportée par Java. Il vous faudra probablement utiliser une bibliothèque tierce telle que Jackson ou GSon. Tutoriel d'utilisation de Jackson
M. Peisson voudrait pouvoir ajouter des poissons et des algues à n'importe quel tour.
Le tour d'insertion serait indiqué par des séparateurs comme celui-ci :
===== Tour 5 ====
Le logiciel devra pouvoir lui proposer de saisir les informations qu'il souhaite.
M. Peisson voudrait donner le simulateur à son petit-neveu.
Sauf que celui-ci, bien qu'aquariophile également, n'a aucune connaissance en développement : il ne sait ni utiliser un IDE et surtout pas compiler le code.
M. Peisson souhaite lui donner un exécutable utilisable.