Dessiner avec StdDraw¶
Introduction¶
La classe StdDraw définit un ensemble de méthodes permettant à nos programmes Java de produire des sorties graphiques en 2D. Il s’agit d’une couche d’abstraction simple à Java Swing, à usage pédagogique. Elle a été conçue par Robert Sedgewick et Kevin Wayne.
Les méthodes de l’interface de StdDraw peuvent être classées en deux catégories :
les instructions de dessin comme tracer une ligne ou tracer un rectangle,
les instructions de contrôle comme sélectionner la couleur du stylo ou ajuster les échelles de la fenêtre.
La documentation de référence est accessible ici, mais les principales méthodes en sont présentées ci-dessous.
Méthodes de base¶
Pour le dessin¶
public static void line(double x0, double y0, double x1, double y1) // trace un segment
public static void point(double x, double y)
public static void circle(double x, double y, double r)
public static void rectangle(double x, double y, double halfWidth, double halfHeight) // attention aux paramètres
Note
Par défaut,
la fenêtre graphique représente le carré de diagonale (0,0)-(1,1),
le stylo est de couleur noire,
le fond est de couleur blanche.
Pour le contrôle¶
public static void setXscale(double min, double max) // fixe l'amplitude des abscisses dans la fenêtre
public static void setYscale(double min, double max) // fixe l'amplitude des ordonnées dans la fenêtre
public static void setPenRadius(double r) // fixe l'épaisseur du trait
public static void setPenColor(Color color)
public static void show(int t) // raffraichit le dessin
Pour l’écriture¶
public static void text(double x, double y, String s)
public static void setFont(Font f)
Pour l’interaction¶
public static boolean mousePressed() // indique si un des boutons de souris est enfoncé
public static double mouseX() // abscisse du pointeur de souris
public static double mouseY() // ordonnée du pointeur de souris
Exemple d’utilisation¶
Programme Triangle (télécharger le fichier Triangle.java)
public class Triangle {
public static void main(String[] args) {
double t = Math.sqrt(3.0) / 2.0;
StdDraw.line(0.0, 0.0, 1.0, 0.0);
StdDraw.line(1.0, 0.0, 0.5, t);
StdDraw.line(0.5, t, 0.0, 0.0);
StdDraw.point(0.5, t/3.0);
StdDraw.text(0.5, 0.5, "Un joli triangle");
}
}
Compilation / exécution (télécharger le fichier StdDraw.java ici
$ javac StdDraw.java
$ javac Triangle.java
$ java Triangle
Défi n°1 : damiers¶
À faire
Écrire un programme qui prend en argument un nombre entier N et qui dessine un damier de NxN cases, rouges et noires, comme dans les exemples ci-dessous.
Indication
Penser à calculer judicieusement les échelles en x et en y et à les fixer avec les méthodes setXSCale() et setYScale(). Cela permet ensuite d’exprimer plus facilement et plus clairement les coordonnées des différents éléments à positionner dans la fenêtre.
Aller voir du coté de la méthode filledSquare() pour les cases colorées.
Pour récupérer le premier argument passé au programme sur la ligne de commande et l’affecter à la variable entière n, on peut utiliser l’instruction suivante :
int n = Integer.parseInt(args[0]);
Correction
Défi n°2 : Erdös¶
À faire
Écrire une fonction boolean tireProba(double p) qui simule un tirage aléatoire renvoyant true avec une probabilité p, et false le reste du temps.
Indication
On pourra utiliser la méthode Math.random() pour générer des valeurs aléatoires comprises entre 0 et 1 et dont la distribution est uniforme, puis distinguer deux intervalles non égaux selon la valeur de p.
Par exemple pour avoir 60% de tirages true, on effectue un tirage de distribution uniforme entre 0 et 1, puis on retourne true si la valeur tirée est inférieure à 0.6, false sinon.
Écrire un programme qui prend en ligne de commande un entier N et qui trace N points équidistants, répartis sur un cercle de diamètre 1.
Modifier le programme pour qu’il accepte un second argument sur la ligne de commande, correspondant à une probabilité p (réel entre 0 et 1) afin de tracer, avec la probabillité p, une ligne entre chaque paire de points sur le cercle, comme dans les exemples ci-dessus.
Correction
version sans tableaux
Erdos.javaversion avec des tableaux 1D
ErdosTableaux.java
Défi n°3 : horloge¶
À faire
Écrire un programme qui affiche une horloge animée classique, dont les aiguilles ne changent de position q’à chaque seconde pour la trotteuse, chaque minute pour la grande aiguille et chaque heure pour la petite aiguille.
Modifier le programme pour que les aiguilles semblent en mouvement perpetuel, c’est à dire que par exemple à 8h30, l’aiguille des heures doit se trouver entre le 8 et le 9 et non pas pile sur le 8 comme dans la version précédente.
Indication
On pourra utiliser la méthode StdDraw.show() pour raffraichir l’affichage, suivie de la méthode StdDraw.pause(1000) pour que cette mise à jour s’effectue toutes les secondes (à peu près).
Attention à l’unité d’expression des angles (radians/degrés), ainsi qu’à la position de référence O°.
On peut récupérer les éléments de l’heure à l’aide de la classe Calendar comme ceci
hours = Calendar.getInstance().get(Calendar.HOUR) ; minutes = Calendar.getInstance().get(Calendar.MINUTE) ; seconds = Calendar.getInstance().get(Calendar.SECOND) ;
Correction
version 1 sans fonction + des aiguilles toujours en face des points
Horloge1.javaversion 2 sans fonction + des aiguilles des heures et minutes en mouvement
Horloge2.javaversion avec fonction + aiguilles en mouvement et trotteuse soft
Horloge.java
Défi n°4 : balle rebondissante¶
À faire
Écrire un programme qui simule une balle rebondissante, prisonnière de la fenêtre graphique.
Pour les plus chevronnés :
Intégrer l’effet de la gravité (amortisement).
Indication
Classiquement, on calcule la prochaine position de la balle en ajoutant le vecteur de déplacement unitaire (dx, dy) à la position actuelle (x, y). Ce vecteur unitaire est proportionnel à la vitesse de la balle.
Les rebonds seront supposés parfaitement élastiques et se modélisent alors en inversant une composante du vecteur de déplacement unitaire selon le mur rencontré.
Le vecteur vitesse initial sera aléatoire. La position initiale pourra être le milieu de la fenêtre.
On ne fera pas apparaître la trace qui est conservée sur l’image ci-dessus.
Correction
avec gravité et dissipation d’énergie :
Balle.java
Pour les plus chevronnés¶
Défi n°5 : flocon de Von Koch¶
Le principe de dessin d’une famille de fractales est de remplacer chaque segment de la figure initiale par un motif et de réitérer le processus sur les segments ainsi générés. Dans l’exemple de la fractale de Von Koch, on réalise l’ajout des points C, D et E dans la figure initiale [AB] en considérant que les longueurs des nouveaux segments [AC], [CD], [DE] et [EB] sont toutes égales au tiers de la longueur du segment initial [AB].
À faire
Écrire une fonction permettant de calculer les coordonnées C, D et E, à partir des coordonnées des points A et B.
Avertissement
Cette fonction effectue le calcul quelles que soient les coordonnées des points A et B.
En conséquence, il ne faut faire aucune hypothèse simplificatrice.
Écrire une méthode (récursive) qui dessine la fractale de Von Koch pour deux points de départ et un niveau de récursion donnés.
Correction
Version bourrin
VonKoch.javaVersion tortue logo
Turtle.javaetKoch.java
Défi n°6 : tours de Hanoï¶
Autrefois, à Hanoï, l’empereur a conçu un puzzle de N disques et trois piquets : le “A” (départ), le “B” (échangeur) et le “C” (arrivée). À cause de leur poids important, on ne pouvait pas mettre un disque plus lourd au dessus de disques qui étaient plus petits. Le but du jeu est de transférer tous les disques du piquet “A” au piquet “C”, en ne déplaçant qu’un seul disque à la fois.
À faire
Récupérer
l'archive des classes *PlateauHanoi* et *StdDraw*qui permet de gérer un tracé simpliste du plateau de jeu.Récupérer
le squelette de la clase *Hanoi*qui initialise un plateau de jeu et appelle la méthode hanoi().Écrire la méthode hanoi() (récursive) qui permet la découverte et l’affichage de la solution. Son prototype devra être le suivant :
/* retourne le nombre de mouvements effectués*/ int hanoi(int nbDisques, PlateauHanoi plateau, char source, char destination, char intermediaire)
Indication
Les tours sont nommées respectivement “A”, “B” et “C” de gauche à droite, comme sur la figure.
Pour déplacer un disque il faut appeler a méthode move() de l’objet plateau de la façon suivante :
plateau.move(char tourSource, char tourDestination) ;
Concevoir une classe PlateauHanoi remplaçant celle fournie et comportant a minima
un constructeur prenant un paramètre entier représentant le nombre de disques n.
une méthode move() de caractéristiques identiques à celle présentée à la question précédente.
Correction
La classe Hanoi :
Hanoi.javaLa classe (moche) PlateauHanoi :
PlateauHanoi.java



