Table des matières

TD 5 : Cartographie Martienne

Nous allons développer un éditeur de cartes de la surface martienne. Téléchargez la version de base de l’éditeur de cartes . Dans cette séance, vous allez développer les fonctionnalités de chargement et de sauvegarde d’une carte. L’objectif est de fournir différentes implémentations, toutes respectant l’interface GridRepo définit ci-dessous.

public interface GridRepo {
    Grid load(String string);
    String export(Grid grid);
}

Version minimale

Dans cette première version, nous allons charger une carte depuis une déclaration Java et fournir un export vers un format similaire.

1) Créez une classe GridRepoVar qui implémente l’interface GridRepo. Votre classe devrait avoir la forme suivante :

public class GridRepoVar implements GridRepo {

   private final Entity[][] sample1 = {
            {GROUND, GROUND, GROUND, GROUND, DUST, GROUND, GROUND, GROUND, GROUND},
            {GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, DUST, GROUND, GROUND},
            {GROUND, GROUND, ROCK, CRACK, GROUND, GROUND, BIGROCK, GROUND, GROUND},
            {GROUND, ROCK, GROUND, ROCK, GROUND, GROUND, GROUND, GROUND, GROUND},
            {GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND},
            {GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, CRACK, GROUND},
            {GROUND, DUST, GROUND, DUST, GROUND, GROUND, GROUND, GROUND, GROUND},
            {GROUND, GROUND, GROUND, CRACK, GROUND, DUST, BIGROCK, GROUND, GROUND},
            {GROUND, ROCK, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND, GROUND},
    };
    
    @Override
    public Grid load(String string) { 
        /*  Crée une nouvelle instance de la classe Grid et initialise les champs de l'objet avec les informations de sample1. 
            Retourn le nouvel objet.
         */ 
    }

    @Override
    public String export(Grid grid) { 
        /*  Retourne sous forme de chaîne de caractères la déclaration Java correspondant aux tableau d'entités de l'objet grid.
            Le code produit peut être utilisé pour remplacer la déclaration de sample1 plus haut.
        */ 
    }
}

Indications

StringBuilder s = new StringBuilder();
s.append("foo");
s.append("bar");
System.out.println(s.toString()); // output "foobar"  

2) Décommentez les lignes correspondantes dans la classe EditorView. Pour tester votre code cliquez sur le menu File et choisir Load from Java declaration. Une fois une image sélectionnée sur la partie droite de l’éditeur, il suffit de cliquer sur une case de la grille pour modifier la tuile correspondante. Si vous maintenez la touche SHIFT enfoncée, un survol des cases avec la souris aurra le même effet.

Version avec introspection

Utilisons maintenant une fonctionnalité très avancée de Java, l’introspection. Il s’agit d’un mécanisme qui permet de découvrir, de façon dynamique, des informations propres à une classe Java. Pas de panique, nous vous donnons tout ce dont vous avez besoin!

1) Ajoutez la méthode suivante dans la classe GridRepoVar.

private Entity[][] getEntities(String name) {
    try {
        Field field = this.getClass().getDeclaredField(name);
        return (Entity[][]) field.get(this);
    } catch (IllegalAccessException e) {
        return null;
    } catch (NoSuchFieldException e) {
        return null;
    }
}

2) Modifiez la méthode load de la manière suivante.

public Grid load(String name) {
    Entity[][] entities = getEntities(name);
    if (entities == null)
        return null;
    // Votre code ici
}

3) Remplacer l’appel de la méthode load dans la classe EditorView par les trois lignes suivantes. Vous pouvez maintenant saisir sample1 qui est le nom de votre tableau Entity dans le champ du formulaire.

Form form = new Form(stage, "Name field");
this.grid = gridRepoVar.load(form.getText());
updateGrid(grid);

4) Ajoutez la déclaration sample2 suivante dans la classe GridRepoVar et tester votre code en saisisant sample1 ou sample2 dans le champ du formulaire pour sélectionner le tableau d’entitées à utiliser.

private final Entity[][] sample2 = {
    {GROUND, ROCK, DUST, ROCK, GROUND},
    {GROUND, CRACK, BIGROCK, CRACK, DUST},
    {GROUND, CRACK, CRACK, GROUND, BIGROCK},
    {ROCK, DUST, DUST, GROUND, DUST}
};

Codage des cartes

Nous allons maintenant coder une carte sous la forme d’une chaîne de caractère en utilisant le codage défini dans l’énumération Entity. Par exemple, un rocher est codé par le caractère R. Nous utiliserons par la suite le caractère x comme marqueur de fin de ligne (EOL). Nous supposerons pour le moment que les chaînes de caractères sont bien formées.

1) Créez une classe GridRepoString qui implémente l’interface GridRepo. Cette classe contiendra la déclaration suivante :

final char EOL = 'x';

2) Décommentez les lignes correspondantes dans la classe EditorView et testez votre code.

Indications

Gestion des erreurs

Lors du chargement d’une carte depuis une chaîne de caractères, de nombreuses erreurs peuvent avoir lieu.

1) Créez une exception GridException qui permettra d’avoir une erreur personalisée avec un message explicite sur la cause de l’erreur : Invalid character, Missing eol character, etc. Votre exception sera de nature Unchecked.

2) Modifiez les classes Entity et GridRepoString pour lever une exception en cas d’erreur.

Compression

Notre codage n’est pas très efficace si un caractère se répète beaucoup. Nous allons mettre en oeuvre une version très simplifiée de l’algorithme de compression LRE. Si un caractère c est répété 6 fois, nous écrirons c6 au lieu de cccccc.

1) Créez une classe GridRepoStringRLE qui implémente l’interface GridRepo.

2) Décommentez les lignes correspondantes dans la classe EditorView et testez votre code.

Indications