LI260: Course de voiture - Laboratoire d`Informatique de Paris 6

Transcription

LI260: Course de voiture - Laboratoire d`Informatique de Paris 6
LI260: Course de voiture
Vincent Guigue
[email protected] - webia.lip6.fr/~guigue
Quelques images pour comprendre le
contexte
 
Une compétition algorithmique:
 
http://www.dtek.chalmers.se/groups/icfpcontest/
Modèle (complexe )
de voiture imposé.
Une course tour par tour
1  Algo -> commande
2  Application sur la
voiture
3  MAJ voiture
Optimiser le nombre de
coups pour faire un tour
Objectifs de ce projet
 
 
 
 
Gérer de nouveaux outils JAVA (fichiers, fenêtre…)
Apprendre à mieux programmer (introduction aux design
pattern)
Coder (!)
Gérer l’interface entre mathématiques et informatique
 
Algorithmique
  Géométrie dans l’espace
  Algorithmes de plus court chemin
  Algorithmes génétiques
Dans le détail:
Organisation générale
1 
1 
2 
3 
Fichiers
Organisation du code: package, interface
Interactions basiques
Géométrie
2 
1 
2 
Point,Vecteur
Modèle physique, inertie, déplacement, franchissement…
1er algorithme: radar + système expert
3 
1 
2 
3 
Architecture de la stratégie
Codage du radar
Système de décision
4 
Algorithmes de plus court chemin
1 
2 
5 
Optimisation automatique des trajectoires
1 
2 
6 
7 
8 
Dijkstra
Codage
Algorithmes génétiques
Plusieurs possibilités pour les utiliser
Interfaces graphiques JAVA: SWING
Moteur de rendu 3D
… En fonction des besoins
Fonctionnement de l’UE
 
 
1h45 TD/Cours le lundi pendant 6 à 9 séances puis TME
3h30 TME le mercredi matin
 
 
 
 
Double encadrement pour avancer plus vite
Possibilité de tutorat pour les personnes qui se sentent
perdues à partir de la semaine 4/5
Contacts par mail [email protected]
Evaluation:
 
CC : 70%
 
 
Partiel (0.25), Rapport et performance de votre code (0.6),
participation (0.15)
Exam : 30%
 
Soutenance orale et modification de code individuel
Les fichiers
Les différents éléments du projet:
Fichier actions:
Simulation
Fichier terrain:
1.0 0.5
1.0 0.0
-0.5 0.3
…
ggggggggg…
ggggrr…
gggggrr…
Score:
1256 coups
Simulateur
externe
Fichiers:
le dialogue entre les composants
 
Besoins:
 
 
 
Lire le fichier de terrain
Ecrire un fichier action
Pour le simulateur externe: lire le fichier action
3 manières de gérer les fichiers
 
 
 
 
 
Lecture/écriture ASCII
Serialization
Externalization
Syntaxes associées, usages
Points forts et faibles des méthodes…
ASCII: écriture dans un fichier
 
Même syntaxe que pour l’écriture dans la console
 
 
 
System.out.println(‘’Coucou’’);
Mais dans un autre stream
Forme classique de codage:
try {
FileOutputStream output = new FileOutputStream(filename);
PrintStream p = new PrintStream(output);
p.print(…); […]
output.close();
} catch (IOException e) {
System.err.println("Can't open file " + filename
+ " for writting... Saving aborted");
}
ASCII: lecture dans un fichier
try {
FileReader fr = new FileReader(new File(filename));
BufferedReader in = new BufferedReader(fr);
String buf = in.readLine();
in.close();
}catch (FileNotFoundException e) {
System.err.println("Unable to find "+ filename);
}
catch (IOException e) {
System.err.println("Can't open file " + filename
+ " for reading... Loading aborted");
} catch (Exception e) {
System.err.println("Invalid Format : " + filename
+ "... Loading aborted");
}
Trucs et usages classiques
 
Pour lire les fichiers, plusieurs fonctions sont disponibles
dans la classe BufferedReader:
 
 
 
 
Dans la pratique, on préfère lire ligne par ligne:
 
 
 
int read(): retourne le caractère lu ou -1 en fin de flux
int read(cbuf, offset, length): lecture d’un ensemble de
caractères
…
String readLine()
On évite ainsi tous les problèmes d’encodage de retour chariot
Gérer (au moins) 2 exceptions différentes pour les
fichiers manquants ou les pbs de lecture
Fonctions complémentaires
 
Comment séparer les différents mots de la ligne?
String buf = in.readLine();
StringTokenizer st = new StringTokenizer(buf, ", ");
while (st.hasMoreTokens()) {
// traitements sur st.next()
}
 
Lire les caractères dans une String:
 
Convertir une chaine vers un entier:
String buf = in.readLine();
for(int i=0; i<buf.length(); i++)
buf.charAt(i);
String buf = …
Integer.parseInt(buf);
 
En cas de pb, envoie: NumberFormatException
Bilan sur les fichiers ASCII
 
 
 
Indispensable, surtout en lecture: on vous donne souvent
des fichiers ASCII
Très utile pour les grands projets impliquant beaucoup de
gens: on comprend ce qu’il y a dans les fichiers et on
gagne du temps
Assez lourds:
 
 
 
 
Un double pèse 4 octets
Un char pèse 1 octet…
Pour coder 1251.66679128, combien faut-il de place avec ce
système?
Pas très précis (les doubles sont tronqués)
Interface Serializable: sauvegarde
 
 
Si un objet implements Serializable, il devient
sauvegardable/chargeable automatiquement…
Exemple avec la classe Vector:
public class Vector implements Serializable{ …
 
Il suffit ensuite d’utiliser la syntaxe suivante:
// sauvegarde
try{
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new Vector(2,2));
fos.close();
}catch (java.io.FileNotFoundException e){
System.out.println(e.toString());
}catch (java.io.IOException e){
System.out.println(e.toString());
}
Interface Serializable: chargement
 
Usage symétrique:
// chargement
try{
FileInputStream fin = new FileInputStream(filename);
ObjectInputStream oos = new ObjectInputStream(fin);
Vector v = (Vector) oos.readObject();
fin.close();
}catch (java.io.FileNotFoundException e){
System.out.println(e.toString());
}catch (java.io.IOException e){
System.out.println(e.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
 
ATTENTION: on charge des Object -> il faut un cast pour
avoir ce que vous voulez
Limites d’usage
 
La sérialization est une opération visant à automatiser la
sauvegarde des attributs d’une instance de classe
 
 
 
Sauvegarde d’un Point (attributs: double x, y)
 
 
 
 
Il peut y avoir des problèmes avec les attributs static
Il faut que les attributs soient sérializable (!)
Tout se passe bien !
Sauvegarde d’une Voiture (position, vitesse, compteur
static de voiture, stratégie de déplacement…)
Il est possible d’éliminer un attribut de la sauvegarde
grace au mot clé transient.
Problème de version très sensible (!)
Limites d’usage (2)
 
Lors de la sauvegarde, la Serialization enregistre le type
exact de l’objet… Le cas suivant pose problème:
Sauvegarde d’un objet
Modification (même très légère) de la classe
Chargement de l’objet précédent:
1. 
2. 
3. 
 
ClassNotFoundException JAVA vous indique qu’il n’est pas capable de charger l’objet
car cet objet est inconnu dans le cadre actuel du projet
Interface Serializable: bilan
 
 
 
Très facile à utiliser
On ne maitrise pas le format de sauvegarde
Difficile à utiliser sur des projets en cours de
développement
Interface Externalizable
 
 
Même usage que Serializable: l’ouverture/fermeture des
flux est automatique…
Maitrise du format de sauvegarde à travers deux fonctions
de lecture/écriture dans les flux:
public class Vector implements Externalizable{
[…]
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
x = in.readDouble();
y = in.readDouble();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeDouble(x);
out.writeDouble(y);
}
Règles de développement
Règles de développement
 
 
Attributs TOUJOURS private (+ accesseurs éventuels)
Code d’une classe < 2 pages en général,
exceptionnellement un peu plus
 
 
 
 
Penser à créer des sous-classe… Nous y reviendrons
régulièrement
Regarder la documentation quand on a un doute:
http://java.sun.com/javase/6/docs/api/
Utiliser les interfaces avant de coder les objets
complexes… cf transparents suivants.
Utiliser les packages pour structurer le projet
Exemple: Circuit
 
Exemple: le circuit
 
 
 
 
Un circuit est une matrice:
Chaque case de la matrice a un type
Quelles sont les interactions entre le circuit
et les autres éléments de la simulation?
Quelles classes créer?
Circuit: le cahier des charges
 
 
 
 
La voiture doit pouvoir interroger le circuit
La voiture doit savoir si elle a le droit de rouler sur une
case ou pas
Le circuit doit pouvoir donner le point de départ, la
direction de départ et le sens de franchissement de la
ligne d’arrivée
Idées importantes:
 
 
 
Séparer les différents concepts (Circuit / Terrain)
Abstraire les objets complexes pour pouvoir proposer
plusieurs implémentations
Outil de base:
 
Une interface = un objet abstrait = un cahier des charges
Proposition d’architecture
CircuitImpl
-Terrain[][] matrice
-Vecteur ptDepart
-Vecteur sensDepart
-Vecteur sensArrivee
+CircuitImpl(Terrain[][], Vecteur,
Vecteur, Vecteur)
Tools
+ static isRunnable(Terrain t): boolean
+ static terrainFromChar(char c): Terrain
+ static colorFromTerrain(Terrain t): int
...
+getTerrain(int i, int j): Terrain
+getTerrain(Point p): Terrain
+getPointDepart(): Vecteur
+getDirectionDepart(): Vecteur
+getDirectionArrivee(): Vecteur
+ getWidth(): int
+ getHeight(): int
+ getArrivees(): ArrayList<Vecteur>
Vecteur
- x: double
- y: double
Création
manipulation
opérateur
... cf semaine prochaine
utilise
Circuit <<INT>>
+getTerrain(int i, int j): Terrain
+getTerrain(Vecteur p): Terrain
+getPointDepart(): Vecteur
+getDirectionDepart(): Vecteur
+getDirectionArrivee(): Vecteur
+ getWidth(): int
+ getHeight(): int
+ getArrivees(): ArrayList<Vecteur>
utilise
Terrain <<ENUM>>
Route, Herbe, Eau, Obstacle,
BandeRouge, BandeBlanche,
StartPoint, EndLine
Proposition d’architecture (2)
 
Dans notre projet, nous manipulerons toujours des
Circuit:
 
 
si l’implémentation change, notre programme ne change
pas
Tous les concepts sont biens séparés des
implémentations: terrain, circuit, aspects géométriques,
outils de manipulation des circuits…
Outils de manipulation des circuits
 
 
 
 
Char -> Terrain (pour la lecture)
Terrain -> RGB (pour la sauvegarde d’image)
Circuit -> Image
Interrogation isRunnable
Comment créer un circuit?
 
Reflexe classique mais mauvais:
 
 
public Circuit(String filename){…} dans Circuit.java
Bon reflexe: nouvelle classe
 
 
Moins de code dans le même fichier, plus facile à lire et à
corriger
Si le format de fichier change… Pas de problème, il suffit de
faire une nouvelle classe
Tools
+ static isRunnable(Terrain t): boolean
+ static terrainFromChar(char c): Terrain
+ static colorFromTerrain(Terrain t): int
CircuitFactory
-filename : String
+CircuitFactory(String filename)
+build() : Circuit
utilise
Circuit <<INT>>
+getTerrain(int i, int j): Terrain
+getTerrain(Point p): Terrain
+getPointDepart(): Vecteur
+getDirectionDepart(): Vecteur
+getDirectionArrivee(): Vecteur
Structuration en package
 
Afin de mieux gérer les gros projets, les fichiers sont
répartis en arborescence: les packages
geometry
circuit
Vecteur
Circuit
CircuitImpl
Terrain
ToolsTerrain
CircuitFactory
CircuitSaver
voiture
Voiture
VoitureImpl
VoitureFactory
Rappels de syntaxe
 
Interface
public interface Circuit {
public Terrain getTerrain(int i, int j);
public Terrain getTerrain(Vecteur v);
…
 
Classe implémentant une interface
public class CircuitImpl implements Circuit {
public Terrain getTerrain(int i, int j) {
…
}
public Terrain getTerrain(Vecteur v) {
…
}
Rappels de syntaxe (2)
 
Enumération (dans le fichier Terrain.java):
public enum Terrain {
Route, Herbe, Eau, Obstacle, BandeRouge, BandeBlanche,
StartPoint, EndLine}
 
Déclaration/usage:
 
 
 
Terrain t = Terrain.Herbe
If( t == Terrain.Route)
…
Rappels de syntaxe (3)
Que signifie public, private?
  Que signifie this?
  Définir les notions de constructeur, accesseur, setteur
 
public class Vector {
private double x,y;
public Vector(double x, double y) {
this.x = x;
this.y = y;
} public double getX() {return x;}
public double getY() {return y;}
Exercice
 
public Vector(Vecteur a, Vecteur b)
Construit le vecteur du point a au point b…
 
 
Donner le code de la fonction
NB: on considère qu’un Point est un vecteur
 
Rappeler l’interprétation géométrique du produit
scalaire
 
Donner la signature et le code de la fonction
calculant le produit scalaire.
Une correction formelle
public Vector(Vecteur a, Vecteur b){
this(b.getX() - a.getX(), b.getY() - a.getY());
}
public double scal(Vector v){
return v.getX()*getX() + v.getY()*getY();
}
A-t-on le droit de se passer des accesseurs?
Pourquoi?
Exercice suivant…
 
Donner le code de la fonction qui permet d’additionner
deux vecteurs.
 
 
 
 
Plusieurs versions sont possibles: on peut retourner void ou
Vecteur… Que choisir?
On peut faire une version static ou pas…
Donner le code du programme principal permettant
d’additionner 2 vecteurs dans les différents cas
Introduction à la classe Math:
Donner le code de la fonction norme()…
Gestion des images
Manipulation des images
 
 
 
Image: classe abstraite
Nous utiliserons la classe BufferedImage
Chargement:
 
 
Savegarde:
 
 
ImageIO.write(im, "png", outputfilename);
Creation:
 
 
BufferedImage im = ImageIO.read(new File(filename))
BufferedImage im = new BufferedImage(ncol,nligne,
BufferedImage.TYPE_INT_ARGB);
Manipulation:
 
im.setRGB(i,j, color)
int color = im.getRGB(i,j);