Exercices

Exercice - Programme simple

Testez le programme Java suivant :

Pour fonctionner, ce programme doit se trouver dans un fichier PremierProgramme.java dans le répertoire des sources du projet.

System.out représente la sortie standard du programme.

Exercice à rendre - les nombres premiers

On souhaite connaître le nombre de nombres premiers entre 1 et 1000. En mathématique, un nombre premier est un nombre qui n’est divisible que par 1 et lui-même.

Complétez la fichier NombrePremier.java ci-dessous :

Chapitres de référence :

  • langage_java/structure_fondamentale

  • langage_java/types_primitifs

  • langage_java/operateurs

  • langage_java/structures_de_controle

Exercice à rendre - afficher les nombres premiers

On souhaite afficher les nombres premiers entre 1 et 1000. En mathématique, un nombre premier est un nombre qui n’est divisible que par 1 et lui-même.

Complétez la fichier AffichageNombrePremier.java ci-dessous :

Chapitres de référence :

  • langage_java/structure_fondamentale

  • langage_java/types_primitifs

  • langage_java/operateurs

  • langage_java/structures_de_controle

  • langage_java/les_collections

Exercice à rendre - afficher les nombres premiers (version 2)

Reprenez l’exercice précédent. On peut redéfinir un nombre premier comme : un nombre qui n’est pas divisible par un autre nombre premier sauf 1 et lui-même.

Améliorez l’implémentation précédente en utilisant la liste des nombres premiers déjà trouvés pour déterminer si le nombre courant est premier.

Chapitres de référence :

  • langage_java/structure_fondamentale

  • langage_java/types_primitifs

  • langage_java/operateurs

  • langage_java/structures_de_controle

  • langage_java/les_collections

Exercice à rendre - La classe Rectangle

Implémentez une classe Rectangle. Cette classe doit définir les méthodes suivantes :

  • public double getLongueur()

  • public void setLongueur(double valeur)

  • public double getLargeur()

  • public void setLargeur(double valeur)

  • public double getPerimetre()

  • public double getAire()

  • public boolean isCarre()

  • public void transpose()

Pour rappel, le périmètre d’un rectangle est :

périmètre = (longueur + largeur) x 2

Pour rappel, l’aire d’un rectangle est :

aire = longueur x largeur

Un rectangle est un carré si sa longueur est égale à sa largeur. La méthode transponse intervertit la largeur et la longueur.

Un fois implémentée, votre classe doit pouvoir être utilisée dans le programme DemoRectangle.java ci-dessous :

Chapitres de référence :

  • langage_java/types_primitifs

  • langage_java/operateurs

  • langage_java/premiere_classe

Exercice à rendre - La classe Phrase

Implémentez la classe Phrase. Cette classe permet de créer une chaîne de caractères en ajoutant des mots qui seront séparés par un séparateur. Par défaut, le séparateur est le caractère espace, mais il peut être changé.

La classe Phrase doit permettre de :

  • ajouter un mot

  • ajouter une série de mots (nombre de paramètres variable)

  • ajouter un mot en le répétant n fois (on indique le mot et le nombre de fois qu’il faut le répéter)

  • changer le séparateur qui peut être soit une chaîne de caractères soit un seul caractère

  • la méthode public String toString() permet de récupérer la phrase sous la forme d’une chaîne de caractères. Cette chaîne doit être terminée par un point.

  • connaître le nombre de lettres dans la phrase

Le code suivant :

Phrase phrase = new Phrase();
phrase.ajouter("Une");
phrase.ajouter("classe");
phrase.ajouter("pour");
phrase.ajouter("ajouter");
phrase.ajouter("des mots");
phrase.setSeparateur(" et encore ");
phrase.ajouter("des mots", 3);
phrase.setSeparateur(' ');
phrase.ajouter("toujours", "et", "encore");

System.out.println(phrase);
System.out.println(phrase.getNbLettres());

doit produire sur la sortie standard

Une classe pour ajouter des mots et encore des mots et encore des mots et encore des mots toujours et encore.
88

Indication

On ne peut pas parcourir directement une chaîne de caractères, par contre on peut obtenir un tableau de caractères à partir d’une chaîne avec la méthode toCharArray.

String helloWorld = "Hello world!";
for (char c : helloWorld.toCharArray()) {
  // ...
}

Pour savoir si un caractère est une lettre, on utilise la méthode static Character.isAlphabetic.

Chapitres de référence :

  • langage_java/structures_de_controle

  • langage_java/premiere_classe

  • langage_java/attributs_et_methodes

  • langage_java/la_classe_string

Exercice à rendre - Le jeu du pendu

On souhaite réaliser un programme en ligne de commande pour jouer au jeu du pendu.

Vous devez implémenter la classe JeuDuPendu. Elle possède :

  • un constructeur pour lui passer le mot à trouver

  • la méthode proposer qui attend une lettre (char) en paramètre et qui retourne true si la lettre est présente dans le mot à trouver

  • la méthode getNbTentativesRestantes qui indique le nombre de tentatives restantes. Ce nombre diminue chaque fois qu’on propose une lettre qui n’est pas dans le mot

  • la méthode isPartieGagnee qui indique si on a trouvé toutes les lettres du mot.

  • la méthode isPartieTerminee qui indique si la partie est terminée. Une partie est terminée si on a gagné ou s’il ne reste plus de tentative.

  • la méthode getMotMasque qui retourne sous forme de chaîne de caractères le mot à trouver. ATTENTION, les lettres non encore trouvées sont remplacées par _.

  • la méthode getSolution qui retourne le mot qu’il faut trouver.

Si votre implémentation est complète, vous pourrez la tester avec la classe DemoJeuDuPendu ci-dessous :

Chapitres de référence :

  • langage_java/structures_de_controle

  • langage_java/premiere_classe

  • langage_java/attributs_et_methodes

  • langage_java/cycle_de_vie

  • langage_java/la_classe_string

Exercice bonus à rendre - Les constructeurs pour la classe Phrase

En reprenant la classe Phrase, ajoutez les constructeurs suivants :

// constructeur sans paramètre
Phrase phrase = new Phrase();
phrase.ajouter("Bonjour", "le", "monde");
System.out.println(phrase); // Bonjour le monde.

// constructeur pour indiquer quel caractère fini la phrase
Phrase phraseInterrogative = new Phrase(Phrase.INTERROGATION);
phraseInterrogative.ajouter("Ça", "va");
System.out.println(phraseInterrogative); // Ça  va ?

Phrase phraseExclamative = new Phrase(Phrase.EXCLAMATION);
phraseExclamative.ajouter("Oui");
System.out.println(phraseExclamative); // Oui !

Phrase phraseDeclarative = new Phrase(Phrase.DECLARATION);
phraseDeclarative.ajouter("C'est", "bien");
System.out.println(phraseDeclarative); // C'est bien.

// constructeur pour indiquer quel caractère fini la phrase
// et passer un nombre quelconque de mots à la phrase
phrase = new Phrase(Phrase.INTERROGATION, "Et", "ensuite");
System.out.println(phrase); // Et ensuite ?

Ajoutez également des méthodes de classe (méthodes statiques) pour créer directement une Phrase selon son type :

phrase = Phrase.interrogation("Comment", "allez", "vous");
System.out.println(phrase); // Comment allez vous ?

phrase = Phrase.exclamation("Dormez");
System.out.println(phrase); // Dormez !

phrase = Phrase.declaration("Brian", "est", "dans", "la", "cuisine");
System.out.println(phrase); // Brian est dans la cuisine.

Chapitres de référence :

  • langage_java/premiere_classe

  • langage_java/attributs_et_methodes

  • langage_java/cycle_de_vie

Exercice à rendre - Les constructeurs pour la classe Rectangle

Reprenez la classe Rectangle et ajoutez les constructeurs suivants :

  • Un constructeur qui attend la largeur et la longueur en paramètre

  • Un constructeur qui attend une seule valeur pour créer un carré

  • Un constructeur qui attend un Rectangle en paramètre et qui crée un rectangle avec la même largeur et longueur que celui passé en paramètre.

Testez vos implémentations en ajoutant du code de test dans la classe DemoRectangle.

Chapitre de référence :

  • langage_java/cycle_de_vie

Exercice à rendre - Gestion des formations

On souhaite représenter un système de gestion des formations. Chaque formation est représentée par son nom et la liste des modules qui la composent.

Créez les classes Formation et ModuleFormation. Un module de formation a un nom, une description, un nombre maximum de stagiaires acceptés et une durée en heures pleines. Une Formation a la propriété duree qui correspond à la somme des heures des modules qui la composent et la propriété nbStagiaires (minimum du nombre autorisé de stagiaires des modules qui la composent).

Il existe différents types de module de formation :

  • le type Cours qui dispose d’un numéro de salle

  • le type Tutoriel qui est représenté par un lien sur une vidéo en ligne. Il n’y a pas de limite au nombre de stagiaires pouvant suivre un tutoriel. Pour simplifier, vous pouvez considérer que la limite est fixée arbitrairement à 1000 stagiaires.

  • le type Projet qui est défini par le nombre de groupes et le nombre maximum de stagiaires dans un groupe. Le nombre de stagiaires maximum est donc le produit du nombre de groupes et du nombre de personnes par groupe.

Par exemple, si la formation Programmer en Java comprend :

  • Un cours de 20h accueillant 25 stagiaires maximum

  • Un tutoriel en ligne de 4h

  • Un projet de 30h avec 4 groupes de 5 personnes (soit 5 x 4 = 20 stagiaires)

Alors la formation Programmer en Java dure 54h et est disponible pour 20 stagiaires au maximum.

Testez votre implémentation avec une classe DemoFormation contenant une méthode main. Vérifiez que vous obtenez bien la durée et le nombre de stagiaires attendus pour une formation.

Chapitres de référence :

  • langage_java/attributs_et_methodes

  • langage_java/cycle_de_vie

  • langage_java/heritage_composition

Exercice à rendre - Le rectangle (suite)

Reprenez la classe Rectangle. On veut pouvoir comparer deux rectangles entre eux. Deux rectangles sont identiques s’ils ont la même longueur et la même largeur.

Modifiez la classe DemoRectangle pour tester vos ajouts.

Chapitres de référence :

  • langage_java/polymorphisme

  • langage_java/la_classe_object

Exercice à rendre - Figures géométriques (1/3)

On souhaite créer des classes Java qui permettent de représenter et de manipuler des figures géométriques.

Une figure est une représentation abstraite d’une forme géométrique. Parmi les figures géométriques, on distingue :

  • Le rectangle qui est défini par sa longueur et sa largeur

  • Le disque qui est défini par son rayon

Pour chaque type de figure, il est possible de connaître son périmètre et son aire.

Pour un rectangle

périmètre = (longueur + largeur) x 2
aire = longueur x largeur

Pour un disque

périmètre = 2 x π x rayon
aire = π x rayon²

Note

La valeur de π est donnée en Java par la constante Math.PI

Reprenez l’implémentation de la classe Rectangle et implémentez les classes Disque et Figure. Toutes ces classes doivent déclarer les méthodes getPerimetre() et getAire().

Créez une classe DemoFiguresGeometrique avec une méthode main pour tester votre implémentation.

Chapitres de référence :

  • langage_java/heritage_composition

  • langage_java/polymorphisme

  • langage_java/classe_abstraite

Exercice à rendre - Figures géométriques (2/3)

Reprenez l’exercice précédent et ajoutez la classe FigureComposee. Cette classe est une figure qui contient une liste de figures. Son périmètre vaut la somme des périmètres de toutes ses figures. Son aire vaut la somme des aires de toutes ses figures.

Implémentez la classe FigureComposee. Déclarez dans cette classe une méthode ajouter pour ajouter une nouvelle figure à cette figure composée.

Modifiez la classe DemoFigureGeometrique pour tester votre nouvelle classe.

Note

Une FigureComposee doit aussi pouvoir être composée d’autres FigureComposee. Dans les modèles de conception (design patterns), on appelle ce type de classe un composite. On trouve souvent ce type de représentation : dans un système de fichiers, un répertoire peut être représenté comme un type de fichier particulier qui peut contenir des fichiers ou des répertoires.

Chapitres de référence :

  • langage_java/heritage_composition

  • langage_java/polymorphisme

Exercice à rendre - Figures géométriques (3/3)

On veut pouvoir comparer deux objets Figure entre eux. Deux figures sont identiques si elles ont le même périmètre et la même aire.

Modifiez la classe DemoFigureGeometrique pour tester vos ajouts.

Chapitres de référence :

  • langage_java/polymorphisme

  • langage_java/la_classe_object

Exercice à rendre - Figures géométriques / les exceptions (1/4)

Modifier les classes Rectangle et Disque. Il ne doit pas être possible de donner une valeur négative pour la longueur, la largeur et le rayon à la construction des objets et sur les méthodes setter.

Utiliser l’exception IllegalArgumentException pour signaler qu’une valeur négative est interdite. Il s’agit d’un unchecked exception utilisée pour signaler un paramètre invalide.

Chapitre de référence :

  • langage_java/les_exceptions

Exercice à rendre - Figures géométriques / les exceptions (2/4)

Si ce n’est pas déjà le cas, déclarez une méthode ajouter dans la classe FigureComposee pour ajouter une Figure dans la figure composée. Afin d’éviter une relation cyclique, il n’est pas possible d’ajouter une figure composée à elle-même. Dans ce cas, la méthode ajouter doit produire une exception du type FigureInterditeException.

Créez la classe FigureInterditeException et modifiez la méthode ajouter de FigureComposee pour appliquer cette règle.

Faites évoluer les classes existantes afin qu’elles compilent toujours.

Chapitre de référence :

  • langage_java/les_exceptions

Exercice à rendre - Figures géométriques / les exceptions (3/4)

Étant donnée le programme suivant :

Vous pouvez télécharger directement le fichier ApprentissageFiguresGeometriques.java

Modifiez ce programme pour qu’il gère les exceptions de type IllegalArgumentException si jamais l’utilisateur saisit une valeur négative pour la longueur, la largeur ou le rayon.

Le programme ne doit pas planter. Il doit indiquer à l’utilisateur qu’il a fait une erreur et lui permettre de continuer à utiliser l’application.

Chapitre de référence :

  • langage_java/les_exceptions

Exercice bonus - Figures géométriques / les exceptions (4/4)

Pour le programme précédent, si vous saisissez autre chose qu’un nombre, le programme plante car les méthodes nextInt et nextDouble de la classe Scanner lancent alors une InputMismatchException.

Modifiez le programme précédent pour qu’il gère élégamment les erreurs de saisie de l’utilisateur. Par exemple, il peut signaler que la saisie n’est pas correcte et proposer une nouvelle tentative à l’utilisateur.

Astuce

Attention, lorsqu’un objet de la classe Scanner ne peut pas lire une donnée qui est au mauvais format, il jette une exception InputMismatchException et il conserve la valeur saisie dans une zone tampon. Cela signifie que les appels suivants aux méthodes de Scanner vont relire la même valeur ! Pour vider la zone tampon, il suffit de lire la donnée invalide sous la forme d’une chaîne de caractère en appelant la méthode next() :

scanner.next();

Chapitres de référence :

  • langage_java/les_exceptions

  • langage_java/entrees_sorties

Exercice à rendre - La gestion d’un catalogue (1/3)

On désire mettre en place un outil pour la gestion d’articles dans un catalogue.

Important

L’objectif de cet exercice et des suivants est de vous inciter à réaliser une conception objet d’une application. Il serait sans doute possible de réaliser ces exercices en codant une ou plusieurs méthodes avec des centaines de lignes de code. Mais ce type d’implémentation serait maladroite en Java et surtout absolument pas évolutive.

Essayez de mettre en pratique le principe SOLID de la single responsability : une classe doit avoir une responsabilité unique dans un programme. Pour vous guider, les éléments en gras dans le texte représentent des responsabilités différentes qui devaient très certainement être implémentées dans des classes différentes.

Un catalogue est composé d’un ensemble d’articles. Un article a un code, un titre et une note metascore (nombre entier sur 100). Mais il a aussi des caractéristiques qui dépendent du type de l’article :

  • un film est un article qui a en plus un réalisateur et une affiche. Pour faire simple, l’affiche du film est représentée par une URI sur le web. Par exemple :

    https://static.cotecine.fr/tb/Affiches/450x450/ffffff/LES+7+SAMOURAIS.JPG
    

    Plutôt que de représenter l’adresse de l’affiche sur la forme d’une String, vous pouvez utiliser les classes Java URL ou URI.

  • une série tv est un article qui a en plus un distributeur et un nombre de saisons.

  • un jeu vidéo est un article qui a en plus un studio de développement et un niveau dans la classification PEGI : PEGI 3, PEGI 7, PEGI 12, PEGI 16 et PEGI 18. Vous pouvez représenter la classification PEGI avec une énumération en Java (Cf. langage_java/enumeration).

Créez les classes pour représenter ce domaine. Placez ces classes dans le package catalogue de votre projet.

Exercice à rendre - La gestion d’un catalogue (2/3)

On souhaite implémenter un module pour charger les données d’un catalogue. Les données seront chargées à partir d’un fichier texte dans un format proche du format CSV.

Attention, nous souhaitons garantir une indépendance de ce module avec les autres modules que nous pourrions implémenter plus tard. Vous devez donc vous assurer que la classe responsable de charger le catalogue implémente l’interface ImporteurCatalogue :

Vous pouvez télécharger directement le fichier ImporteurCatalogue.java

Voici un exemple de fichier à traiter. Chaque ligne représente un article en séparant les informations par un point-virgule. La ligne indique, le code, le titre, la note metascore, le type de l’article (film, serie, jeu) puis les informations spécifiques à chaque type d’article.

exemple de fichier de catalogue
F0001;Les sept samouraïs;98;film;Akira Kurosawa;https://static.cotecine.fr/tb/Affiches/450x450/ffffff/LES+7+SAMOURAIS.JPG
S0012;The Strain;70;serie;FX;4
JV010;Mass effect;89;jeu;Bioware;PEGI18

Pour lire un fichier, il existe plusieurs solutions en Java. La solution la moins performantes (mais la plus facile à coder) consiste à appeler la méthode de classe Files.readAllLines. Vous pouvez vous reporter au chapitre langage_java/entrees_sorties pour en savoir plus.

Pour l’analyse d’une ligne, vous pouvez utiliser la méthode split de la classe String pour découper la chaîne de caractères en tableau en utilisant le point-virgule comme séparateur :

String[] colonnes = ligne.split(";");
// La première colonne est accessible part colonnes[0], la seconde
// colonne par colonnes[1], etc.

Écrivez une programme qui demande un chemin de fichier à l’utilisateur pour ensuite charger le catalogue. Si le chargement échoue avec une exception, affichez vos excuses à l’utilisateur ainsi que le message de l’exception.

Exercice à rendre - La gestion d’un catalogue (3/3)

On souhaite implémenter un module pour exporter le catalogue au format HTML.

Pour l’exemple de catalogue donné à l’exercice précédent, le résultat de l’export HTML sera :

Attention, nous souhaitons garantir une indépendance du module d’export. Vous devez donc vous assurer que la classe responsable d’exporter le catalogue au format HTML implémente l’interface ExporteurCatalogue :

Vous pouvez télécharger directement le fichier ExporteurCatalogue.java

L’export consiste à écrire le début du fichier HTML puis, pour chaque article d’écrire une balise <article> avec les informations de l’article et enfin, écrire la fin du fichier HTML.

Nous ne pouvons pas inclure une méthode toHTML dans notre classe Article ou une de ces sous-classes pour réaliser l’écriture de la balise <article>. Cela ne serait pas conforme au principe de single responsability. Nous ne pouvons pas non plus nous contenter de coder la procédure d’export dans une seule méthode : ce code ne serait pas très évolutif.

Pour réaliser l’export, vous devrez créer une interface ExporteurArticle. Cette interface sera implémentée par trois classes spécialisées : une pour l’export de film, une pour l’export de série et une pour l’export de jeu.

Créez également une classe ExporteurArticleFabrique. Cette classe agira comme une fabrique.

Note

Une fabrique est un modèle de conception (design patterns) couramment utilisé dans la programmation orientée objet. Il s’agit d’une classe dont la responsabilité est de créer des objets sans que le reste de l’application ne connaisse le type exact des objets créés.

Pour en savoir plus, vous pouvez consulter l’article Wikipedia dédié à ce modèle de conception :

https://fr.wikipedia.org/wiki/Fabrique_(patron_de_conception)

L’architecture générale de l’export peut être schématisée de la manière suivante :

langage_java/langage_java/exercices/exporteur_article.png

Ce schéma n’est pas complet, par exemple, il manque certainement des méthodes. À vous de vous inspirer de ce schéma pour développer le module d’export.

Écrivez un programme qui demande à l’utilisateur d’indiquer le chemin d’un fichier de catalogue à charger et le chemin d’un fichier HTML à produire. Le programme doit alors charger le catalogue et produire le fichier HTML d’export.