This commit is contained in:
Laureηt 2023-06-20 21:02:09 +02:00
commit e907d221c2
Signed by: Laurent
SSH key fingerprint: SHA256:kZEpW8cMJ54PDeCvOhzreNr4FSh6R13CMGH/POoO8DI
134 changed files with 859702 additions and 0 deletions

13
TP01/CycleVie.java Normal file
View file

@ -0,0 +1,13 @@
/** Illustrer le ramasse-miettes de Java.
* @author Xavier Crégut
* @version 1.4
*/
public class CycleVie {
public static void main(String[] args) {
for (int i = 0; i < 100_000; i++) {
Point p = new Point(i, i);
}
System.out.println("Fini !");
}
}

View file

@ -0,0 +1,91 @@
/** Comprendre les objets et les poignées sur la classe Point.
* @author Xavier Crégut
* @version 1.6
*/
public class ExempleComprendre {
/** Afficher un point précédé d'un texte.
* @param texte le texte à afficher
* @param p le point à afficher
*/
public static void afficher(String texte, Point p) {
System.out.print(texte + " = ");
p.afficher();
System.out.println();
}
/** Méthode principale */
public static void main(String[] args) {
// Créer et afficher un point p1
Point p1; // déclarer une poignée sur un Point
p1 = new Point(3, 4); // créer un point et l'attacher à p1
// On peut écrire les deux instructions précédentes sur la
// même ligne. Ceci évite d'oublier d'initialiser une
// poignée.
afficher("p1", p1);
// Créer et afficher un point p2
Point p2 = new Point(0, 0); // On déclare des poignées et on
// crée des objets quand on veut.
afficher("p2", p2);
// Afficher la distance entre p1 et p2
double d = p1.distance(p2);
System.out.println("Distance de p1 à p2 : " + d);
// Translater p1
System.out.println("> p1.translater(6, -2);");
p1.translater(6, -2);
afficher("p1", p1); // Qu'est ce qui est affiché ?
// Changer l'abscisse de p1 et afficher p1
System.out.println("> p1.setX(0);");
p1.setX(0);
afficher("p1", p1); // Qu'est ce qui est affiché ?
// Changer l'ordonnée de p1 et afficher p1
System.out.println("> p1.setY(10);");
p1.setY(10);
afficher("p1", p1);
// Dessiner l'état de la mémoire
// Prendre une nouvelle poignée sur p1
System.out.println("> Point p3 = p1;");
Point p3 = p1;
afficher("p3", p3); // Qu'est ce qui est affiché ?
afficher("p1", p1); // Qu'est ce qui est affiché ?
// Déplacer p3
System.out.println("> p3.translater(100, 100);");
p3.translater(100, 100);
afficher("p3", p3); // Qu'est ce qui est affiché ?
// Afficher p1
afficher("p1", p1); // Qu'est ce qui est affiché ?
// Dessiner l'état de la mémoire
// Affectations entre poignées
System.out.println("> p3 = new Point(123, 321);");
p3 = new Point(123, 321);
afficher("p3", p3); // Qu'est ce qui est affiché ?
afficher("p1", p1); // Qu'est ce qui est affiché ?
System.out.println("> p1 = p2 = p3;");
p1 = p2 = p3;
// Dessiner l'état de la mémoire
afficher("p1", p1); // Qu'est ce qui est affiché ?
afficher("p2", p2); // Qu'est ce qui est affiché ?
afficher("p3", p3); // Qu'est ce qui est affiché ?
// p1, p2 et p3 sont-ils des points différents ?
System.out.println("> p1.translater(-123, -321);");
p1.translater(-123, -321);
afficher("p1", p1); // Qu'est ce qui est affiché ?
afficher("p2", p2); // Qu'est ce qui est affiché ?
afficher("p3", p3); // Qu'est ce qui est affiché ?
d = new Point(5, 5).distance(new Point(8, 1));
System.out.println("d = " + d);
// Combien y a-t-il de points accessibles ?
}
}

View file

@ -0,0 +1,108 @@
class MonPoint {
public MonPoint(double vx, double vy) {
this.x = vx;
this.y = vy;
}
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public void setX(double vx) {
this.x = vx;
}
public void setY(double vy) {
this.y = vy;
}
public void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
}
public double distance(MonPoint autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
private double x;
private double y;
}
public class ExempleComprendreTutor {
public static void afficher(String texte, MonPoint p) {
System.out.print(texte + " = ");
p.afficher();
System.out.println();
}
public static void main(String[] args) {
MonPoint p1;
p1 = new MonPoint(3, 4);
afficher("p1", p1);
MonPoint p2 = new MonPoint(0, 0);
afficher("p2", p2);
double d = p1.distance(p2);
System.out.println("Distance de p1 à p2 : " + d);
System.out.println("> p1.translater(6, -2);");
p1.translater(6, -2);
afficher("p1", p1); // Qu'est ce qui est affiché ?
System.out.println("> p1.setX(0);");
p1.setX(0);
afficher("p1", p1); // Qu'est ce qui est affiché ?
System.out.println("> p1.setY(10);");
p1.setY(10);
afficher("p1", p1);
System.out.println("> MonPoint p3 = p1;");
MonPoint p3 = p1;
afficher("p3", p3);
afficher("p1", p1);
System.out.println("> p3.translater(100, 100);");
p3.translater(100, 100);
afficher("p3", p3);
afficher("p1", p1);
System.out.println("> p3 = new MonPoint(123, 321);");
p3 = new MonPoint(123, 321);
afficher("p3", p3);
afficher("p1", p1);
System.out.println("> p1 = p2 = p3;");
p1 = p2 = p3;
afficher("p1", p1);
afficher("p2", p2);
afficher("p3", p3);
System.out.println("> p1.translater(-123, -321);");
p1.translater(-123, -321);
afficher("p1", p1);
afficher("p2", p2);
afficher("p3", p3);
d = new MonPoint(5, 5).distance(new MonPoint(8, 1));
System.out.println("d = " + d);
}
}

17
TP01/ExempleErreur.java Normal file
View file

@ -0,0 +1,17 @@
/** Une erreur à la compilation !
* Pourquoi ?
* @author Xavier Crégut
* @version 1.3
*/
public class ExempleErreur {
/** Méthode principale */
public static void main(String[] args) {
Point p1 = new Point(0, 0);
p1.setX(1);
p1.setY(2);
p1.afficher();
System.out.println();
}
}

115
TP01/Point.java Normal file
View file

@ -0,0 +1,115 @@
import java.awt.Color;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
public class Point {
/** Construire un point à partir de son abscisse et de son ordonnée.
* @param vx abscisse
* @param vy ordonnée
*/
public Point(double vx, double vy) {
System.out.println("CONSTRUCTEUR Point(" + vx + ", " + vy + ")");
this.x = vx;
this.y = vy;
this.couleur = Color.green;
}
/** Obtenir l'abscisse du point.
* @return abscisse du point
*/
public double getX() {
return this.x;
}
/** Obtenir l'ordonnée du point.
* @return ordonnée du point
*/
public double getY() {
return this.y;
}
/** Changer l'abscisse du point.
* @param vx nouvelle abscisse
*/
public void setX(double vx) {
this.x = vx;
}
/** Changer l'ordonnée du point.
* @param vy nouvelle ordonnée
*/
public void setY(double vy) {
this.y = vy;
}
/** Afficher le point. */
public void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
}
/** Distance par rapport à un autre point.
* @param autre l'autre point
* @return distance entre this et autre
*/
public double distance(Point autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
// La méthode finalize est appelée avant que le récupérateur de
// mémoire ne détruise l'objet. Attention toutefois, on ne sait
// pas quand ces ressources seront libérées et il est donc
// dangereux de s'appuyer sur ce mécanisme pour libérer des
// ressources qui sont en nombre limité.
//
// D'autre part, pour être sûr que les méthodes << finalize >>
// sont appelées avant la fermeture de Java, il faut appeler la
// méthode statique :
// System.runFinalizersOnExit(true)
//
protected void finalize() {
System.out.print("DESTRUCTION du point : ");
this.afficher();
System.out.println();
}
// Représentation interne d'un point
// ---------------------------------
// Remarque : en Java, il est conseillé (convention de programmation)
// de mettre les attributs au début de la classe.
private double x; // abscisse
private double y; // ordonnée
private Color couleur; // couleur du point
}

67
TP01/Schema.java Normal file
View file

@ -0,0 +1,67 @@
/** Un Schéma est défini pas trois points qui constituent ses
* sommets. Un Schéma peut être affiché et translaté.
*
* @author
* @version 1.9
*/
public class Schema {
private Segment s1;
private Segment s2;
private Segment s3;
private Point barycentre;
/** Construire un Schéma à partir de ses trois sommets.
* @param s1 le premier point du schéma
* @param s2 le deuxième point du schéma
* @param s3 le troisème point du schéma
*/
public Schema(Point p1, Point p2, Point p3) {
this.s1 = new Segment(p1, p2);
this.s2 = new Segment(p2, p3);
this.s3 = new Segment(p3, p1);
this.barycentre = calcul_barycentre(p1, p2, p3);
}
/**
* Calcul le barycentre à partir de trois points
* @param p1
* @param p2
* @param p3
* @return le barycentre de trois points
*/
private static Point calcul_barycentre(Point p1, Point p2, Point p3) {
return new Point(
(p1.getX() + p2.getX() + p3.getX())/3,
(p1.getY() + p2.getY() + p3.getY())/3 );
}
/**
* Translater le schéma.
*
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.s1.getExtremite(1).translater(dx, dy);
this.s2.getExtremite(1).translater(dx, dy);
this.s3.getExtremite(1).translater(dx, dy);
this.barycentre.translater(dx, dy);
}
/**
* Afficher le schéma
*/
public void afficher() {
System.out.print("[ ");
this.s1.getExtremite(1).afficher();
System.out.print(" - ");
this.s2.getExtremite(1).afficher();
System.out.print(" - ");
this.s3.getExtremite(1).afficher();
System.out.print(" ], barycentre: ");
this.barycentre.afficher();
}
}

81
TP01/Segment.java Normal file
View file

@ -0,0 +1,81 @@
import java.awt.Color;
/** Un segment est défini pas ses deux points qui constituent ses
* extrémités. Un segment peut être affiché et translaté.
*
* @author Xavier Crégut
* @version 1.9
*/
public class Segment {
private Point extremite1;
private Point extremite2;
private Color couleur;
/** Construire un Segment à partir de ses deux points extrémités.
* @param ext1 le premier point extrémité
* @param ext2 le deuxième point extrémité
*/
public Segment(Point ext1, Point ext2) {
this.extremite1 = ext1;
this.extremite2 = ext2;
this.couleur = Color.green;
}
/** Translater le segment.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
// System.err.println("Segment.translater(double, double) non implantée");
this.extremite1.translater(dx, dy);
this.extremite2.translater(dx, dy);
}
/** Obtenir la longueur du segment.
* @return la longueur du segment
*/
public double longueur() {
// System.err.println("Segment.longueur() non implantée");
return Math.sqrt(
Math.pow(this.extremite1.getY() - this.extremite2.getY(), 2)
+ Math.pow(this.extremite1.getX() - this.extremite2.getX(), 2));
}
/** Afficher le segment. Le segment est affiché sous la forme :
* <PRE>
* [extremite1-extremite2]
* </PRE>
*/
public void afficher() {
// System.err.println("Segment.afficher() non implantée");
System.out.print("[ ");
this.extremite1.afficher();
System.out.print(" - ");
this.extremite2.afficher();
System.out.print(" ]");
}
/** Obtenir la couleur du segment.
* @return la couleur du segment
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du segment.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
public Point getExtremite(int id) {
if (id == 1) {
return this.extremite1;
} else {
return this.extremite2;
}
}
}

45
TP01/TestSchema.java Normal file
View file

@ -0,0 +1,45 @@
/** Programme de test de la classe Schéma.
* @author
* @version 1.4
*/
public class TestSchema {
public static void main(String[] args) {
// Créer trois points et un schéma à partir de ces points
Point p1 = new Point(3, 2);
Point p2 = new Point(11, 4);
Point p3 = new Point(6, 9);
Schema s = new Schema(p1, p2, p3);
// Afficher le schéma
System.out.println("s = "); s.afficher(); System.out.println();
// Translater le segment
System.out.println("> s.translater(10, 100);");
s.translater(10, 100);
// Afficher le schéma
System.out.println("s = "); s.afficher(); System.out.println();
// vérif
if (p1.getX() != 13) {
System.out.println("ERREUR pour translater p1.x !");
}
if (p1.getY() != 102) {
System.out.println("ERREUR pour translater p1.y !");
}
if (p2.getX() != 21) {
System.out.println("ERREUR pour translater p2.x !");
}
if (p2.getY() != 104) {
System.out.println("ERREUR pour translater p2.y !");
}
if (p3.getX() != 16) {
System.out.println("ERREUR pour translater p3.x !");
}
if (p3.getY() != 109) {
System.out.println("ERREUR pour translater p3.y !");
}
}
}

47
TP01/TestSegment.java Normal file
View file

@ -0,0 +1,47 @@
/** Programme de test de la classe Segment.
* @author Xavier Crégut
* @version 1.4
*/
public class TestSegment {
public static void main(String[] args) {
// Créer deux points et un segment à partir de ces points
Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
Segment s = new Segment(p1, p2);
// Afficher le segment
System.out.print("s = "); s.afficher(); System.out.println();
// Afficher la longueur du segment
System.out.println("longueur de s = " + s.longueur());
if (s.longueur() != 5) {
System.out.println("ERREUR : la longueur devrait être 5 !");
}
// Translater le segment
System.out.println("> s.translater(10, 100);");
s.translater(10, 100);
if (p1.getX() != 10) {
System.out.println("ERREUR pour translater extrémité1.x !");
}
if (p1.getY() != 100) {
System.out.println("ERREUR pour translater extrémité1.y !");
}
if (p2.getX() != 13) {
System.out.println("ERREUR pour translater extrémité2.x !");
}
if (p2.getY() != 104) {
System.out.println("ERREUR pour translater extrémité2.y !");
}
// Afficher le segment
System.out.print("s = "); s.afficher(); System.out.println();
// Afficher la longueur du segment
System.out.println("longueur de s = " + s.longueur());
if (s.longueur() != 5) {
System.out.println("ERREUR : la longueur devrait être 5 !");
}
}
}

Binary file not shown.

13
TP02/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,13 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"/usr/share/java/hamcrest-core.jar",
"/usr/share/java/junit.jar"
],
"files.exclude": {
"**/.classpath": true,
"**/.project": true,
"**/.settings": true,
"**/.factorypath": true
}
}

117
TP02/Point.java Normal file
View file

@ -0,0 +1,117 @@
import java.awt.Color;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
public class Point {
/** Construire un point à partir de son abscisse et de son ordonnée.
* @param vx abscisse
* @param vy ordonnée
*/
public Point(double vx, double vy) {
// System.out.println("CONSTRUCTEUR Point(" + vx + ", " + vy + ")");
this.x = vx;
this.y = vy;
this.couleur = Color.green;
}
/** Obtenir l'abscisse du point.
* @return abscisse du point
*/
public double getX() {
return this.x;
}
/** Obtenir l'ordonnée du point.
* @return ordonnée du point
*/
public double getY() {
return this.y;
}
/** Changer l'abscisse du point.
* @param vx nouvelle abscisse
*/
public void setX(double vx) {
this.x = vx;
}
/** Changer l'ordonnée du point.
* @param vy nouvelle ordonnée
*/
public void setY(double vy) {
this.y = vy;
}
/** Afficher le point. */
public void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
}
/** Distance par rapport à un autre point.
* @param autre l'autre point
* @return distance entre this et autre
*/
public double distance(Point autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
/*
// La méthode finalize est appelée avant que le récupérateur de
// mémoire ne détruise l'objet. Attention toutefois, on ne sait
// pas quand ces ressources seront libérées et il est donc
// dangereux de s'appuyer sur ce mécanisme pour libérer des
// ressources qui sont en nombre limité.
//
// D'autre part, pour être sûr que les méthodes << finalize >>
// sont appelées avant la fermeture de Java, il faut appeler la
// méthode statique :
// System.runFinalizersOnExit(true)
//
protected void finalize() {
System.out.print("DESTRUCTION du point : ");
this.afficher();
System.out.println();
}
*/
// Représentation interne d'un point
// ---------------------------------
// Remarque : en Java, il est conseillé (convention de programmation)
// de mettre les attributs au début de la classe.
private double x; // abscisse
private double y; // ordonnée
private Color couleur; // couleur du point
}

101
TP02/PointTest.java Normal file
View file

@ -0,0 +1,101 @@
import org.junit.*;
import static org.junit.Assert.*;
import java.awt.Color;
/** Programme de test de la classe Point.
* @author Xavier Crégut
* @version 1.11
*/
public class PointTest {
public static final double EPSILON = 1e-6;
// précision pour la comparaison entre réels.
private Point p1;
private Point p2;
@Before
public void setUp() {
p1 = new Point(1, 2);
p2 = new Point(4, -2);
}
@Test
public void testInitialisation() {
assertTrue(p1 != null);
assertTrue(p2 != null);
assertTrue(p1.getX() == 1);
assertTrue(p1.getY() == 2);
assertTrue(p2.getX() == 4);
assertTrue(p2.getY() == -2);
}
@Test
public void testInitialisationMieux() {
assertNotNull(p1);
assertNotNull(p2);
// Remarque : faire un test d'égalité sur des réels est à éviter
// à cause des erreurs d'arrondi. En conséquence, il faut
// vérifier que les deux nombres sont égaux à EPSILON près.
// C'est ce que fait assertEquals(attendu, réel, précision)
assertEquals(1.0, p1.getX(), EPSILON);
assertEquals(2.0, p1.getY(), EPSILON);
assertEquals(4.0, p2.getX(), EPSILON);
assertEquals(-2.0, p2.getY(), EPSILON);
}
@Test
public void testSetX() {
p1.setX(10);
assertEquals(10.0, p1.getX(), EPSILON);
p1.setX(-5);
assertEquals(-5.0, p1.getX(), EPSILON);
}
@Test
public void testSetY() {
p1.setY(10);
assertEquals(10.0, p1.getY(), EPSILON);
p1.setY(-5);
assertEquals(-5.0, p1.getY(), EPSILON);
}
@Test
public void testDistance() {
assertEquals(0.0, p1.distance(p1), EPSILON);
assertEquals(0.0, p2.distance(p2), EPSILON);
assertEquals(5.0, p1.distance(p2), EPSILON);
assertEquals(5.0, p2.distance(p1), EPSILON);
}
@Test
public void testTranslater1() {
p1.translater(2, 4);
assertEquals(3.0, p1.getX(), EPSILON);
assertEquals(6.0, p1.getY(), EPSILON);
}
@Test
public void testTranslater2() {
p2.translater(-2, -4);
assertEquals(2.0, p2.getX(), EPSILON);
assertEquals(-6.0, p2.getY(), EPSILON);
}
@Test
public void testCouleur() {
assertEquals(p1.getCouleur(), Color.GREEN);
assertEquals(p2.getCouleur(), Color.GREEN);
}
@Test
public void testSetCouleur() {
p1.setCouleur(Color.RED);
p2.setCouleur(Color.BLUE);
assertEquals(p1.getCouleur(), Color.RED);
assertEquals(p2.getCouleur(), Color.BLUE);
}
}

Binary file not shown.

View file

6
TP04/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"afficheur.jar"
]
}

46
TP04/AfficheurTexte.java Normal file
View file

@ -0,0 +1,46 @@
import afficheur.Afficheur;
public class AfficheurTexte implements Afficheur {
public void dessinerPoint(double x, double y, java.awt.Color c) {
System.out.println("Point {");
System.out.printf(" x = %f\n", x);
System.out.printf(" y = %f\n", y);
System.out.print( " couleur = ");
System.out.println(c);
System.out.println("}");
}
public void dessinerLigne(double x1, double y1, double x2, double y2, java.awt.Color c) {
System.out.println("Ligne {");
System.out.printf(" x1 = %f\n", x1);
System.out.printf(" y1 = %f\n", y1);
System.out.printf(" x2 = %f\n", x2);
System.out.printf(" y2 = %f\n", y2);
System.out.print( " couleur = ");
System.out.println(c);
System.out.println("}");
}
public void dessinerCercle(double x, double y, double rayon, java.awt.Color c) {
System.out.println("Cercle {");
System.out.printf(" centre_x = %f\n", x);
System.out.printf(" centre_y = %f\n", y);
System.out.printf(" rayon = %f\n", rayon);
System.out.print( " couleur = ");
System.out.println(c);
System.out.println("}");
}
public void dessinerTexte(double x, double y, java.lang.String texte, java.awt.Color c) {
System.out.println("Texte {");
System.out.printf(" x = %f\n", x);
System.out.printf(" y = %f\n", y);
System.out.printf(" valeur = %s\n", texte);
System.out.print( " couleur = ");
System.out.println(c);
System.out.println("}");
}
}

31
TP04/ExempleEcran.java Normal file
View file

@ -0,0 +1,31 @@
import afficheur.AfficheurSVG;
import afficheur.Ecran;
import java.awt.Color;
/**
* Exemple d'utilisation de la classe Ecran.
*/
class ExempleEcran {
public static void main(String[] args) {
// Construire un écran
// AfficheurTexte monEcran = new AfficheurTexte();
Ecran monEcran = new Ecran("ExempleEcran", 400, 250, 15);
// Dessiner les axes
monEcran.dessinerAxes();
// Dessiner un point vert de coordonnées (1, 2)
monEcran.dessinerPoint(1, 2, Color.GREEN);
// Dessiner un segment rouge d'extrémités (6, 2) et (11, 9)
monEcran.dessinerLigne(6, 2, 11, 9, Color.RED);
// Dessiner un cercle jaune de centre (4, 3) et rayon 2.5
monEcran.dessinerCercle(4, 3, 2.5, Color.YELLOW);
// Dessiner le texte "Premier dessin" en bleu à la position (1, -2)
monEcran.dessinerTexte(1, -2, "Premier dessin", Color.BLUE);
}
}

70
TP04/ExempleSchema1.java Normal file
View file

@ -0,0 +1,70 @@
import afficheur.AfficheurSVG;
import java.awt.Color;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7 $
*/
public class ExempleSchema1 {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new Point(3, 2);
Point p2 = new Point(6, 9);
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new Point(sx / 3, sy / 3);
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Construire un écran
// AfficheurSVG monEcran = new AfficheurSVG("ExempleSchema1", "schemaSVG", 600, 400);
AfficheurTexte monEcran = new AfficheurTexte();
// Dessiner sur l'écran
s12.dessiner(monEcran);
s23.dessiner(monEcran);
s31.dessiner(monEcran);
barycentre.dessiner(monEcran);
// Translater le schéma
s12.translater(4, -3);
s23.translater(4, -3);
s31.translater(4, -3);
barycentre.translater(4, -3);
// Redessiner sur l'écran
s12.dessiner(monEcran);
s23.dessiner(monEcran);
s31.dessiner(monEcran);
barycentre.dessiner(monEcran);
// Dessiner les axes
// monEcran.dessinerAxes();
// // Afficher le dessin
// monEcran.ecrire();
// // Écrire le dessin SVG dans un fichier
// monEcran.ecrire("schema.svg");
}
}

100
TP04/Point.java Normal file
View file

@ -0,0 +1,100 @@
import java.awt.Color;
import afficheur.Afficheur;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
public class Point {
private double x; // abscisse
private double y; // ordonnée
private Color couleur; // couleur du point
/** Construire un point à partir de son abscisse et de son ordonnée.
* @param vx abscisse
* @param vy ordonnée
*/
public Point(double vx, double vy) {
this.x = vx;
this.y = vy;
this.couleur = Color.green;
}
/** Obtenir l'abscisse du point.
* @return abscisse du point
*/
public double getX() {
return this.x;
}
/** Obtenir l'ordonnée du point.
* @return ordonnée du point
*/
public double getY() {
return this.y;
}
/** Changer l'abscisse du point.
* @param vx nouvelle abscisse
*/
public void setX(double vx) {
this.x = vx;
}
/** Changer l'ordonnée du point.
* @param vy nouvelle ordonnée
*/
public void setY(double vy) {
this.y = vy;
}
/** Afficher le point. */
public void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
}
/**
* Dessiner sur un écran le point.
* @param canvas Écran sur lequel on dessine
*/
public void dessiner(Afficheur canvas) {
canvas.dessinerPoint(this.x, this.y, this.couleur);
}
/** Distance par rapport à un autre point.
* @param autre l'autre point
* @return distance entre this et autre
*/
public double distance(Point autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

89
TP04/Segment.java Normal file
View file

@ -0,0 +1,89 @@
import java.awt.Color;
import afficheur.Afficheur;
/** Un segment est défini pas ses deux points qui constituent ses
* extrémités. Un segment peut être affiché et translaté.
*
* @author Xavier Crégut
* @version 1.9
*/
public class Segment {
private Point extremite1;
private Point extremite2;
private Color couleur;
/** Construire un Segment à partir de ses deux points extrémités.
* @param ext1 le premier point extrémité
* @param ext2 le deuxième point extrémité
*/
public Segment(Point ext1, Point ext2) {
this.extremite1 = ext1;
this.extremite2 = ext2;
this.couleur = Color.green;
}
/** Translater le segment.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
extremite1.translater(dx, dy);
extremite2.translater(dx, dy);
}
/** Obtenir la longueur du segment.
* @return la longueur du segment
*/
public double getLongueur() {
return this.extremite1.distance(this.extremite2);
}
/** @deprecated Cette méthode a changé de nom pour respecter
* la convention de nommage préconisée par Sun pour Java.
* @see #getLongueur()
*/
@Deprecated public double longueur() {
return this.extremite1.distance(this.extremite2);
}
/** Afficher le segment. Le segment est affiché sous la forme :
* <PRE>
* [extremite1-extremite2]
* </PRE>
*/
public void afficher() {
System.out.print("[");
this.extremite1.afficher();
System.out.print("-");
this.extremite2.afficher();
System.out.print("]");
}
/**
* Dessiner sur un écran le segment.
* @param canvas Écran sur lequel on dessine
*/
public void dessiner(Afficheur canvas) {
canvas.dessinerLigne(this.extremite1.getX(),
this.extremite1.getY(),
this.extremite2.getX(),
this.extremite2.getY(),
this.couleur);
}
/** Obtenir la couleur du segment.
* @return la couleur du segment
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du segment.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

BIN
TP04/afficheur.jar Normal file

Binary file not shown.

16
TP04/schema.svg Normal file
View file

@ -0,0 +1,16 @@
<?xml version='1.0'?>
<!-- Car l'axe des Y est inversé en SVG les y sont transformés en 10 - y
Toutes les coordonnées sont * 10
-->
<svg xmlns='http://www.w3.org/2000/svg' version="11" width="600" height="400">
<title>ExempleSchema1</title>
<desc>schemaSVG</desc>
<line x1="30" y1="80" x2="60" y2="10" stroke="rgb(0,255,0)"/>
<line x1="60" y1="10" x2="110" y2="60" stroke="rgb(0,255,0)"/>
<line x1="110" y1="60" x2="30" y2="80" stroke="rgb(0,255,0)"/>
<circle cx="66" cy="50" r="2" fill="rgb(0,255,0)"/>
<line x1="110" y1="140" x2="140" y2="70" stroke="rgb(0,255,0)"/>
<line x1="140" y1="70" x2="190" y2="120" stroke="rgb(0,255,0)"/>
<line x1="190" y1="120" x2="110" y2="140" stroke="rgb(0,255,0)"/>
<circle cx="106" cy="80" r="2" fill="rgb(0,255,0)"/>
</svg>

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

8
TP05/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"/usr/share/java/hamcrest-core.jar",
"/usr/share/java/junit.jar",
"afficheur.jar"
]
}

71
TP05/ExempleSchema1.java Normal file
View file

@ -0,0 +1,71 @@
import afficheur.Ecran;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7 $
*/
public class ExempleSchema1 {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* Ensuite, il est translaté et affiché de nouveau.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new Point(3, 2);
Point p2 = new Point(6, 9);
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new Point(sx / 3, sy / 3);
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Créer l'écran d'affichage
Ecran ecran = new Ecran("ExempleSchema1", 600, 400, 20);
ecran.dessinerAxes();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Translater le schéma
System.out.println("Translater le schéma de (4, -3) : ");
s12.translater(4, -3);
s23.translater(4, -3);
s31.translater(4, -3);
barycentre.translater(4, -3);
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Forcer l'affichage du schéma (au cas ...)
ecran.rafraichir();
}
}

71
TP05/ExempleSchema2.java Normal file
View file

@ -0,0 +1,71 @@
import afficheur.Ecran;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7 $
*/
public class ExempleSchema2 {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* Ensuite, il est translaté et affiché de nouveau.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new PointNomme(3, 2, "A");
Point p2 = new PointNomme(6, 9, "S");
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new PointNomme(sx / 3, sy / 3, "C");
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Créer l'écran d'affichage
Ecran ecran = new Ecran("ExempleSchema1", 600, 400, 20);
ecran.dessinerAxes();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Translater le schéma
System.out.println("Translater le schéma de (4, -3) : ");
s12.translater(4, -3);
s23.translater(4, -3);
s31.translater(4, -3);
barycentre.translater(4, -3);
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Forcer l'affichage du schéma (au cas ...)
ecran.rafraichir();
}
}

108
TP05/Point.java Normal file
View file

@ -0,0 +1,108 @@
import java.awt.Color;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
* Le point peut être dessiné sur un afficheur.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
// si on met final, aucune des méthodes de Point nest polymorphe)
public /* final */ class Point {
private double x; // abscisse
private double y; // ordonnée
//@ private invariant getCouleur() != null;
//@ private invariant getCouleur() == couleur; // invariant de liaison
private Color couleur; // couleur du point
/** Construire un point à partir de son abscisse et de son ordonnée.
* @param vx abscisse
* @param vy ordonnée
*/
public Point(double vx, double vy) {
this.x = vx;
this.y = vy;
this.couleur = Color.green;
}
/** Obtenir l'abscisse du point.
* @return abscisse du point
*/
//@ pure
public double getX() {
return this.x;
}
/** Obtenir l'ordonnée du point.
* @return ordonnée du point
*/
//@ pure
public double getY() {
return this.y;
}
/** Changer l'abscisse du point.
* @param vx nouvelle abscisse
*/
public void setX(double vx) {
this.x = vx;
}
/** Changer l'ordonnée du point.
* @param vy nouvelle ordonnée
*/
public void setY(double vy) {
this.y = vy;
}
/** Afficher le point. */
public /* final */ void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
} // si on met final, on ne peut pas override cette méthode dans pointNomme
/** Distance par rapport à un autre point.
* @param autre l'autre point
* @return distance entre this et autre
*/
//@ pure
public double distance(Point autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
/** Dessiner le point sur l'afficheur.
* @param afficheur l'afficheur à utiliser
*/
public void dessiner(afficheur.Afficheur afficheur) {
afficheur.dessinerPoint(this.getX(), this.getY(), this.getCouleur());
}
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
//@ pure
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

50
TP05/PointNomme.java Normal file
View file

@ -0,0 +1,50 @@
/** Un point nommé est un point avec un nom.
* @author Xavier Crégut
* @version 1.7
*/
public class PointNomme extends Point {
private String nom; // le nom du point nommé
/** Construire un point nommé à partir de son abscisse, son
* ordonnée et son nom.
* @param vx valeur de l'abscisse
* @param vy valeur de l'ordonnée
* @param sonNom nom à donner au point
*/
public PointNomme(double vx, double vy, String sonNom) {
super(vx, vy); // toujours en première ligne !
this.setNom(sonNom);
}
/** Obtenir le nom du point nommé.
* @return le nom du point nommé
*/
public String getNom() {
return this.nom;
}
/** Changer le nom du point nommé.
* @param sonNom le nouveau nom
*/
public void setNom(String sonNom) {
this.nom = sonNom;
}
/** Afficher le point nommé. Le point est affiché sous la forme :
* <PRE>
* nom:(x, y)
* </PRE>
*/
@Override public void afficher() {
System.out.print(this.getNom() + ":");
super.afficher(); // utiliser afficher de Point
}
@Override public void dessiner(afficheur.Afficheur afficheur) {
super.dessiner(afficheur); // utiliser dessiner de Point
afficheur.dessinerTexte (this.getX(), this.getY(),
this.getNom(), this.getCouleur());
}
}

90
TP05/Segment.java Normal file
View file

@ -0,0 +1,90 @@
import java.awt.Color;
/** Un segment est défini pas ses deux points qui constituent ses
* extrémités. Un segment peut être affiché et translaté.
* Le segment peut être dessiné sur un afficheur.
*
* @author Xavier Crégut
* @version 1.9
*/
public class Segment {
private Point extremite1;
private Point extremite2;
private Color couleur;
/** Construire un Segment à partir de ses deux points extrémités.
* @param ext1 le premier point extrémité
* @param ext2 le deuxième point extrémité
*/
public Segment(Point ext1, Point ext2) {
this.extremite1 = ext1;
this.extremite2 = ext2;
this.couleur = Color.green;
}
/** Translater le segment.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
extremite1.translater(dx, dy);
extremite2.translater(dx, dy);
}
/** Dessiner le segment sur l'afficheur.
* @param afficheur l'afficheur à utiliser
*/
public void dessiner(afficheur.Afficheur afficheur) {
afficheur.dessinerLigne(this.extremite1.getX(), this.extremite1.getY(),
this.extremite2.getX(), this.extremite2.getY(),
this.getCouleur());
// Dessiner les deux extrémités : est-ce bien normal ?
this.extremite1.dessiner(afficheur);
this.extremite2.dessiner(afficheur);
}
/** Obtenir la longueur du segment.
* @return la longueur du segment
*/
public double getLongueur() {
return this.extremite1.distance(this.extremite2);
}
/** @deprecated Cette méthode a changé de nom pour respecter
* la convention de nommage préconisée par Sun pour Java.
* @see #getLongueur()
*/
@Deprecated public double longueur() {
return this.extremite1.distance(this.extremite2);
}
/** Afficher le segment. Le segment est affiché sous la forme :
* <PRE>
* [extremite1-extremite2]
* </PRE>
*/
public void afficher() {
System.out.print("[");
this.extremite1.afficher();
System.out.print("-");
this.extremite2.afficher();
System.out.print("]");
}
/** Obtenir la couleur du segment.
* @return la couleur du segment
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du segment.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

102
TP05/TestPolymorphisme.java Normal file
View file

@ -0,0 +1,102 @@
/** Tester le polymorphisme(principe de substitution) et la liaison
* dynamique.
* @author Xavier Crégut
* @version 1.5
*/
public class TestPolymorphisme {
/** Méthode principale */
public static void main(String[] args) {
// Créer et afficher un point p1
Point p1 = new Point(3, 4); // Est-ce autorisé ? Pourquoi ?
// oui, on utilise le constructeur de la classe
p1.translater(10,10); // Quel est le translater exécuté ?
// celui de Point
System.out.print("p1 = "); p1.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// p1 = (13.0, 14.0)
// Créer et afficher un point nommé pn1
PointNomme pn1 = new PointNomme(30, 40, "PN1");
// Est-ce autorisé ? Pourquoi ?
// oui, on utilise le constructeur de la classe
pn1.translater(10,10); // Quel est le translater exécuté ?
// celui de PointNomme, donc celui de Point par héritage
System.out.print("pn1 = "); pn1.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// pn1 = PN1:(40.0, 50.0)
// Définir une poignée sur un point
Point q;
// Attacher un point à q et l'afficher
q = p1; // Est-ce autorisé ? Pourquoi ?
// oui, les types des deux objets sont les mêmes
System.out.println("> q = p1;");
System.out.print("q = "); q.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// q = (13.0, 14.0)
// Attacher un point nommé à q et l'afficher
q = pn1; // Est-ce autorisé ? Pourquoi ?
// oui, PointNommé est pas un sous-type de Point
System.out.println("> q = pn1;");
System.out.print("q = "); q.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// q = PN1:(40.0, 50.0)
// Définir une poignée sur un point nommé
PointNomme qn;
// Attacher un point à q et l'afficher
// qn = p1; // Est-ce autorisé ? Pourquoi ?
// Non, Point nest pas un sous-type de PointNommé
// System.out.println("> qn = p1;");
// System.out.print("qn = "); qn.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// rien, ça compile pas
// Attacher un point nommé à qn et l'afficher
qn = pn1; // Est-ce autorisé ? Pourquoi ?
// oui, les types des deux objets sont les mêmes
System.out.println("> qn = pn1;");
System.out.print("qn = "); qn.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// qn = PN1:(40.0, 50.0)
double d1 = p1.distance(pn1); // Est-ce autorisé ? Pourquoi ?
// oui, par Liaison dynamique
System.out.println("distance = " + d1);
double d2 = pn1.distance(p1); // Est-ce autorisé ? Pourquoi ?
// oui, par héritage
System.out.println("distance = " + d2);
double d3 = pn1.distance(pn1); // Est-ce autorisé ? Pourquoi ?
// oui, par héritage
System.out.println("distance = " + d3);
System.out.println("> qn = q;");
// qn = q; // Est-ce autorisé ? Pourquoi ?
// Non, Point nest pas un sous-type de PointNommé
// System.out.print("qn = "); qn.afficher(); System.out.println();
// Qu'est ce qui est affiché ?
// rien, erreur de compilation
System.out.println("> qn = (PointNomme) q;");
qn = (PointNomme) q; // Est-ce autorisé ? Pourquoi ?
// oui, car q = pn1, transtypage
System.out.print("qn = "); qn.afficher(); System.out.println();
// System.out.println("> qn = (PointNomme) p1;");
// qn = (PointNomme) p1; // Est-ce autorisé ? Pourquoi ?
// non, p1 ne comporte pas de nom, conversion impossible
// System.out.print("qn = "); qn.afficher(); System.out.println();
}
}

BIN
TP05/afficheur.jar Normal file

Binary file not shown.

Binary file not shown.

8
TP06/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"/usr/share/java/hamcrest-core.jar",
"/usr/share/java/junit.jar",
"/home/laurent/Documents/Cours/ENSEEIHT/S6 - Technologie objet/tps/TP05/afficheur.jar"
]
}

72
TP06/ExempleSchema2.java Normal file
View file

@ -0,0 +1,72 @@
import afficheur.Ecran;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* des points nommés
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7 $
*/
public class ExempleSchema2 {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* Ensuite, il est translaté et affiché de nouveau.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new PointNomme(3, 2, "A");
Point p2 = new PointNomme(6, 9, "S");
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new PointNomme(sx / 3, sy / 3, "C");
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Créer l'écran d'affichage
Ecran ecran = new Ecran("ExempleSchema2", 600, 400, 20);
ecran.dessinerAxes();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Translater le schéma
System.out.println("Translater le schéma de (4, -3) : ");
s12.translater(4, -3);
s23.translater(4, -3);
s31.translater(4, -3);
barycentre.translater(4, -3);
// Afficher le schéma
System.out.println("Le schéma est composé de : ");
s12.afficher(); System.out.println();
s23.afficher(); System.out.println();
s31.afficher(); System.out.println();
barycentre.afficher(); System.out.println();
// Dessiner le schéma sur l'écran graphique
s12.dessiner(ecran);
s23.dessiner(ecran);
s31.dessiner(ecran);
barycentre.dessiner(ecran);
// Forcer l'affichage du schéma (au cas ...)
ecran.rafraichir();
}
}

View file

@ -0,0 +1,68 @@
import afficheur.Ecran;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* des points nommés
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7$
*/
public class ExempleSchemaGroupe {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* Ensuite, il est translaté et affiché de nouveau.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new PointNomme(3, 2, "A");
Point p2 = new PointNomme(6, 9, "S");
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new PointNomme(sx / 3, sy / 3, "C");
// Définir le schéma (vide)
// Geometrique[] schema = new Geometrique[10]; // le schéma
// 10 : capacité suffisante ici, non contrôlée dans la suite.
//int nb = 0; // Le nombre d'éléments dans le schéma
Groupe liste = new Groupe();
// Peupler le schéma
liste.ajouter(s12);
liste.ajouter(s23);
liste.ajouter(s31);
liste.ajouter(barycentre);
// Afficher le schéma
liste.afficher();
// Créer l'écran d'affichage
Ecran ecran = new Ecran("ExempleSchemaTab", 600, 400, 20);
ecran.dessinerAxes();
// Dessiner le schéma sur l'écran graphique
liste.dessiner(ecran);
// Translater le schéma
liste.translater(4, -3);
// Afficher le schéma
liste.afficher();
// Dessiner le schéma sur l'écran graphique
liste.dessiner(ecran);
// Forcer l'affichage du schéma (au cas ...)
ecran.rafraichir();
}
}

View file

@ -0,0 +1,96 @@
import java.util.ArrayList;
import afficheur.Ecran;
/** Construire le schéma proposé dans le sujet de TP avec des points,
* des points nommés
* et des segments.
*
* @author Xavier Crégut
* @version $Revision: 1.7$
*/
public class ExempleSchemaTab {
/** Construire le schéma et le manipuler.
* Le schéma est affiché.
* Ensuite, il est translaté et affiché de nouveau.
* @param args les arguments de la ligne de commande
*/
public static void main(String[] args)
{
// Créer les trois segments
Point p1 = new PointNomme(3, 2, "A");
Point p2 = new PointNomme(6, 9, "S");
Point p3 = new Point(11, 4);
Segment s12 = new Segment(p1, p2);
Segment s23 = new Segment(p2, p3);
Segment s31 = new Segment(p3, p1);
// Créer le barycentre
double sx = p1.getX() + p2.getX() + p3.getX();
double sy = p1.getY() + p2.getY() + p3.getY();
Point barycentre = new PointNomme(sx / 3, sy / 3, "C");
// Définir le schéma (vide)
// Geometrique[] schema = new Geometrique[10]; // le schéma
// 10 : capacité suffisante ici, non contrôlée dans la suite.
//int nb = 0; // Le nombre d'éléments dans le schéma
ArrayList<Geometrique> schema = new ArrayList<Geometrique>();;
// Peupler le schéma
schema.add(s12);
schema.add(s23);
schema.add(s31);
schema.add(barycentre);
// // Afficher le schéma
// System.out.println("Le schéma est composé de : ");
// for (int i = 0; i < nb; i++) {
// schema[i].afficher();
// System.out.println();
// }
schema.forEach(obj -> {
obj.afficher();
System.out.println();
});
// Créer l'écran d'affichage
Ecran ecran = new Ecran("ExempleSchemaTab", 600, 400, 20);
ecran.dessinerAxes();
// // Dessiner le schéma sur l'écran graphique
// for (int i = 0; i < nb; i++) {
// schema[i].dessiner(ecran);
// }
schema.forEach(obj -> obj.dessiner(ecran));
// // Translater le schéma
// System.out.println("Translater le schéma de (4, -3) : ");
// for (int i = 0; i < nb; i++) {
// schema[i].translater(4, -3);
// }
schema.forEach(obj -> obj.translater(4, -3));
// // Afficher le schéma
// System.out.println("Le schéma est composé de : ");
// for (int i = 0; i < nb; i++) {
// schema[i].afficher();
// System.out.println();
// }
schema.forEach(obj -> {
obj.afficher();
System.out.println();
});
// // Dessiner le schéma sur l'écran graphique
// for (int i = 0; i < nb; i++) {
// schema[i].dessiner(ecran);
// }
schema.forEach(obj -> obj.dessiner(ecran));
// Forcer l'affichage du schéma (au cas ...)
ecran.rafraichir();
}
}

View file

@ -0,0 +1,103 @@
import org.junit.*;
import static org.junit.Assert.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.awt.Color;
/**
* Programme de test pour vérifier la bonne mise en oeuvre de la généralisation.
*
* @author Xavier Crégut <Prenom.Nom@enseeiht.fr>
*/
public class GeneralisationTest {
private Method getDeclaredMethod(Class<?> classe, String name, Class<?>... args) {
try {
return classe.getDeclaredMethod(name, args);
}
catch (NoSuchMethodException e) {
return null;
}
}
private Constructor<?> getDeclaredConstructor(Class<?> classe, Class<?>... args) {
try {
return classe.getDeclaredConstructor(args);
}
catch (NoSuchMethodException e) {
return null;
}
}
private Field getDeclaredField(Class<?> classe, String name) {
try {
return classe.getDeclaredField(name);
}
catch (NoSuchFieldException e) {
return null;
}
}
private void verifierLaSuperClasse(Class<?> superClasse) {
Method getCouleurMethod = getDeclaredMethod(superClasse, "getCouleur");
assertTrue("Pourquoi ne pas factoriser getCouleur() dans "
+ superClasse.getName() + " ?",
getCouleurMethod != null);
Method setCouleurMethod = getDeclaredMethod(superClasse, "setCouleur", Color.class);
assertTrue("Pourquoi ne pas factoriser setCouleur() dans "
+ superClasse.getName() + " ?",
setCouleurMethod != null);
Field couleurField = getDeclaredField(superClasse, "couleur");
assertTrue("Pourquoi ne pas factoriser l'attribut 'couleur' dans "
+ superClasse.getName() + " ?",
couleurField != null);
assertTrue("L'attribut 'couleur' devrait être privé !",
Modifier.isPrivate(couleurField.getModifiers()));
assertFalse("Pourquoi ne pas définir getCouleur() dans "
+ superClasse.getName() + " ?",
Modifier.isAbstract(getCouleurMethod.getModifiers()));
assertFalse("Pourquoi ne pas définir setCouleur() dans "
+ superClasse.getName() + " ?",
Modifier.isAbstract(setCouleurMethod.getModifiers()));
Constructor<?> constructeur = getDeclaredConstructor(superClasse, Color.class);
assertTrue("Pourquoi ne pas définir un constructeur pour initialiser"
+ " la couleur dans " + superClasse.getName() + " ?",
constructeur != null);
}
private void verifierGestionCouleur(Class<?> uneClasse) {
Class<?> superClasse = uneClasse.getSuperclass();
assertFalse("Il faut d'abord faire marcher ExempleSchemaTab !",
Object.class.equals(superClasse));
// Vérifier la super-classe
verifierLaSuperClasse(superClasse);
assertTrue("Pourquoi redéfinir la méthode getCouleur() dans "
+ uneClasse.getName() + " ?",
null == getDeclaredMethod(uneClasse, "getCouleur"));
assertTrue("Pourquoi redéfinir la méthode setCouleur() dans "
+ uneClasse.getName() + " ?",
null == getDeclaredMethod(uneClasse, "setCouleur", Color.class));
assertTrue("Pourquoi ne pas supprimer l'attribut 'couleur' de "
+ uneClasse.getName() + " ?",
null == getDeclaredField(uneClasse, "couleur"));
}
@Test
public void testerGeneralisationPoint() {
verifierGestionCouleur(Point.class);
}
@Test
public void testerGeneralisationSegment() {
verifierGestionCouleur(Segment.class);
}
}

55
TP06/Geometrique.java Normal file
View file

@ -0,0 +1,55 @@
import java.awt.Color;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
* Le point peut être dessiné sur un afficheur.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
abstract public class Geometrique {
//@ private invariant getCouleur() != null;
//@ private invariant getCouleur() == couleur; // invariant de liaison
private Color couleur; // couleur du point
/** Construire un point à partir de son abscisse et de son ordonnée.
*/
public Geometrique(Color couleur) {
this.couleur = couleur;
}
/** Afficher sur le terminal les caractéristiques de lobjet. */
abstract public void afficher();
/**
* Dessiner lobjet.
* @param afficheur Ecran sur lequel on dessine
* */
abstract public void dessiner(afficheur.Afficheur afficheur);
/**
* Translater lobjet géométrique.
* @param dx déplacement en X
* @param dy déplacement en Y
*/
abstract public void translater(double dx, double dy);
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
//@ pure
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

46
TP06/Groupe.java Normal file
View file

@ -0,0 +1,46 @@
import java.awt.Color;
import java.util.ArrayList;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
* Le point peut être dessiné sur un afficheur.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
public class Groupe {
private ArrayList<Geometrique> list = new ArrayList<Geometrique>();
public void ajouter(Geometrique obj) {
list.add(obj);
}
public void supprimer(Geometrique obj) {
list.remove(obj);
}
/** Afficher le point. */
public void afficher() {
list.forEach(obj -> {
obj.afficher();
System.out.println();
});
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
list.forEach(obj -> obj.translater(dx, dy));
}
/** Dessiner le point sur l'afficheur.
* @param afficheur l'afficheur à utiliser
*/
public void dessiner(afficheur.Afficheur afficheur) {
list.forEach(obj -> obj.dessiner(afficheur));
}
}

106
TP06/Point.java Normal file
View file

@ -0,0 +1,106 @@
import java.awt.Color;
/** Point modélise un point géométrique dans un plan équipé d'un
* repère cartésien. Un point peut être affiché et translaté.
* Sa distance par rapport à un autre point peut être obtenue.
* Le point peut être dessiné sur un afficheur.
*
* @author Xavier Crégut <Prénom.Nom@enseeiht.fr>
*/
public class Point extends Geometrique {
private double x; // abscisse
private double y; // ordonnée
//@ private invariant getCouleur() != null;
//@ private invariant getCouleur() == couleur; // invariant de liaison
private Color couleur; // couleur du point
/** Construire un point à partir de son abscisse et de son ordonnée.
* @param vx abscisse
* @param vy ordonnée
*/
public Point(double vx, double vy) {
super(Color.green);
this.x = vx;
this.y = vy;
}
/** Obtenir l'abscisse du point.
* @return abscisse du point
*/
//@ pure
public double getX() {
return this.x;
}
/** Obtenir l'ordonnée du point.
* @return ordonnée du point
*/
//@ pure
public double getY() {
return this.y;
}
/** Changer l'abscisse du point.
* @param vx nouvelle abscisse
*/
public void setX(double vx) {
this.x = vx;
}
/** Changer l'ordonnée du point.
* @param vy nouvelle ordonnée
*/
public void setY(double vy) {
this.y = vy;
}
/** Afficher le point. */
public void afficher() {
System.out.print("(" + this.x + ", " + this.y + ")");
}
/** Distance par rapport à un autre point.
* @param autre l'autre point
* @return distance entre this et autre
*/
//@ pure
public double distance(Point autre) {
return Math.sqrt(Math.pow(autre.x - this.x, 2)
+ Math.pow(autre.y - this.y, 2));
}
/** Translater le point.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
this.x += dx;
this.y += dy;
}
/** Dessiner le point sur l'afficheur.
* @param afficheur l'afficheur à utiliser
*/
public void dessiner(afficheur.Afficheur afficheur) {
afficheur.dessinerPoint(this.getX(), this.getY(), this.getCouleur());
}
// Gestion de la couleur
/** Obtenir la couleur du point.
* @return la couleur du point
*/
//@ pure
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du point.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

50
TP06/PointNomme.java Normal file
View file

@ -0,0 +1,50 @@
/** Un point nommé est un point avec un nom.
* @author Xavier Crégut
* @version 1.7
*/
public class PointNomme extends Point {
private String nom; // le nom du point nommé
/** Construire un point nommé à partir de son abscisse, son
* ordonnée et son nom.
* @param vx valeur de l'abscisse
* @param vy valeur de l'ordonnée
* @param sonNom nom à donner au point
*/
public PointNomme(double vx, double vy, String sonNom) {
super(vx, vy); // toujours en première ligne !
this.setNom(sonNom);
}
/** Obtenir le nom du point nommé.
* @return le nom du point nommé
*/
public String getNom() {
return this.nom;
}
/** Changer le nom du point nommé.
* @param sonNom le nouveau nom
*/
public void setNom(String sonNom) {
this.nom = sonNom;
}
/** Afficher le point nommé. Le point est affiché sous la forme :
* <PRE>
* nom:(x, y)
* </PRE>
*/
@Override public void afficher() {
System.out.print(this.getNom() + ":");
super.afficher(); // utiliser afficher de Point
}
@Override public void dessiner(afficheur.Afficheur afficheur) {
super.dessiner(afficheur); // utiliser dessiner de Point
afficheur.dessinerTexte (this.getX(), this.getY(),
this.getNom(), this.getCouleur());
}
}

82
TP06/Segment.java Normal file
View file

@ -0,0 +1,82 @@
import java.awt.Color;
/** Un segment est défini pas ses deux points qui constituent ses
* extrémités. Un segment peut être affiché et translaté.
* Le segment peut être dessiné sur un afficheur.
*
* @author Xavier Crégut
* @version 1.9
*/
public class Segment extends Geometrique {
private Point extremite1;
private Point extremite2;
private Color couleur;
/** Construire un Segment à partir de ses deux points extrémités.
* @param ext1 le premier point extrémité
* @param ext2 le deuxième point extrémité
*/
public Segment(Point ext1, Point ext2) {
super(Color.green);
this.extremite1 = ext1;
this.extremite2 = ext2;
}
/** Translater le segment.
* @param dx déplacement suivant l'axe des X
* @param dy déplacement suivant l'axe des Y
*/
public void translater(double dx, double dy) {
extremite1.translater(dx, dy);
extremite2.translater(dx, dy);
}
/** Dessiner le segment sur l'afficheur.
* @param afficheur l'afficheur à utiliser
*/
public void dessiner(afficheur.Afficheur afficheur) {
afficheur.dessinerLigne(this.extremite1.getX(), this.extremite1.getY(),
this.extremite2.getX(), this.extremite2.getY(),
this.getCouleur());
// Dessiner les deux extrémités : est-ce bien normal ?
this.extremite1.dessiner(afficheur);
this.extremite2.dessiner(afficheur);
}
/** Obtenir la longueur du segment.
* @return la longueur du segment
*/
public double longueur() {
return this.extremite1.distance(this.extremite2);
}
/** Afficher le segment. Le segment est affiché sous la forme :
* <PRE>
* [extremite1-extremite2]
* </PRE>
*/
public void afficher() {
System.out.print("[");
this.extremite1.afficher();
System.out.print("-");
this.extremite2.afficher();
System.out.print("]");
}
/** Obtenir la couleur du segment.
* @return la couleur du segment
*/
public Color getCouleur() {
return this.couleur;
}
/** Changer la couleur du segment.
* @param nouvelleCouleur nouvelle couleur
*/
public void setCouleur(Color nouvelleCouleur) {
this.couleur = nouvelleCouleur;
}
}

Binary file not shown.

399
TP07/Date.java Normal file
View file

@ -0,0 +1,399 @@
/**
* Définition d'une date dans le calendrier grégorien.
*
* @author Xavier Crégut
* @version 1.5
*/
public class Date {
/*@ // le jour, le mois et l'année sont valides
public invariant
Date.estValide(this.getJour(), this.getMois(), this.getAnnee());
// le quantième est valide
public invariant
Date.estQuantiemeValide(this.getQuantieme(), this.getAnnee());
private invariant // cumulJoursMois est cohérent avec nbJoursDansMois
(\forall int mois; 0 <= mois && mois < Date.cumulJoursMois.length;
Date.cumulJoursMois[mois] ==
(\sum int m; 0 <= m && m < mois; Date.nbJoursMois[m]));
@*/
/** Tableau du nombre de jours par mois (sans prendre en compte les
* années bissextiles). nbJoursMois[i] est le nombre de jours du
* mois de numéro i+1.
*/
private static int nbJoursMois[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/** Cumul des jours des mois précédents. cumulJoursMois[i] est le
* nombre cumulé des jours des mois dont les numéros sont dans
* l'intervalle 1..i-1.
*/
private static int cumulJoursMois[] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
/** le numéro du jour dans le mois */
private int jour;
/** le numéro du mois dans l'année */
private int mois;
/** l'année */
private int annee;
/** Construire une date à partir du numéro du jour, du numéro du mois et de
* l'année (qui doivent former une date valide).
* @param j le numéro du jour dans le mois m
* @param m le numéro du mois
* @param a l'année
*/
//@ requires Date.estValide(j, m, a);
//@ ensures getJour() == j;
//@ ensures getMois() == m;
//@ ensures getAnnee() == a;
public Date(int j, int m, int a) {
this._set(j, m, a);
// On ne peut pas appeler directement set(j, m, a) car comme elle est
// publique, elle provoque la vérification des invariants.
}
/** Construire une date à partir du quantième du jour dans l'année et de
* l'année.
* @param q le quantième du jour dans l'année
* @param a l'année
*/
//@ requires Date.estAnneeValide(a);
//@ requires Date.estQuantiemeValide(q, a);
//@ ensures getQuantieme() == q;
//@ ensures getAnnee() == a;
public Date(int q, int a) {
this._set(q, a);
}
/** Changer la date à partir du numéro du jour, du numéro du mois et de
* l'année.
* @param j le numéro du jour dans le mois m
* @param m le numéro du mois
* @param a l'année
*/
// Cette méthode est privée et déclarée comme <em>helper</em> de manière à
// ce que les invariants de la classe ne soient pas vérifiés quand elle
// appelée depuis une autre méthode de la classe.
//@ requires Date.estValide(j, m, a);
//@ ensures this.jour == j;
//@ ensures this.mois == m;
//@ ensures this.annee == a;
//@ helper
private void _set(int j, int m, int a) {
this.jour = j;
this.mois = m;
this.annee = a;
}
/** Changer la date à partir du numéro du jour, du numéro du mois et de
* l'année.
* @param j le numéro du jour dans le mois m
* @param m le numéro du mois
* @param a l'année
*/
//@ requires Date.estValide(j, m, a);
//@ ensures getJour() == j;
//@ ensures getMois() == m;
//@ ensures getAnnee() == a;
public void set(int j, int m, int a) {
this._set(j, m, a);
}
/** Changer la date à partir du quantième du jour dans l'année et de
* l'année.
* @param q le quantième du jour dans l'année
* @param a l'année
*/
//@ requires Date.estAnneeValide(a);
//@ requires Date.estQuantiemeValide(q, a);
//@ ensures getQuantieme() == q;
//@ ensures getAnnee() == a;
//@ helper
private void _set(int q, int a) {
// Initialiser l'année
this.annee = a;
// Initialiser le mois
this.mois = 1;
while (q > nbJoursDansMois(this.mois, a)) { // le mois est terminé
q = q - nbJoursDansMois(this.mois, a);
this.mois++;
}
// Initialiser les jours
this.jour = q;
}
/** Changer la date à partir du quantième du jour dans l'année et de
* l'année.
* @param q le quantième du jour dans l'année
* @param a l'année
*/
//@ requires Date.estAnneeValide(a);
//@ requires Date.estQuantiemeValide(q, a);
//@ ensures getQuantieme() == q;
//@ ensures getAnnee() == a;
public void set(int q, int a) {
this._set(q, a);
}
/** Obtenir le numéro du jour dans le mois.
* @return le numéro du jour dans le mois
*/
//@ pure
//@ helper
public int getJour() {
return this.jour;
}
/** Obtenir le numéro du mois dans l'année.
* @return le numéro du mois dans l'année
*/
//@ pure
//@ helper
public int getMois() {
return this.mois;
}
/** Obtenir l'année.
* @return l'année
*/
//@ pure
//@ helper
public int getAnnee() {
return this.annee;
}
/** Obtenir le quantième du jour dans l'année.
* @return le quantième du jour dans l'année
*/
//@ pure
//@ helper
public int getQuantieme() {
int resultat = this.jour // nb de jours dans le mois en cours
+ cumulJoursMois[this.mois-1]; // nb de jours des mois précédents
// Prendre en compte le cas de l'année bissextile
if (this.mois > 2 && estBissextile(this.annee)) {
resultat++;
}
return resultat;
}
/** Obtenir le nombres de jours depuis l'an 0.
* @return nombres de jours depuis l'an 0.
*/
//@ pure
public int getNbJoursDepuisAn0() {
int a = this.annee - 1; // nb d'années pleines
return this.getQuantieme() // nb de jours dans l'année en cours
+ 365 * a // années considérées non bissextiles
+ (a / 4 - a / 100 + a / 400); // nb d'années bissextiles
}
/** Afficher la date sous la forme jour/mois/année. */
public void afficher() {
System.out.println(this);
}
// Méthode définie dans objet. Je n'utilise pas un commentaire javadoc car
// le commentaire défini dans la classe parente est le commentaire à
// utiliser.
public String toString() {
return "" + int2String(this.jour)
+ '/' + int2String(this.mois)
+ '/' + this.annee;
// le "" intial est pour forcer la conversion en String,
// les caractères sont en effet compatibles avec les entiers !
}
/** Obtenir la représentation d'un entier sous la forme d'une chaîne de
* caractères avec au moins 2 caractères.
* @param entier l'entier à convertir
* @return la chaîne de caractères correspondant à entier
*/
private static String int2String(int entier) {
String prefixe = (entier >= 0 && entier < 10) ? "0" : "";
return prefixe + entier;
}
/** L'année a est-elle bissextile ?
* @param a l'année
* @return vrai si l'année est bissextile
*/
//@ pure
public static boolean estBissextile(int a) {
return (a % 4 == 0) // divisible par 4
&& ((a % 100 != 0) // et non divible par 100
|| (a % 400 == 0)); // sauf si divisible par 400
}
/** Nombre de jours dans le mois m de l'année a.
* @param m le numéro du mois
* @param a l'année
* @return le nombre de jours dans le mois m de l'année a
*/
//@ pure
public static int nbJoursDansMois(int m, int a) {
int resultat = nbJoursMois[m-1]; // nb de jours dans le mois
if (m == 2 && estBissextile(a)) { // cas du mois de février
resultat++;
}
return resultat;
}
/** Est-ce que le numéro de jour j est valide pour le mois m de l'année a ?
* @param j le numéro du jour dans le mois m
* @param m le numéro du mois
* @param a l'année
*/
//@ requires Date.estAnneeValide(a);
//@ requires Date.estMoisValide(m);
//@ pure
public static boolean estJourValide(int j, int m, int a) {
return 1 <= j && j <= nbJoursDansMois(m, a);
}
/** Est-ce que le numéro de mois m est valide ?
* @param m le numéro du mois
*/
//@ ensures \result <==> (1 <= m && m <= 12);
//@ pure
public static boolean estMoisValide(int m) {
return 1 <= m && m <= 12;
}
/** Est-ce que le quantième est valide ?
* @param q le numéro du jour dans l'année
* @param a l'année
*/
//@ pure
//@ helper
public static boolean estQuantiemeValide(int q, int a) {
boolean resultat = estAnneeValide(a);
int nbJours = 365; // nb de jours dans l'année a;
if (estBissextile(a)) {
nbJours++;
}
resultat = resultat && 1 <= q && q <= nbJours;
return resultat;
}
/** Est-ce que l'année est valide ?
* @param a l'année
*/
//@ ensures \result <==> a > 0;
//@ pure
public static boolean estAnneeValide(int a) {
return a > 0;
}
/** Est-ce que la date définie par le jour j, le mois m et l'année a est
* valide ?
* @param j le numéro du jour dans le mois m
* @param m le numéro du mois
* @param a l'année
*/
//@ pure
//@ helper
public static boolean estValide(int j, int m, int a) {
return estAnneeValide(a)
&& estMoisValide(m)
&& estJourValide(j, m, a);
}
// Relation d'ordre sur les dates
// ------------------------------
/** Déterminer si une date est antérieure strictement à une autre date.
* @param autre l'autre date (non nulle)
* @return cette date est-elle strictement antérieure à l'autre date ?
*/
/*@ requires autre != null; // l'autre date est définie
ensures \result == this.getAnnee() < autre.getAnnee()
|| (this.getAnnee() == autre.getAnnee()
&& getMois() < autre.getMois())
|| (this.getAnnee() == autre.getAnnee()
&& this.getMois() == autre.getMois()
&& this.getJour() < autre.getJour());
pure
@*/
public boolean lt(Date autre) {
if (this.getAnnee() != autre.getAnnee()) {
return this.getAnnee() < autre.getAnnee();
} else if (this.getMois() != autre.getMois()) {
return this.getMois() < autre.getMois();
} else {
return this.getJour() < autre.getJour();
}
}
/** Déterminer si une date est postérieure ou égale à une autre date.
* @param autre l'autre date (non nulle)
* @return cette date est-elle postérieure ou égale à l'autre date
*/
//@ ensures \result == ! lt(autre);
//@ pure
public boolean ge(Date autre) {
return ! this.lt(autre);
}
/** Déterminer si une date est strictement postérieure à une autre date.
* @param autre l'autre date (non nulle)
* @return cette date est-elle strictement postérieure à l'autre date
*/
//@ ensures \result == autre.lt(this);
//@ pure
public boolean gt(Date autre) {
return autre.lt(this);
// Utilisation obligatoire de this (on ne peut pas s'en passer).
}
/** Déterminer si une date est antérieure ou égale à une autre date.
* @param autre l'autre date (non nulle)
* @return cette date est-elle antérieure ou égale à l'autre date
*/
//@ ensures \result == !autre.lt(this);
//@ pure
public boolean le(Date autre) {
return ! autre.lt(this);
}
// Égalité de deux dates
// ---------------------
/** Déterminer si deux dates sont égales.
* @param autre l'autre date
* @return cette date est égale à l'autre date
*/
//@ ensures \result == (le(autre) && ge(autre));
//@ pure
public boolean equals(Date autre) {
return autre != null
&& this.getAnnee() == autre.getAnnee()
&& this.getMois() == autre.getMois()
&& this.getJour() == autre.getJour();
}
/** Déterminer si cette date est égale à un autre objet.
* Ceci est une redéfinition de la méthode définie dans Object
* @param objet l'autre objet
* @return cette date est égale à l'autre objet
*/
//@ pure
public boolean equals(/*@ nullable @*/ Object objet) {
return objet != null
&& (objet instanceof Date)
// XXX on pourrait faire aussi objet.getClass() == this.getClass()
&& equals((Date) objet);
}
}
// vi: sw=4 ts=4

14
TP07/ExempleDate1.java Normal file
View file

@ -0,0 +1,14 @@
// Que penser du programme suivant ?
public class ExempleDate1 {
public static void main (String args []) {
// Construire les dates
Date d1 = new Date(20, 5, 1989);
Date d2 = new Date(13, 2, 1993);
Date d3 = new Date(31, 6, 2001);
// Afficher les dates
System.out.println("d1 = " + d1);
System.out.println("d2 = " + d2);
System.out.println("d3 = " + d3);
}
}

BIN
TP07/openjml.zip Normal file

Binary file not shown.

7
TP08/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"/usr/share/java/junit.jar",
"/usr/share/java/hamcrest-core.jar"
]
}

11
TP08/Cellule.java Normal file
View file

@ -0,0 +1,11 @@
public class Cellule<E> {
public E element;
public Cellule<E> suivante;
public Cellule(E elm, Cellule<E> next) {
this.element = elm;
this.suivante = next;
}
}

5
TP08/Comparateur.java Normal file
View file

@ -0,0 +1,5 @@
public interface Comparateur<E> {
boolean inf(E n1, E n2);
}

29
TP08/Ensemble.java Normal file
View file

@ -0,0 +1,29 @@
/** Définition d'un ensemble d'entier. */
public interface Ensemble<E> {
//@ public invariant estVide() <==> cardinal() == 0;
//@ public invariant 0 <= cardinal();
/** Obtenir le nombre d'éléments dans l'ensemble.
* @return nombre d'éléments dans l'ensemble. */
/*@ pure helper @*/ int cardinal();
/** Savoir si l'ensemble est vide.
* @return Est-ce que l'ensemble est vide ? */
/*@ pure helper @*/ boolean estVide();
/** Savoir si un élément est présent dans l'ensemble.
* @param x l'élément cherché
* @return x est dans l'ensemble */
/*@ pure helper @*/ boolean contient(E x);
/** Ajouter un élément dans l'ensemble.
* @param x l'élément à ajouter */
//@ ensures contient(x); // élément ajouté
void ajouter(E x);
/** Enlever un élément de l'ensemble.
* @param x l'élément à supprimer */
//@ ensures ! contient(x); // élément supprimé
void supprimer(E x);
}

59
TP08/EnsembleChaine.java Normal file
View file

@ -0,0 +1,59 @@
public class EnsembleChaine<E> implements Ensemble<E> {
protected Cellule<E> premiere;
@Override
public int cardinal() {
int nb = 0;
Cellule<E> curseur = this.premiere;
while (curseur != null) {
nb++;
curseur = curseur.suivante;
}
return nb;
}
@Override
public boolean estVide() {
return this.premiere == null;
}
@Override
public boolean contient(E x) {
Cellule<E> curseur = this.premiere;
while (curseur != null) {
if (curseur.element == x) {
return true;
}
curseur = curseur.suivante;
}
return false;
}
@Override
public void ajouter(E x) {
if (!this.contient(x)) {
Cellule<E> newCellule = new Cellule<E>(x, this.premiere);
this.premiere = newCellule;
}
}
@Override
public void supprimer(E x) {
if (this.contient(x)) {
if (this.premiere.element == x) {
this.premiere = this.premiere.suivante;
} else {
Cellule<E> curseur = this.premiere;
while (curseur.suivante != null && curseur.suivante.element != x) {
curseur = curseur.suivante;
}
if (curseur.suivante != null) {
Cellule<E> save = curseur.suivante;
curseur.suivante = curseur.suivante.suivante;
save.suivante = null;
}
}
}
}
}

View file

@ -0,0 +1,54 @@
public class EnsembleChaineOrdonne<E> extends EnsembleChaine<E> implements EnsembleOrdonne<E> {
public Comparateur<E> comparateur;
@Override
public int cardinal() {
return super.cardinal();
}
@Override
public boolean estVide() {
return super.estVide();
}
@Override
public boolean contient(E x) {
return super.contient(x);
}
@Override
public void ajouter(E x) {
if (this.estVide()) {
super.premiere = new Cellule<E>(x, null);
} else if ( comparateur.inf(x, super.premiere.element) ) {
Cellule<E> newCellule = new Cellule<E>(x, super.premiere);
super.premiere = newCellule;
} else if (!this.contient(x)){
Cellule<E> curseur = this.premiere;
while (curseur != null && comparateur.inf(x, curseur.element) ) {
curseur = curseur.suivante;
}
curseur.suivante = new Cellule<E>(x, curseur.suivante);
}
}
@Override
public void supprimer(E x) {
super.supprimer(x);
}
@Override
public E min() {
E min = super.premiere.element;
Cellule<E> curseur = this.premiere;
while (curseur != null) {
if ( comparateur.inf(curseur.element, min) ) {
min = curseur.element;
}
curseur = curseur.suivante;
}
return min;
}
}

View file

@ -0,0 +1,12 @@
/**
* Classe de test pour EnsembleChaine.
*/
public class EnsembleChaineTest extends EnsembleTestAbstrait {
protected Ensemble<Integer> nouvelEnsemble(int capacite) {
EnsembleChaineOrdonne<Integer> ens = new EnsembleChaineOrdonne<Integer>();
ens.comparateur = new IntOrdreCroissant();
return ens;
}
}

View file

@ -0,0 +1,5 @@
public interface EnsembleOrdonne<E> extends Ensemble<E> {
E min();
}

View file

@ -0,0 +1,182 @@
import org.junit.*;
import static org.junit.Assert.*;
/** Programme de test JUnit pour les ensembles.
* @author Xavier Crégut &lt;prenom.nom@enseeiht.fr&gt;
*/
abstract public class EnsembleTestAbstrait {
protected Ensemble<Integer> e1;
private int[] tab0; // pour faire les tests élémentaires
@Before
public void setUp() throws Exception {
tab0 = new int[] { 10, 15, -5 };
this.e1 = nouvelEnsemble(10);
// System.out.println("e1 = " + e1);
}
abstract protected Ensemble<Integer> nouvelEnsemble(int capacite);
// la capacité sera utile dans le cas d'une ensemble tableau pour
// choisir la capacité initiale du tableau utilisé pour stocker les
// éléments.
static void ajouterTous(Ensemble<Integer> ens, int... elements) {
for (int n : elements) {
ens.ajouter(n);
}
}
@Test
public void testInitVide() {
assertNotNull(e1);
assertTrue(e1.estVide());
assertEquals(0, e1.cardinal());
}
@Test
public void testAjouterPremier() {
assertTrue(e1.estVide());
e1.ajouter(10);
assertFalse(e1.estVide());
assertEquals(1, e1.cardinal());
assertTrue(e1.contient(10));
}
@Test
public void testAjouterPlusieursFois() {
assertTrue(e1.estVide());
e1.ajouter(10);
e1.ajouter(10);
e1.ajouter(10);
e1.ajouter(10);
assertFalse(e1.estVide());
assertEquals(1, e1.cardinal());
assertTrue(e1.contient(10));
}
@Test
public void testAjouterTroisElements() {
e1.ajouter(10);
e1.ajouter(15);
e1.ajouter(-5);
assertEquals(3, e1.cardinal());
assertTrue(e1.contient(10));
assertTrue(e1.contient(-5));
assertTrue(e1.contient(15));
}
@Test
public void testContient() {
e1.ajouter(10);
e1.ajouter(15);
e1.ajouter(-5);
assertEquals(3, e1.cardinal());
assertTrue(e1.contient(10));
assertTrue(e1.contient(-5));
assertTrue(e1.contient(15));
assertFalse(e1.contient(1));
assertFalse(e1.contient(2));
assertFalse(e1.contient(100));
assertFalse(e1.contient(0));
}
@Test
public void testSupprimerAbsent() {
ajouterTous(e1, tab0);
assertFalse(e1.contient(1));
assertEquals(3, e1.cardinal());
e1.supprimer(1);
assertFalse(e1.contient(1));
assertEquals(3, e1.cardinal());
e1.supprimer(1);
e1.supprimer(1);
assertTrue(e1.contient(10));
assertTrue(e1.contient(-5));
assertTrue(e1.contient(15));
assertFalse(e1.contient(1));
assertFalse(e1.contient(2));
assertEquals(3, e1.cardinal());
}
@Test
public void testSupprimerPresent() {
ajouterTous(e1, tab0);
assertEquals(3, e1.cardinal());
assertTrue(e1.contient(10));
e1.supprimer(10);
assertFalse(e1.contient(10));
assertEquals(2, e1.cardinal());
assertTrue(e1.contient(-5));
assertTrue(e1.contient(15));
assertFalse(e1.contient(1));
assertFalse(e1.contient(2));
assertEquals(2, e1.cardinal());
}
@Test
public void testSupprimerDifferentsCas() {
ajouterTous(e1, tab0);
e1.supprimer(10);
assertFalse(e1.contient(10));
e1.supprimer(-5);
assertFalse(e1.contient(10));
assertFalse(e1.contient(-5));
assertTrue(e1.contient(15));
assertFalse(e1.contient(1));
assertFalse(e1.contient(2));
assertEquals(1, e1.cardinal());
e1.supprimer(15);
assertFalse(e1.contient(10));
assertFalse(e1.contient(-5));
assertFalse(e1.contient(15));
assertFalse(e1.contient(1));
assertFalse(e1.contient(2));
assertEquals(0, e1.cardinal());
assertTrue(e1.estVide());
}
/*@
requires tab.length > 0;
requires // éléments tous différents
(\forall int i1; i1 >= 0 && i1 < tab.length;
(\forall int i2; i2 >= 0 && i2 < i1;
tab[i1] != tab[i2]));
@*/
protected void testerAvecTab(int... tab) {
// Au fur et à mesure que l'on ajoute les éléments, on vérifie la
// présence des éléments.
for (int i = 0; i < tab.length; i++) {
e1.ajouter(tab[i]);
assertEquals(i+1, e1.cardinal());
// vérifier la présence des éléments insérés
for (int j = 0; j <= i; j++) {
assertTrue(e1.contient(tab[j]));
}
// vérifier l'absence des éléments à insérer
for (int j = i+1; j < tab.length; j++) {
assertFalse(e1.contient(tab[j]));
}
}
}
@Test
public void testerAvecTab1() {
testerAvecTab(10, 15, 12, 5, 20, -5, 0);
}
@Test
public void testerAvecTab2() {
testerAvecTab(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
@Test
public void testerAvecTab3() {
testerAvecTab(10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
}
}

View file

@ -0,0 +1,8 @@
public class IntOrdreCroissant implements Comparateur<Integer> {
@Override
public boolean inf(Integer n1, Integer n2) {
return n1 < n2;
}
}

7
TP09/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"/usr/share/java/junit.jar",
"/usr/share/java/hamcrest-core.jar"
]
}

48
TP09/Agenda.java Normal file
View file

@ -0,0 +1,48 @@
public interface Agenda {
/** Le plus petit créneau possible. */
int CRENEAU_MIN = 1;
/** Le plus grand créneau possible. */
int CRENEAU_MAX = 366;
/**
* Obtenir le nom de l'agenda.
* @return le nom de l'agenda
*/
String getNom();
/**
* Enregistrer un rendez-vous dans cet agenda.
*
* @param creneau le créneau du rendez-vous
* @param rdv le rendez-vous
* @throws CreneauInvalideException si le créneau est invalide
* @throws IllegalArgumentException si nom vaut null
* @throws OccupeException si le créneau n'est pas libre
*/
void enregistrer(int creneau, String rdv) throws CreneauInvalideException, IllegalArgumentException, OccupeException;
/**
* Annuler le rendez-vous pris à une creneau donnée.
* Rien ne se passe si le créneau est libre.
* Retourne vrai si l'agenda est modifié (un rendez-vous est annulé),
* faux sinon.
*
* @param creneau créneau du rendez-vous à annuler
* @return vrai si l'agenda est modifié
* @throws CreneauInvalideException si le créneau est invalide
*/
boolean annuler(int creneau) throws CreneauInvalideException;
/**
* Obtenir le rendez-vous pris à une creneau donnée.
*
* @param creneau le créneau du rendez-vous
* @return le rendez-vous à le créneau donnée
* @throws LibreException si pas de rendez-vous à ce créneau
* @throws CreneauInvalideException si le créneau est invalide
*/
String getRendezVous(int creneau) throws CreneauInvalideException, LibreException;
}

28
TP09/AgendaAbstrait.java Normal file
View file

@ -0,0 +1,28 @@
/**
* AgendaAbstrait factorise la définition du nom et de l'accesseur associé.
*/
public abstract class AgendaAbstrait extends ObjetNomme implements Agenda {
/**
* Initialiser le nom de l'agenda.
*
* @param nom le nom de l'agenda
* @throws IllegalArgumentException si nom n'a pas au moins un caractère
*/
public AgendaAbstrait(String nom) throws IllegalArgumentException {
super(nom);
}
/**
* Tester la validité d'un créneau
*
* @param creneau créneau que l'on souhaite valider
* @throws CreneauInvalideException si le créneau est invalide
*/
public void verifierCreneauValide(int creneau) throws CreneauInvalideException {
if ( creneau < Agenda.CRENEAU_MIN || creneau > Agenda.CRENEAU_MAX ) {
throw new CreneauInvalideException();
}
}
}

View file

@ -0,0 +1,59 @@
/**
* Définition d'un agenda individuel.
*/
public class AgendaIndividuel extends AgendaAbstrait {
/** Le texte des rendezVous */
private String[] rendezVous;
/**
* Créer un agenda vide (avec aucun rendez-vous).
*
* @param nom le nom de l'agenda
* @throws IllegalArgumentException si nom nul ou vide
*/
public AgendaIndividuel(String nom) throws IllegalArgumentException {
super(nom);
this.rendezVous = new String[Agenda.CRENEAU_MAX + 1];
// On gaspille une case (la première qui ne sera jamais utilisée)
// mais on évite de nombreux « creneau - 1 »
}
@Override
public void enregistrer(int creneau, String rdv) throws CreneauInvalideException, IllegalArgumentException, OccupeException {
super.verifierCreneauValide(creneau);
if (rdv == null || rdv.length() < 1) {
throw new IllegalArgumentException();
} else if (this.rendezVous[creneau] != null) {
throw new OccupeException();
} else {
this.rendezVous[creneau] = rdv;
}
}
@Override
public boolean annuler(int creneau) throws CreneauInvalideException {
super.verifierCreneauValide(creneau);
boolean modifie = this.rendezVous[creneau] != null;
this.rendezVous[creneau] = null;
return modifie;
}
@Override
public String getRendezVous(int creneau) throws CreneauInvalideException, LibreException {
super.verifierCreneauValide(creneau);
String rdv = this.rendezVous[creneau];
if (rdv == null) {
throw new LibreException();
} else {
return rdv;
}
}
}

View file

@ -0,0 +1,19 @@
/**
* Classe de test de AgendaIndividuel.
*
* @author Xavier Crégut <Prenom.Nom@enseeiht.fr>
*/
public class AgendaIndividuelTest extends AgendaTestAbstrait {
@Override
protected AgendaIndividuel nouvelAgenda(String nom) {
return new AgendaIndividuel(nom);
}
@Override
protected ObjetNomme nouvelObjetNomme(String nom) {
return nouvelAgenda(nom);
}
}

View file

@ -0,0 +1,108 @@
import org.junit.*;
import static org.junit.Assert.*;
/**
* Programme de test d'un agenda.
*/
abstract public class AgendaTestAbstrait extends ObjetNommeTest {
protected Agenda agenda;
final protected String jourAn = "Jour de l'an";
final protected String premierFevrier = "Février commence";
final protected String finAnnee = "Fin de l'année";
protected abstract Agenda nouvelAgenda(String nom);
@Override
protected abstract ObjetNomme nouvelObjetNomme(String nom);
@Before
public void setUp() throws OccupeException {
this.agenda = nouvelAgenda("Agenda");
this.agenda.enregistrer(1, jourAn);
this.agenda.enregistrer(32, premierFevrier);
this.agenda.enregistrer(365, finAnnee);
}
@Test
public void testerNom() {
assertEquals("A1", nouvelAgenda("A1").getNom());
assertEquals("A2", nouvelAgenda("A2").getNom());
}
@Test
public void testerGetRendezVous() throws LibreException {
assertEquals(jourAn, agenda.getRendezVous(1));
assertEquals(premierFevrier, agenda.getRendezVous(32));
assertEquals(finAnnee, agenda.getRendezVous(365));
}
@Test
public void testerAnnuler() throws Exception {
assertTrue(agenda.annuler(1));
assertFalse(agenda.annuler(2));
}
@Test
public void testerAnneeBissectile() throws LibreException, OccupeException {
agenda.enregistrer(Agenda.CRENEAU_MAX, "OK");
assertEquals("OK", agenda.getRendezVous(Agenda.CRENEAU_MAX));
}
@Test(expected=OccupeException.class)
public void testerRobustesseEnregistrerOccupe() throws Exception {
agenda.enregistrer(1, "UN");
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseEnregistrerCreneauPetit() throws Exception {
agenda.enregistrer(Agenda.CRENEAU_MIN - 1, "UN");
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseEnregistrerCreneauGrand() throws Exception {
agenda.enregistrer(Agenda.CRENEAU_MAX + 1, "UN");
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseAnnulerCreneauPetit() throws Exception {
agenda.annuler(Agenda.CRENEAU_MIN - 1);
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseAnnulerCreneauGrand() throws Exception {
agenda.annuler(Agenda.CRENEAU_MAX + 1);
}
@Test(expected=LibreException.class)
public void testerRobustesseGetRendezVousLibre() throws Exception {
agenda.getRendezVous(2);
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseGetRendezVousCreneauPetit() throws Exception {
agenda.getRendezVous(Agenda.CRENEAU_MIN - 1);
}
@Test(expected=CreneauInvalideException.class)
public void testerRobustesseGetRendezVousCreneauGrand() throws Exception {
agenda.getRendezVous(Agenda.CRENEAU_MAX + 1);
}
@Test(expected=IllegalArgumentException.class)
public void testerEnregistrerIllegalArgumentNull() throws Exception {
agenda.enregistrer(10, null);
}
@Test(expected=IllegalArgumentException.class)
public void testerEnregistrerIllegalArgumentVide() throws Exception {
agenda.enregistrer(10, "");
}
}

View file

@ -0,0 +1,5 @@
/**
* CreneauInvalideException indique qu'une date n'est pas valide.
*/
public class CreneauInvalideException extends RuntimeException {
}

45
TP09/ExceptionsTest.java Normal file
View file

@ -0,0 +1,45 @@
import org.junit.*;
import static org.junit.Assert.*;
/**
* Vérifier que les exceptions sont correctement définies.
*
* @author Xavier Crégut <Prenom.Nom@enseeiht.fr>
*/
public class ExceptionsTest {
public static boolean isUncheckedException(Class<?> classe) {
return Error.class.isAssignableFrom(classe)
|| RuntimeException.class.isAssignableFrom(classe);
}
public static boolean isCheckedException(Class<?> classe) {
return Throwable.class.isAssignableFrom(classe)
&& ! isUncheckedException(classe);
}
public void verifierEstRuntimeException(Class<?> classe) {
assertTrue(classe.getName() + " doit être une exception !",
Throwable.class.isAssignableFrom(classe));
assertTrue(classe.getName() + " doit être non vérifiée !",
isUncheckedException(classe));
assertFalse(classe.getName() + " : pourquoi en faire une Error ?",
Error.class.isAssignableFrom(classe));
}
public void verifierIsCheckedException(Class<?> classe) {
assertTrue(classe.getName() + " doit être une exception !",
Throwable.class.isAssignableFrom(classe));
assertTrue(classe.getName() + " doit être vérifiée !",
isCheckedException(classe));
}
@Test
public void testerExceptions() {
verifierEstRuntimeException(CreneauInvalideException.class);
verifierIsCheckedException(LibreException.class);
verifierIsCheckedException(OccupeException.class);
}
}

88
TP09/GroupeAgenda.java Normal file
View file

@ -0,0 +1,88 @@
import java.util.ArrayList;
public class GroupeAgenda extends AgendaAbstrait {
private ArrayList<Agenda> agendas;
public GroupeAgenda(String nom) {
super(nom);
this.agendas = new ArrayList<Agenda>();
}
public void ajouter(Agenda agenda) {
agendas.add(agenda);
}
public void ajouter(GroupeAgenda groupe) {
groupe.agendas.forEach(agenda -> {
this.ajouter(agenda);
});
}
@Override
public void enregistrer(int creneau, String rdv) throws CreneauInvalideException, IllegalArgumentException, OccupeException {
// vérif tous libres
Boolean rdv_present = false;
for (Agenda agenda : this.agendas) {
try {
agenda.getRendezVous(creneau);
rdv_present = true;
break;
} catch (LibreException e) {}
}
if (rdv_present) {
throw new OccupeException();
}
// si tous libre, enregistrer le rdv
for (Agenda agenda : this.agendas) {
try {
agenda.enregistrer(creneau, rdv);
} catch (IllegalArgumentException e) {
throw e;
} catch (OccupeException e) {
throw e;
}
}
}
@Override // TODO finir
public boolean annuler(int creneau) throws CreneauInvalideException {
Boolean rep = null;
for (Agenda agenda : this.agendas) {
rep = agenda.annuler(creneau);
}
return rep;
}
@Override
public String getRendezVous(int creneau) throws CreneauInvalideException, LibreException {
String rdv0 = this.agendas.get(0).getRendezVous(creneau);
Boolean diff = false;
Boolean one_free = false;
for (Agenda agenda : this.agendas) {
try {
String rdv = agenda.getRendezVous(creneau);
if (!rdv.equals(rdv0)) {
diff = true;
break;
}
} catch (LibreException e) {
one_free = true;
}
}
if (diff) {
return null;
} else if (one_free) {
throw new LibreException();
} else {
return rdv0;
}
}
}

View file

@ -0,0 +1,46 @@
import org.junit.*;
import static org.junit.Assert.*;
/**
* Classe de test pour la méthode proposer de GroupeAgenda.
*/
public class GroupeAgendaProposerTest extends GroupeAgendaTest {
private void testerProposer(GroupeAgenda g) throws Exception {
agenda2.enregistrer(15, "FAIT");
g.proposer(15, "OK");
assertEquals("OK", agenda1.getRendezVous(15));
assertEquals(null, g.getRendezVous(15));
if (g == superGroupe) {
assertEquals("OK", xavier.getRendezVous(15));
}
assertTrue(g.annuler(15)); // remettre dans l'état initial
}
@Test
public void testerProposer() throws Exception {
testerProposer(groupe);
testerProposer(superGroupe);
}
@Test(expected=IllegalArgumentException.class)
public void testerProposerIllegalArgumentNull() throws Exception {
groupe.proposer(10, null);
}
@Test(expected=IllegalArgumentException.class)
public void testerProposerIllegalArgumentVide() throws Exception {
groupe.proposer(10, "");
}
@Test(expected=CreneauInvalideException.class)
public void testerProposerCreaneauInvalideMin() throws Exception {
groupe.proposer(Agenda.CRENEAU_MIN - 1, "ERREUR");
}
@Test(expected=CreneauInvalideException.class)
public void testerProposerCreaneauInvalideMax() throws Exception {
groupe.proposer(Agenda.CRENEAU_MAX + 1, "ERREUR");
}
}

View file

@ -0,0 +1,74 @@
import org.junit.*;
import static org.junit.Assert.*;
/**
* GroupeAgendaTest
*
* @author Xavier Crégut <Prenom.Nom@enseeiht.fr>
*/
public class GroupeAgendaTest extends AgendaTestAbstrait {
// groupe contient agenda1 et agenda2
// superGroupe contient groupe et xavier
protected GroupeAgenda groupe;
protected Agenda agenda1, agenda2; // les deux sous-groupes
protected Agenda xavier;
protected GroupeAgenda superGroupe;
@Override
protected GroupeAgenda nouvelAgenda(String nom) {
this.groupe = new GroupeAgenda(nom);
this.agenda1 = new AgendaIndividuel(nom + "-agenda1");
this.agenda2 = new AgendaIndividuel(nom + "-agenda2");
groupe.ajouter(agenda1);
groupe.ajouter(agenda2);
this.xavier = new AgendaIndividuel(nom + "-Xavier");
this.superGroupe = new GroupeAgenda(nom + "-superGroupe");
this.superGroupe.ajouter(this.xavier);
this.superGroupe.ajouter(this.groupe);
return groupe;
}
@Override
protected ObjetNomme nouvelObjetNomme(String nom) {
return nouvelAgenda(nom);
}
@Test
public void testerInitialisationCorrecte() {
assertTrue(groupe == agenda);
}
@Test(expected=OccupeException.class)
public void testerEnregistrerPasTousLibres() throws Exception {
agenda2.enregistrer(10, "SEUL");
agenda.enregistrer(10, "OK ?");
}
@Test(expected=OccupeException.class)
public void testerEnregistrerPasTousLibresDansSousSousGroupe() throws Exception {
agenda2.enregistrer(10, "SEUL");
superGroupe.enregistrer(10, "OK ?");
}
private void testerAnnulerPasTousOccupe(Agenda a) throws Exception {
agenda2.enregistrer(10, "SEUL");
assertEquals(null, a.getRendezVous(10));
assertTrue(a.annuler(10));
String rdv = "OK ?";
a.enregistrer(10, rdv);
assertEquals(rdv, a.getRendezVous(10));
assertTrue(a.annuler(10));
}
@Test
public void testerAnnulerPasToutOccupe() throws Exception {
testerAnnulerPasTousOccupe(this.groupe);
testerAnnulerPasTousOccupe(this.superGroupe);
}
}

2
TP09/LibreException.java Normal file
View file

@ -0,0 +1,2 @@
public class LibreException extends Exception {
}

32
TP09/ObjetNomme.java Normal file
View file

@ -0,0 +1,32 @@
/**
* Un objet nommé est un objet qui a un nom.
*/
public abstract class ObjetNomme {
private String nom;
/**
* Initialiser le nom de l'agenda.
*
* @param nom le nom de l'agenda
* @throws IllegalArgumentException si nom n'a pas au moins un caractère
*/
public ObjetNomme(String nom) throws IllegalArgumentException {
if (nom == null || nom.length() < 1) {
throw new IllegalArgumentException();
} else {
this.nom = nom;
}
}
/**
* Obtenir le nom de cet objet.
* @return le nom de cet objet
*/
public String getNom() {
return this.nom;
}
}

45
TP09/ObjetNommeTest.java Normal file
View file

@ -0,0 +1,45 @@
import org.junit.*;
import static org.junit.Assert.*;
/**
* Classe de test de ObjetNomme.
*/
public class ObjetNommeTest {
/**
* Retourner un objet de type ObjetNomme qui sera utilisé pour les test.
* @param nom le nom à utiliser pour l'objet nommé
* @returns un objet nommé du nom fourni
*/
protected ObjetNomme nouvelObjetNomme(String nom) {
return new ObjetNommeConcret(nom);
}
private static class ObjetNommeConcret extends ObjetNomme {
public ObjetNommeConcret(String nom) {
super(nom);
}
}
@Test
public void testerGetNom() {
String unNom = "Petit nom";
ObjetNomme o = nouvelObjetNomme(unNom);
assertEquals(unNom, o.getNom());
assertSame("Pourquoi ne pas garder le même nom ?",
unNom, o.getNom());
}
@Test(expected=IllegalArgumentException.class)
public void testerConstructeurNomNul() {
nouvelObjetNomme(null);
}
@Test(expected=IllegalArgumentException.class)
public void testerConstructeurNomVide() {
nouvelObjetNomme("");
}
}

View file

@ -0,0 +1,2 @@
public class OccupeException extends Exception {
}

Binary file not shown.

157
TP10/editeur-menu.plantuml Normal file
View file

@ -0,0 +1,157 @@
@startuml
skinparam classAttributeIconSize 0
package menu {
class Menu {
- selection: Commande
--
+ estQuitté(): boolean
+ afficher()
+ selectionner()
+ valider()
+ ajouter(txt: String, op: Commande)
}
class Entree {
- texte: String
--
+ afficher(numéro: int)
__constructeurs__
+ Entree(texte: String, op: Commande)
}
interface Commande {
--
+ estExecutable(): boolean
+ executer()
}
Menu *-right-> "*\nentree" Entree: " "
Entree o-right-> "1\noperation" Commande: " "
}
note top of Menu
afficher():
for(int i = 0; i < entrees.size(); i++):
entrees.get(i).afficher(i + 1)
selectionner():
-- demander un entier et
-- initialiser 'selection' avec la commande associée
valider():
if (selection.estExecutable()):
selection.executer()
else:
out.println("Opération impossible")
end note
note top of Entree
afficher(numéro: int):
if (opération.estExecutable):
out.print(numéro)
else:
out.print(" ")
out.print(") " + texte)
end note
package editeur {
class Editeur {
--
+ editer()
__constructeurs__
+ Editeur(l: Ligne)
}
Editeur o-right-> "1\nligne" Ligne : " "
Editeur *--> "1\nmenuPrincipal" Menu
interface Ligne {
}
class LigneTab implements Ligne {
}
class LigneStringBuffer implements Ligne {
}
package commandes {
abstract class CommandeLigne implements Commande {
__constructeurs__
CommandeLigne(l: Ligne)
}
class AvancerCurseur extends CommandeLigne {
+ estExecutable(): boolean
+ executer()
}
class ReculerCurseur extends CommandeLigne {
+ estExecutables(): boolean
+ executer()
}
}
CommandeLigne o-left-> "1\nligne" Ligne
}
note bottom of AvancerCurseur
estExecutable(): boolean:
return ligne.getCurseur() < ligne.getLongueur()
executer():
ligne.avancer()
end note
note bottom of ReculerCurseur
estExecutable(): boolean:
return ligne.getCurseur() > 1
executer():
ligne.reculer()
end note
note as noteEditeur
editer():
do:
ligne.afficher()
menuPrincipal.afficher()
menuPrincipal.sélectionner()
menuPrincipal.valider()
while (! estQuitté())
Editeur(l: Ligne):
this.ligne = l
this.menuPrincipal = new Menu()
this.menuPrincipal.ajouter(
"Avancer curseur",
new AvancerCurseur(l))
this.menuPrincipal.ajouter(
"Reculer curseur",
new ReculerCurseur(l))
end note
Editeur .left. noteEditeur
@enduml
' vim: sw=4 ts=4:

BIN
TP10/editeur-menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

View file

@ -0,0 +1,56 @@
package editeur;
import editeur.commande.*;
import menu.Menu;
/** Un éditeur pour une ligne de texte. Les commandes de
* l'éditeur sont accessibles par un menu.
*
* @author Xavier Crégut
* @version 1.6
*/
public class EditeurLigne {
/** La ligne de notre éditeur */
private Ligne ligne;
/** Le menu principal de l'éditeur */
private Menu menuPrincipal;
// Remarque : Tous les éditeurs ont le même menu mais on
// ne peut pas en faire un attribut de classe car chaque
// commande doit manipuler la ligne propre à un éditeur !
/** Initialiser l'éditeur à partir de la lign à éditer. */
public EditeurLigne(Ligne l) {
ligne = l;
// Créer le menu principal
menuPrincipal = new Menu("Menu principal");
menuPrincipal.ajouter("Ajouter un texte en fin de ligne",
new CommandeAjouterFin(ligne));
menuPrincipal.ajouter("Supprimer le caractère sous le curseur",
new CommandeSupprimer(ligne), "x");
menuPrincipal.ajouter("Sous-Menu Curseur",
new SousMenuCurseur(ligne));
}
public void editer() {
do {
// Afficher la ligne
System.out.println();
ligne.afficher();
System.out.println();
// Afficher le menu
menuPrincipal.afficher();
// Sélectionner une entrée dans le menu
menuPrincipal.selectionner();
// Valider l'entrée sélectionnée
menuPrincipal.valider();
} while (! menuPrincipal.estQuitte());
}
}

View file

@ -0,0 +1,18 @@
package editeur;
/** Programme de test de EditeurLigne.
*
* @author Xavier Crégut
* @version 1.1
*/
public class EditeurLigneMain {
public static void main(String[] args) {
// Ligne uneLigne = new LigneTab(10);
Ligne uneLigne = new LigneStringBuffer();
EditeurLigne editeur = new EditeurLigne(uneLigne);
editeur.editer();
}
}

126
TP10/editeur/Ligne.java Normal file
View file

@ -0,0 +1,126 @@
package editeur;
/** Spécification d'une ligne de texte.
* @author Xavier Crégut (cregut@enseeiht.fr)
* @version 1.5
*/
public interface Ligne {
//@ public invariant 0 <= getLongueur(); // La longueur est positive
//@
//@ // Le curseur est toujours sur un caractère sauf si la ligne est vide.
//@ public invariant 0 <= getCurseur() && getCurseur() <= getLongueur();
//@ public invariant getCurseur() == 0 <==> getLongueur() == 0;
/** nombre de caractères dans la ligne */
/*@ pure @*/ int getLongueur();
/** Position du curseur sur la ligne */
/*@ pure @*/ int getCurseur();
/** le ième caractère de la ligne
* @param i l'indice du caractère
* @return le ième caractère de la ligne
*/
//@ requires 1 <= i && i <= getLongueur(); // indice valide
/*@ pure @*/ char ieme(int i);
/** Le caractère sous le curseur
*/
//@ requires getLongueur() > 0; // la ligne est non vide
/*@ pure @*/ char getCourant();
/** Avancer le curseur d'une position à droite. */
//@ requires getCurseur() < getLongueur(); // pas à la fin
//@ ensures getCurseur() == \old(getCurseur()) + 1; // curseur avancé
void avancer();
/** Avancer le curseur d'une position à gauche. */
//@ requires getCurseur() > 1; // pas en début de ligne
//@ ensures getCurseur() == \old(getCurseur()) - 1; // curseur reculé
void reculer();
/** Placer le curseur sur le premier caractère. */
//@ requires getLongueur() > 0; // ligne non vide
//@ ensures getCurseur() == 1; // curseur sur la première position
void raz();
/** Remplacer le caractère sous le curseur par le caractère c. */
//@ requires getLongueur() > 0;
//@ ensures getCourant() == c;
void remplacer(char c);
/** Supprimer le caractère sous le curseur. La position du curseur reste
* inchangée.
*/
//@ requires getLongueur() > 0;
//@ ensures getLongueur() == \old(getLongueur()) - 1; // un caractère ôté
//@ ensures getCurseur() == Math.min(\old(getCurseur()), getLongueur());
void supprimer();
/** Ajouter le caractère c avant le curseur.
* Le curseur reste sur le même caractère.
*/
//@ requires getLongueur() > 0; // curseur positionné
//@
//@ ensures getLongueur() == \old(getLongueur()) + 1; // un caractère ajouté
//@ ensures getCurseur() == \old(getCurseur()) + 1; // curseur inchangé
//@ ensures getCourant() == \old(getCourant());
void ajouterAvant(char c);
/** Ajouter le caractère c après le curseur.
* Le curseur reste sur le même caractère.
*/
//@ requires getLongueur() > 0; // curseur positionné
//@ ensures getLongueur() == \old(getLongueur()) + 1; // caractère ajouté
//@ ensures getCurseur() == \old(getCurseur()); // curseur inchangé
//@ ensures getCourant() == \old(getCourant());
void ajouterApres(char c);
/** Afficher la ligne en mettant entre crochets [] le caractère courant.
* Si la ligne est vide, un seul caractère tilde(~) est affiché.
*/
/*@ pure @*/ void afficher();
/** Ajouter le caractère c à la fin de la ligne.
* Le curseur reste sur le même caractère.
*/
//@ ensures getLongueur() == \old(getLongueur()) + 1; // caractère ajouté
//@ ensures ieme(getLongueur()) == c; // à la fin
//@ ensures (\forall int i; 1 <= i && i <= \old(getLongueur());
//@ ieme(i) == \old(ieme(i)));
//@ ensures getLongueur() > 1 ==> getCourant() == \old(getCourant());
//@ ensures getCurseur() == Math.max(1, \old(getCurseur()));
void ajouterFin(char c);
/** Ajouter le caractère c au début de la ligne
* Le curseur reste sur le même caractère.
*/
//@ ensures getLongueur() == \old(getLongueur()) + 1; // caractère ajouté
//@ ensures ieme(1) == c; // en première position
//@ ensures (\forall int j; j >= 2 && j <= getLongueur();
//@ ieme((int)j) == \old(ieme((int)(j-1))));
//@ ensures getLongueur() > 1 ==> getCourant() == \old(getCourant());
//@ ensures getCurseur() == \old(getCurseur()) + 1;
void ajouterDebut(char c);
/** supprimer le premier caractère de la ligne. Le curseur reste sur le
* même caractère.
*/
//@ requires getLongueur() > 0;
//@ ensures getLongueur() == \old(getLongueur()) - 1;
//@ ensures \old(getCurseur()) != 1 ==> getCourant() == \old(getCourant());
//@ ensures getCurseur()
//@ == Math.min(Math.max((int)(\old(getCurseur())-1), 1), getLongueur());
void supprimerPremier();
/** supprimer le dernier caractère de la ligne. Le curseur reste sur le même
* caractère.
*/
//@ requires getLongueur() > 0;
//@ ensures getLongueur() == \old(getLongueur()) - 1;
//@ ensures \old(getCurseur()) < \old(getLongueur())
//@ ==> getCourant() == \old(getCourant());
//@ ensures getCurseur() == Math.min(\old(getCurseur()), getLongueur());
void supprimerDernier();
}

View file

@ -0,0 +1,131 @@
package editeur;
/** Une ligne de texte représentée par un StringBuffer.
* @author Xavier Crégut (cregut@enseeiht.fr)
* @version 1.4
*/
public class LigneStringBuffer implements Ligne {
//@ private invariant this.curseur == this.getCurseur();
//@ private invariant this.getLongueur() == this.caracteres.length();
//@ private invariant (\forall int i; i >= 1 && i <= this.getLongueur();
//@ this.ieme(i) == this.caracteres.charAt(i-1));
//@ private invariant caracteres != null;
/** Les caractères de la ligne. */
private StringBuffer caracteres;
/** La position du curseur. */
private int curseur;
/** Créer une ligne vide.
*/
//@ ensures getLongueur() == 0; // la ligne est vide
public LigneStringBuffer() {
caracteres = new StringBuffer();
curseur = 0;
}
public int getLongueur() {
return caracteres.length();
}
public int getCurseur() {
return curseur;
}
public char ieme(int i) {
return caracteres.charAt(i-1);
}
public char getCourant() {
return ieme(curseur);
}
public void avancer() {
curseur++;
}
public void reculer() {
curseur--;
}
public void raz() {
curseur = 1;
}
public void remplacer(char c) {
caracteres.setCharAt(curseur-1, c);
}
public void supprimer() {
// Supprimer le caractère
caracteres.deleteCharAt(curseur-1);
// Mettre à jour le curseur
if (curseur > caracteres.length()) {
curseur = caracteres.length();
}
}
public void ajouterAvant(char c) {
caracteres.insert(curseur-1, c);
curseur++;
}
public void ajouterApres(char c) {
caracteres.insert(curseur, c);
}
public void afficher() {
if (caracteres.length() == 0) { // La chaîne est vide
System.out.print("~");
} else {
// Afficher les caractères avant le curseur
System.out.print(caracteres.substring(0, curseur-1));
// Afficher le caractère sous le curseur
System.out.print("" + '[' + ieme(curseur) + ']');
// Afficher les caractères après le curseur
System.out.print(caracteres.substring(curseur));
}
System.out.println();
}
public String toString() {
return "caractères = \"" + caracteres + '"'
+ " et curseur = " + curseur;
}
public void ajouterFin(char c) {
caracteres.append(c);
if (curseur == 0) {
curseur = 1;
}
}
public void ajouterDebut(char c) {
caracteres.insert(0, c); // Ajouter le caractère
curseur++; // Rétablir le curseur
}
public void supprimerPremier() {
caracteres.deleteCharAt(0);
// Mettre à jour le curseur
if (caracteres.length() == 0) {
curseur = 0;
} else if (curseur > 1) {
curseur--;
}
}
public void supprimerDernier() {
caracteres.deleteCharAt(caracteres.length() - 1);
if (curseur > caracteres.length()) {
curseur--;
}
}
}

View file

@ -0,0 +1,34 @@
package editeur.commande;
import editeur.Ligne;
import util.Console;
/** Ajouter un caractère à la fin de la ligne.
* @author Xavier Crégut
* @version 1.4
*/
public class CommandeAjouterFin
extends CommandeLigne
{
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeAjouterFin(Ligne l) {
super(l);
}
public void executer() {
String texte = Console.readLine("Texte à insérer : ");
for (int i = 0; i < texte.length(); i++) {
ligne.ajouterFin(texte.charAt(i));
}
}
public boolean estExecutable() {
return true;
}
}

View file

@ -0,0 +1,30 @@
package editeur.commande;
import editeur.Ligne;
/** Avancer le curseur d'une position.
* @author Xavier Crégut
* @version 1.4
*/
public class CommandeCurseurAvancer
extends CommandeLigne
{
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeCurseurAvancer(Ligne l) {
super(l);
}
public void executer() {
ligne.avancer();
}
public boolean estExecutable() {
return ligne.getCurseur() < ligne.getLongueur();
}
}

View file

@ -0,0 +1,30 @@
package editeur.commande;
import editeur.Ligne;
/** Reculer le curseur d'une position.
* @author Xavier Crégut
* @version 1.4
*/
public class CommandeCurseurReculer
extends CommandeLigne
{
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeCurseurReculer(Ligne l) {
super(l);
}
public void executer() {
ligne.reculer();
}
public boolean estExecutable() {
return ligne.getCurseur() > 1;
}
}

View file

@ -0,0 +1,27 @@
package editeur.commande;
import editeur.Ligne;
import menu.Commande;
/** Une CommandeLigne est une commande qui travaille sur une
* ligne de l'éditeur orienté ligne.
* @author Xavier Crégut
* @version 1.4
*/
abstract public class CommandeLigne
implements Commande
{
/** La ligne manipulée par la commande. */
protected Ligne ligne;
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeLigne(Ligne l) {
ligne = l;
}
}

View file

@ -0,0 +1,20 @@
package editeur.commande;
import editeur.Ligne;
import menu.Menu;
abstract public class CommandeMenu extends CommandeLigne {
/** La ligne manipulée par la commande. */
protected Menu sousMenu;
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeMenu(Ligne l) {
super(l);
}
}

View file

@ -0,0 +1,30 @@
package editeur.commande;
import editeur.Ligne;
/** Ajouter un caractère à la fin de la ligne.
* @author Xavier Crégut
* @version 1.4
*/
public class CommandeRAZ
extends CommandeLigne
{
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeRAZ(Ligne l) {
super(l);
}
public void executer() {
ligne.raz();
}
public boolean estExecutable() {
return true;
}
}

View file

@ -0,0 +1,30 @@
package editeur.commande;
import editeur.Ligne;
/** Ajouter un caractère à la fin de la ligne.
* @author Xavier Crégut
* @version 1.4
*/
public class CommandeSupprimer
extends CommandeLigne
{
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public CommandeSupprimer(Ligne l) {
super(l);
}
public void executer() {
ligne.supprimer();
}
public boolean estExecutable() {
return ligne.getLongueur() > 0;
}
}

View file

@ -0,0 +1,53 @@
package editeur.commande;
import editeur.Ligne;
import menu.Menu;
/** Reculer le curseur d'une position.
* @author Xavier Crégut
* @version 1.4
*/
public class SousMenuCurseur extends CommandeMenu {
Menu sousMenu = new Menu("Sous menu curseur");
/** Initialiser la ligne sur laquelle travaille
* cette commande.
* @param l la ligne
*/
//@ requires l != null; // la ligne doit être définie
public SousMenuCurseur(Ligne l) {
super(l);
this.sousMenu.ajouter("Avancer le curseur d'un caractère",
new CommandeCurseurAvancer(ligne));
this.sousMenu.ajouter("Reculer le curseur d'un caractère",
new CommandeCurseurReculer(ligne));
this.sousMenu.ajouter("Ramener le curseur au premier caractère",
new CommandeRAZ(ligne));
}
public void executer() {
do {
// Afficher la ligne
System.out.println();
ligne.afficher();
System.out.println();
// Afficher le menu
sousMenu.afficher();
// Sélectionner une entrée dans le menu
sousMenu.selectionner();
// Valider l'entrée sélectionnée
sousMenu.valider();
} while (! sousMenu.estQuitte());
}
public boolean estExecutable() {
return true;
}
}

18
TP10/menu/Commande.java Normal file
View file

@ -0,0 +1,18 @@
package menu;
/** Définition d'une commande générale.
* @author Xavier Crégut
* @version 1.4
*/
public interface Commande {
/** Exécuter la commande. */
//@requires estExecutable();
void executer();
/** La commande est-elle exécutable ?
* @return la commande est-elle exécutable ?
*/
/*@ pure @*/ boolean estExecutable();
}

81
TP10/menu/Entree.java Normal file
View file

@ -0,0 +1,81 @@
package menu;
// À NOTER : La classe n'est pas déclarée « public » car elle n'a
// pas à être utilisée à l'extérieur du paquetage. Plus
// précisément, elle n'est utilisée que par la classe Menu. À ce
// titre, il aurait été possible d'en faire une classe interne à
// la classe Menu. Elle aurait alors été déclarée << static >>.
/** Définition d'une entrée de Menu.
* @author Xavier Crégut
* @version 1.6
*/
class Entree {
/** L'intitulé de l'entrée. */
private String intitule;
/** La commande associée à l'entrée. */
private Commande commande;
public String shortcut;
/** Construire une entrée à partir d'un intitulé et d'une commande.
* @param unIntitule l'intitulé de l'entrée
* @param uneCommande l'intitulé de la commande
*/
//@ requires uneCommande != null; // la commande existe
//@ requires unIntitule != null && unIntitule.length() > 0;
//@ // l'intitulé existe
//@ ensures getIntitule() == unIntitule;
//@ ensures getCommande() == uneCommande;
public Entree(String unIntitule, Commande uneCommande) {
intitule = unIntitule;
commande = uneCommande;
}
public Entree(String unIntitule, Commande uneCommande, String shortcut) {
intitule = unIntitule;
commande = uneCommande;
this.shortcut = shortcut;
}
/** L'intitulé de l'entrée. */
public /*@ pure @*/ String getIntitule() {
return intitule;
}
/** La commande associée à l'entrée. */
public /*@ pure @*/ Commande getCommande() {
return commande;
}
/** Afficher l'entrée.
* @param numero le numéro de l'entrée dans le menu
*/
public /*@ pure @*/ void afficher(int numero) {
if (commande.estExecutable()) {
String num = "" + numero;
if (num.length() < 2) {
System.out.print(" ");
}
System.out.print(num);
} else {
System.out.print(" -");
}
System.out.print(") ");
System.out.print(getIntitule());
if (this.shortcut != null) {
int space = 46 - getIntitule().length() - shortcut.length();
for (int i = 0; i < space; i++) {
System.out.print(' ');
}
System.out.format("[%s]", shortcut);
}
System.out.println();
}
}

165
TP10/menu/Menu.java Normal file
View file

@ -0,0 +1,165 @@
package menu;
import java.util.*;
import util.Console;
import menu.commande.*;
/** Définition de menus textuels avec les entrées non
* sélectionnables désactivées.
* @author Xavier Crégut (cregut@enseeiht.fr)
* @version 1.9
*/
public class Menu {
//@ public invariant 0 <= getNbEntrees();
//@ private invariant titre != null;
//@ private invariant selection != CMD_QUITTER && selection != null ==>
//@ (\exists int i; i >= 0 && i <= getNbEntrees();
//@ selection == getEntree(i).getCommande());
//@ private invariant estQuitte() ==> selection == CMD_QUITTER;
//@ private invariant getNbEntrees() == entrees.size();
//@ private invariant entreeQuitter != null;
private String titre; // Le titre
private List<Entree> entrees; // Les entrées du menu
static final private Commande CMD_QUITTER = new CommandeNOP();
static final private Entree entreeQuitter = new Entree("Quitter", CMD_QUITTER);
private Commande selection; // Commande sélectionnée
private boolean estQuitte; // le menu a-t-il été quitté ?
/** Construire un menu vide (sans entrées).
* @param sonTitre le titre du menu
*/
//@ requires sonTitre != null; // le titre existe
//@ ensures getNbEntrees() == 0; // le menu est vide
//@ ensures estQuitte() == false; // pas encore quitter !
public Menu(String sonTitre) {
this.entrees = new ArrayList<Entree>();
this.titre = sonTitre;
this.selection = null;
this.estQuitte = false;
}
/** le nombre d'entrées du menu. */
public /*@ pure @*/ int getNbEntrees() {
return this.entrees.size();
}
/** Obtenir une entrée du menu.
* @param i position de l'entrée
* @retrun l'entrée correspondant à i
*/
//@ requires 0 <= i && i <= getNbEntrees();
private /*@ pure @*/ Entree getEntree(int i) {
if (i > 0) {
return this.entrees.get(i-1);
} else {
return entreeQuitter;
}
}
public /*@ pure @*/ boolean estQuitte() {
return this.estQuitte;
}
/** Ajouter une entrée dans le menu.
* @param texte l'intitulé dans le menu
* @param cmd la commande associée
*/
//@ requires texte != null && texte.length() > 0; // texte défini
//@ requires cmd != null; // commande définie
public void ajouter(String texte, Commande cmd) {
this.entrees.add(new Entree(texte, cmd));
}
public void ajouter(String texte, Commande cmd, String shortcut) {
this.entrees.add(new Entree(texte, cmd, shortcut));
}
/** Tracer une séparation du menu. */
private static void tracerSeparation() {
String separation =
"----------------------------------------------------";
System.out.println(separation);
}
/** Afficher le menu. Les numéros des commandes non
* exécutables ne sont pas affichés.
*/
public /*@ pure @*/ void afficher() {
// Afficher le titre du menu
tracerSeparation();
System.out.println(titre);
tracerSeparation();
// Afficher les entrées de l'utilisateur
for (int i = 1; i <= this.getNbEntrees(); i++) {
this.getEntree(i).afficher(i);
}
// Afficher la possibilité de quitter
this.getEntree(0).afficher(0);
// Dessiner la fin du menu
tracerSeparation();
}
/** Saisir le choix de l'utilisateur. Le choix correspond à
* une entrée du menu (y compris 0 pour quitter).
* L'utilisateur peut sélectionner une entrée dont la
* commande associée n'est pas exécutable.
*/
//@ ensures ! estQuitte();
public void selectionner() {
// Choisir une entrée
this.estQuitte = false;
String choix;
boolean choix_valide = false;
do {
System.out.print("Votre choix: ");
choix = Console.readString();
try {
int choix_entier = Integer.parseInt(choix);
choix_valide = 0 <= choix_entier && choix_entier <= this.getNbEntrees();
if (!choix_valide) {
System.out.println("Le numéro doit être compris entre "
+ 0 + " et "
+ this.getNbEntrees() + " !");
} else {
this.selection = this.getEntree(choix_entier).getCommande();
}
} catch (java.lang.NumberFormatException e) {
for (Entree entry : entrees) {
if (entry.shortcut != null && entry.shortcut.equals(choix)) {
choix_valide = true;
this.selection = entry.getCommande();
break;
}
}
}
} while (!choix_valide);
}
/** Valider la sélection. Ceci consiste à exécuter la
* commande associée à l'entrée sélectionnée. Si l'entrée
* sélectionnée est non exécutable, un message d'erreur est
* signalé.
*/
public void valider() {
if (this.selection == CMD_QUITTER) {
this.estQuitte = true;
} else {
if (this.selection.estExecutable ()) {
this.selection.executer();
} else {
System.out.println("Opération non réalisable !");
}
}
}
}

View file

@ -0,0 +1,18 @@
package menu.commande;
import menu.Commande;
/** Commande... qui ne fait rien !
* @author Xavier Crégut
* @version $Revision: 1.1 $
*/
final public class CommandeNOP implements Commande {
public void executer() {
}
public boolean estExecutable() {
return true;
}
}

Binary file not shown.

141
TP10/util/Console.java Normal file
View file

@ -0,0 +1,141 @@
package util;
import java.io.*;
/** Quelques méthodes pour lire des entiers et des réels.
* @author Xavier Crégut (très largement inspiré par Cay Horstmann)
* @version $Revision: 1.2 $
*/
public class Console
{
/** Afficher un prompt à l'écran (sans passage à la ligne)
* @param prompt texte à afficher à l'écran
*/
public static void printPrompt(String prompt) {
System.out.print(prompt + " ");
System.out.flush(); // forcer l'écriture en l'absence de '\n'
}
/** Lire une chaîne de caractères à partir du clavier. La chaîne de
* caractères est terminée par un retour à la ligne (qui ne fait pas partie
* du résultat). (cf corejava)
*
* @return la ligne lue à partir du clavier (sans le retour à la ligne)
*/
public static String readLine() {
int ch;
String r = "";
boolean done = false;
while (!done) {
try {
ch = System.in.read();
if (ch < 0 || (char) ch == '\n') {
done = true;
} else if ((char) ch != '\r') {
// weird--it used to do \r\n translation
r = r + (char) ch;
}
} catch (java.io.IOException e) {
done = true;
}
}
return r;
}
public static String readString() {
return readLine();
}
/** Même méthode que readLine avec en plus l'affichage d'une invite.
* @param invite texte à afficher à l'écran
* @return la ligne lue à partir du clavier (sans le retour à la ligne)
*/
public static String readLine(String invite) {
printPrompt(invite);
return readLine();
}
/** Lire un caractère après avoir affiché une invite. Tous les caractères
* suivants, jusqu'au retour à la ligne sont considérés consommés.
* @param invite texte à afficher à l'écran
* @return le caractère lu au clavier.
*/
public static char readChar(String invite) {
printPrompt(invite);
String line = readLine();
return line.length() > 0 ? line.charAt(0) : '\n';
}
public static char readChar() {
return readChar("");
}
/** Lire un entier à partir du clavier après avoir affiché une invite.
* Resaisie dans le cas d'une erreur de l'utilisateur.
* @return l'entier lu
*/
public static int readInt(String invite) {
int resultat = 0;
boolean saisieOK = false;
while(! saisieOK) {
printPrompt(invite);
try {
String s = readLine().trim();
resultat = Integer.parseInt(s);
saisieOK = true;
} catch (NumberFormatException e) {
System.out.println ("Ce n'est pas un entier. Recommencez !");
}
}
return resultat;
}
public static int readInt() {
return readInt("");
}
/** Lire un réel à partir du clavier après avoir affiché une invite.
* Resaisie dans le cas d'une erreur de l'utilisateur.
* @return le réel lu
*/
public static double readDouble(String invite) {
double resultat = 0;
boolean saisieOK = false;
while(! saisieOK) {
printPrompt(invite);
try {
String s = readLine().trim();
resultat = Double.parseDouble(s);
saisieOK = true;
} catch (NumberFormatException e) {
System.out.println ("Ce n'est pas un réel. Recommencez !");
}
}
return resultat;
}
public static double readDouble() {
return readDouble("");
}
/** Lire un entier à partir du << flot >> d'entrée après avoir affiché une invite.
* Resaisie dans le cas d'une erreur de l'utilisateur.
* @return l'entier lu
*/
public static int readInt(BufferedReader in, String invite) throws IOException {
int resultat = 0;
boolean saisieOK = false;
while(! saisieOK) {
printPrompt(invite);
try {
String s = in.readLine().trim();
resultat = Integer.parseInt(s);
saisieOK = true;
} catch (NumberFormatException e) {
System.out.println ("Ce n'est pas un entier. Recommencez !");
}
}
return resultat;
}
}

View file

@ -0,0 +1,9 @@
/** Un joueur essaie de jouer dans une case occupée.
* @author Xavier Crégut
* @version $Revision: 1.1 $
*/
public class CaseOccupeeException extends Exception {
public CaseOccupeeException(String message) {
super(message);
}
}

44
TP12/ModeleMorpion.java Normal file
View file

@ -0,0 +1,44 @@
/** Définition du « modèle » du jeu du Morpion.
* @author Xavier Crégut
* @version $Revision: 1.2 $
*/
public interface ModeleMorpion {
// Modéliser (coder !) le contenu d'une case
enum Etat { VIDE, CROIX, ROND };
int TAILLE = 3; // taille du jeu de Morpion
// Définition des événements qui vont influencer le modèle.
/** Quitter le jeu. */
void quitter();
/** Recommencer une nouvelle partie.*/
void recommencer();
/** Cocher la case (x,y). */
//@ requires x >= 0 && x < TAILLE;
//@ requires y >= 0 && y < TAILLE;
void cocher(int x, int y) throws CaseOccupeeException;
// Requêtes sur le modèle
/** Est-ce que la partie est terminée ? */
boolean estTerminee();
/** Est-ce qu'il y a un gagnant ? */
boolean estGagnee();
/** Obtenir le joueur dont c'est le tour de jouer. */
Etat getJoueur();
/** Obtenir le contenu d'une case.
* @param x colonne de la case
* @param y ligne de la case
*/
//@ requires x >= 0 && x < TAILLE;
//@ requires y >= 0 && y < TAILLE;
Etat getValeur(int x, int y);
}

View file

@ -0,0 +1,139 @@
/**
* ModeleMorpionSimple est une réalisation de l'interface ModeleMorpion en
* utilisant un damier (tableau 3 par 3) pour stocker les symboles...
*
* @author Xavier Crégut
* @version $Revision: 1.2 $
*/
public class ModeleMorpionSimple implements ModeleMorpion {
/** La zone de jeu */
private Etat[][] cases;
/** Le joueur dont c'est le tour de jouer */
private Etat joueur;
/** Le nombres de cases cochées */
private int nbCoups;
/** Est-ce que la partie est gagnée ? */
private boolean gagnee;
public ModeleMorpionSimple() {
// Créer le damier
this.cases = new Etat[ModeleMorpion.TAILLE][ModeleMorpion.TAILLE];
// Commencer une partie
initialiser();
}
/** Est-ce que la partie est terminée ? */
public boolean estTerminee() {
return estGagnee()
|| this.nbCoups >= ModeleMorpion.TAILLE * ModeleMorpion.TAILLE;
}
/** Est-ce qu'il y a un gagnant ? */
public boolean estGagnee() {
return gagnee;
}
/** Est-ce que la case (i,j) est vide ? */
private boolean estVide(int i, int j) {
return getValeur(i,j) == Etat.VIDE;
}
public Etat getValeur(int x, int y) {
return this.cases[x][y];
}
/** Initialiser le jeu pour faire une nouvelle partie */
private void initialiser() {
// Initialiser les cases
for (int i = 0; i < this.cases.length; i++) {
for (int j = 0; j < this.cases[i].length; j++) {
this.cases[i][j] = Etat.VIDE;
}
}
// Initialiser le nb de coups
this.nbCoups = 0;
// Initialiser gagnée
gagnee = false;
// Initialiser le joueur
this.joueur = Etat.CROIX;
}
public Etat getJoueur() {
return this.joueur;
}
/** Changer de joueur */
private void changer() {
if (this.joueur == Etat.CROIX) {
this.joueur = Etat.ROND;
} else {
this.joueur = Etat.CROIX;
}
}
/** Jouer en (i,j) pour le joueur */
//@ requires estVide(i,j);
//@ ensures getValeur(i,j) == joueur;
private void jouer(int i, int j) {
this.cases[i][j] = this.joueur;
this.nbCoups++;
// Mettre à jour gagnee
// XXX: Ceci ne marche que pour un Morpion de taille 3 !
gagnee = gagnee ||
((cases[i][0] == cases[i][1] // ligne pleine
&& cases[i][1] == cases[i][2])
|| (cases[0][j] == cases[1][j] // colonne pleine
&& cases[1][j] == cases[2][j])
|| (i == j // première diagonale pleine
&& cases[0][0] == cases[1][1]
&& cases[1][1] == cases[2][2])
|| (i + j == 2 // deuxième diagonale pleine
&& cases[0][2] == cases[1][1]
&& cases[1][1] == cases[2][0]));
}
/////// « Événements » de haut niveau déclenchées par l'utilisateur ////////////
// Remarque : dans cette partie j'ai laissé le paramètre implicite this car
// il me semble qu'il faudrait mettre tout ceci dans une classe spécifique,
// par exemple LogiqueMorpion. Dans ce cas, this serait remplacé par
// getModele() ou getMorpion().
public void quitter() {
}
public void recommencer() {
this.initialiser();
}
public void cocher(int x, int y) throws CaseOccupeeException {
if (!this.estTerminee()) { // La partie est en cours
if (this.estVide(x, y)) {
// Jouer la case
this.jouer(x, y);
// Passer à la suite
if (! this.estTerminee()) {
// Faire jouer l'autre joueur
this.changer();
}
} else {
throw new CaseOccupeeException("Impossible, la case est occupée !");
}
}
}
}

170
TP12/MorpionSwing.java Normal file
View file

@ -0,0 +1,170 @@
import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.util.*;
/** Programmation d'un jeu de Morpion avec une interface graphique Swing.
*
* REMARQUE : Dans cette solution, le patron MVC n'a pas été appliqué !
* On a un modèle (?), une vue et un contrôleur qui sont fortement liés.
*
* @author Xavier Crégut
* @version $Revision: 1.4 $
*/
public class MorpionSwing {
// les images à utiliser en fonction de l'état du jeu.
private static final Map<ModeleMorpion.Etat, ImageIcon> images
= new HashMap<ModeleMorpion.Etat, ImageIcon>();
static {
images.put(ModeleMorpion.Etat.VIDE, new ImageIcon("blanc.jpg"));
images.put(ModeleMorpion.Etat.CROIX, new ImageIcon("croix.jpg"));
images.put(ModeleMorpion.Etat.ROND, new ImageIcon("rond.jpg"));
}
// Choix de réalisation :
// ----------------------
//
// Les attributs correspondant à la structure fixe de l'IHM sont définis
// « final static » pour montrer que leur valeur ne pourra pas changer au
// cours de l'exécution. Ils sont donc initialisés sans attendre
// l'exécution du constructeur !
private ModeleMorpion modele; // le modèle du jeu de Morpion
// Les éléments de la vue (IHM)
// ----------------------------
/** Fenêtre principale */
private JFrame fenetre;
/** Bouton pour quitter */
private final JButton boutonQuitter = new JButton("Q");
/** Bouton pour commencer une nouvelle partie */
private final JButton boutonNouvellePartie = new JButton("N");
/** Cases du jeu */
private final JLabel[][] cases = new JLabel[3][3];
/** Zone qui indique le joueur qui doit jouer */
private final JLabel joueur = new JLabel();
// Le constructeur
// ---------------
/** Construire le jeu de morpion */
public MorpionSwing() {
this(new ModeleMorpionSimple());
}
/** Construire le jeu de morpion */
public MorpionSwing(ModeleMorpion modele) {
// Initialiser le modèle
this.modele = modele;
// Créer les cases du Morpion
for (int i = 0; i < this.cases.length; i++) {
for (int j = 0; j < this.cases[i].length; j++) {
this.cases[i][j] = new JLabel();
}
}
// Initialiser le jeu
this.recommencer();
// Construire la vue (présentation)
// Définir la fenêtre principale
this.fenetre = new JFrame("Morpion");
this.fenetre.setLocation(100, 200);
// Construire le contrôleur (gestion des événements)
this.fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Création du contenu
Container contenu = fenetre.getContentPane();
contenu.setLayout(new BorderLayout());
// Ajout de la bar
JMenuBar bar = new JMenuBar();
this.fenetre.setJMenuBar(bar);
// Ajout d'un menu dans la bar
JMenu menu = new JMenu("Jeu");
bar.add(menu);
// Ajout d'items dans le menu
JMenuItem newGame = new JMenuItem("Nouvelle Partie");
menu.add(newGame);
JMenuItem quitter = new JMenuItem("Quitter");
menu.add(quitter);
// Définir le Panel de la grille
JPanel boutons_grid = new JPanel(new GridLayout(3, 3));
contenu.add(boutons_grid, BorderLayout.NORTH);
// Ajout de la grille
for (int i = 0; i < 9; i++) {
JButton b = new JButton("", new ImageIcon("blanc.jpg"));
b.setBorder(BorderFactory.createEmptyBorder());
b.setContentAreaFilled(false);
boutons_grid.add(b);
}
// Définir le Panel des actions
JPanel boutons_actions = new JPanel(new GridLayout(1, 3));
contenu.add(boutons_actions, BorderLayout.SOUTH);
// Ajout des Buttons Next, Current et Quit
JButton next = new JButton("N");
boutons_actions.add(next);
JButton current = new JButton("", new ImageIcon("rond.jpg"));
current.setBorder(BorderFactory.createEmptyBorder());
current.setContentAreaFilled(false);
boutons_actions.add(current);
JButton quit = new JButton("Q");
boutons_actions.add(quit);
// afficher la fenêtre
this.fenetre.pack(); // redimmensionner la fenêtre
this.fenetre.setVisible(true); // l'afficher
}
// Quelques réactions aux interactions de l'utilisateur
// ----------------------------------------------------
/** Recommencer une nouvelle partie. */
public void recommencer() {
this.modele.recommencer();
// Vider les cases
for (int i = 0; i < this.cases.length; i++) {
for (int j = 0; j < this.cases[i].length; j++) {
this.cases[i][j].setIcon(images.get(this.modele.getValeur(i, j)));
}
}
// Mettre à jour le joueur
joueur.setIcon(images.get(modele.getJoueur()));
}
// La méthode principale
// ---------------------
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new MorpionSwing();
}
});
}
}

BIN
TP12/blanc.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
TP12/croix.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
TP12/rond.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Some files were not shown because too many files have changed in this diff Show more