UFR de Mathématiques et d'Informatique
IUP 1, DEUG 2, 2002/2003
Algorithmique et programmation orientées objets
Contrôle continu
Exercice de programmation








CUBE








Rapport à rendre le vendredi 9 mai 2001.

Binomes autorisés.





La séance de TP de la semaine du 28 avril sera consacrée à programmer pour cet exercice : les encadrants de TP pourront y répondre aux questions éventuelles. Il est donc recommendé d'avoir commencé la programmation avant cette semaine.




1  Le sujet, en bref

Il s'agit de réaliser une implémentation orientée objets, en Java, du Rubik's cube. Les sorties se feront sur la sortie standard.

Deux choses sont à réaliser :



Cette implémentation sera ensuite utilisée pour compter le nombre de répétitions d'une séquence, nécessaires pour retrouver l'état de départ. En effet, une des propriétés du cube est que si, en partant d'un certain état de départ, on applique une certaine séquence de manipulations de faces, alors pour retrouver l'état de départ il suffit de réappliquer autant de fois que nécessaire cette séquence. Le nombre de répétitions nécessaires est quant à lui facilement calculé par une simulation par ordinateur, d'où le présent projet. (Il est possible d'essayer à la main, mais il faut savoir que jusqu'à 1260 répétitions peuvent être nécessaires ....)

2  Le Rubik's cube

Le Hongrois Ernö Rubik a lancé le cube en Hongrie en 1980. Le cube a ensuite été exporté, via la firme américaine Ideal Toy Company. Il a connu un succès considérable au début des années 1980.

Aujourd'hui, le cube revient, sur Internet. Vous pouvez trouver plusieurs applets sur le net. Par exemple : http://www.npac.syr.edu/projects/java/magic/Magic.html.

La plupart de ces applets sont programmées, cependant, de façon assez directe, et pas très orientée-objets, car leur code n'est pas destiné à servir à autre-chose qu'à animer l'applet.

Le présent projet, par contraste, met l'accent sur le cube lui-même, et son fonctionnement. C'est pourquoi nous nous contentons dans ce projet de la sortie standard. Une fois que votre programme fonctionnera, vous pourrez facilement lui adjoindre une applet pour une manipulation graphique du cube.

3  Choix de conception

Il vous est demandé d'implanter le cube en utilisant la modélisation suivante : on s'inspire de la façon dont fonctionne le cube <<concret>>, et on choisit de considérer le cube comme constitué de 27 petits cubes (que nous appelerons <<pièces>> dans la suite), assemblés de façon à former le cube.

Votre programme devra donc comporter au moins les deux classes suivantes : la classe publique RubiksCube, et la classe Piece.

3.1  Pour parler du cube

Afin que vous puissiez discuter du cube entre vous, et avec l'examinateur de votre programme, il est demandé que tout le monde utilise le même placement initial du cube dans l'espace. Étant donné le cube initialement posé sur un support horizontal comme une table, 3 faces sont visibles : la face du devant (<<front>>), la face du dessus (<<top>>), et la face de droite (<<right>>).

Dans ce projet on ne considère pas de <<basculements>> du cube, et donc ces trois faces resteront, au cours des transformations du cube, celles observées depuis le point d'observation initial.





Initialement, les couleurs sont disposées comme suit sur les faces du cube :




face colour
top blue
down green
front red
back orange
left white
right yellow






Les vocables anglais ici utilisés sont ceux utilisés d'habitude pour parler du cube. Pour les faces, en particulier, il constituent un standard, ce qui fait que pour tout cubiste, <<TFL>> signifie : <<quart de tour dans le sens des aiguilles d'une montre de la face du dessus, puis quart de tour dans le sens des aiguilles d'une montre de la face du devant, puis quart de tour dans le sens des aiguilles d'une montre de la face de gauche>>.

3.2  La classe RubiksCube

3.2.1  Les méthodes publiques

La classe RubiksCube devra fournir les méthodes publiques suivantes :



3.2.2  L'implantation

Pour l'implantation, l'idée est d'utiliser les tableaux à plusieurs dimensions de Java, et d'avoir le champ privé suivant :
  private Piece[][][] cube ;
cube est un tableau à trois dimensions, de longueur 3 dans chaque dimension---i.e., le constructeur définira :
  cube = new Piece[3][3][3] ;

3.3  La classe Piece

Une pièce est un petit cube. Ainsi, un coin du cube, dans l'état initial, peut être vu comme un petit cube avec trois faces colorées et trois faces non colorées (disons, grises).

3.4  Le principe d'implantation

Le fait d'avoir, pour représenter un cube, un tableau à trois dimensions de petits cubes, permet d'implémenter l'opération de pivotage d'une face de façon simple. Faire pivoter la face de devant, par exemple (<<front>>), d'un quart de tour dans le sens des aiguilles d'une montre (ce que fait la méthode <<F()>>) consiste à :


  1. demander à chacune des pièces de la face (sauf éventuellement celle du centre) de pivoter sur elle-même, d'un quart de tour dans le sens des aiguilles d'une montre, par rapport à sa face <<front>>.

3.5  Repère dans l'espace

L'association suivante devra être suivie pour situer les pièces dans le tableau à trois dimentions constituant le cube : la première dimension correspond à l'axe <<left ® right>>, la deuxième à l'axe <<down ® top>>, et la troisième à l'axe <<front ® back>>. Ainsi, la pièce cube[0][2][0] est le coin <<front-top-left>>.

De façon plus générale, vous pouvez utiliser un repère pour situer les faces dans l'espace à trois dimensions. Dans ce cas, il vous est demandé de suivre l'association suivante : l'axe x correspond à l'axe <<left ® right>>, l'axe y à l'axe <<down ® top>>, et l'axe z à l'axe <<front ® back>>. (Ainsi, la première dimension du tableau suit l'axe x, la deuxième l'axe y, et la troisième l'axe z.)

4  Comment devrait se comporter votre programme

Le test suivant devrait pouvoir fonctionner avec votre code :

public class TestRubiksCube {
  // Test de la classe RubiksCube :

  public static void main( String [] args)
  {
    RubiksCube cube = new RubiksCube() ;

    System.out.println(cube) ;
    cube.F() ;
    System.out.println("\n") ;
    System.out.println(cube) ;

    System.out.println("\n") ;
    System.out.println("Returned to initial state after " +
                    + countFTTBDDLL()
                    + " instances of FTTBDDLL.") ;
  }

  public static int countFTTBDDLL() {
    RubiksCube c = new RubiksCube() ;
    c.F() ; c.T() ; c.T() ; c.B() ; c.D() ; c.D() ; c.L() ; c.L() ;
    int k = 1 ;

    while (!c.isInInitialState())
    {
      c.F() ; c.T() ; c.T() ; c.B() ; c.D() ; c.D() ; c.L() ; c.L() ;
      k++ ;
    }
    return k ;
  }
}
Une sortie possible pour l'exécution du test précédent est la suivante :





   |OOO|
   |OOO|
   |OOO|
    --- 
   |BBB|
   |BBB|
   |BBB|
    --- 
WWW|RRR|YYY
WWW|RRR|YYY
WWW|RRR|YYY
    --- 
   |GGG|
   |GGG|
   |GGG|




   |OOO|
   |OOO|
   |OOO|
    --- 
   |BBB|
   |BBB|
   |WWW|
    --- 
WWG|RRR|BYY
WWG|RRR|BYY
WWG|RRR|BYY
    --- 
   |YYY|
   |GGG|
   |GGG|




Returned to initial state after 140 instances of FTTBDDLL.

5  Conseils pour la méthodologie

Conseil pour l'écriture du code : testez régulièrement votre code. I.e., écrivez, testez, écrivez, .... Ainsi, s'il y a un bug à un moment, il devrait être rapidement trouvé.

6  Ce qu'il faut rendre

Il est demandé de rendre un petit rapport comprenant :



La notation se fera d'une part à partir de ce rapport, et d'autre part à partir d'une soutenance rapide (5 à 10 minutes) devant machine, qui sera faite après le 9 mai, après que le correcteur aura examiné votre rapport. Pour cette soutenance devant machine, l'examinateur disposera d'une batterie de tests (du type de celui ci-dessus), faisant appel à la classe RubiksCube, et aux méthodes de cette classe qui ont été demandées, avec les noms donnés ci-dessus (par exemple : setInitialState). Il est donc important que vous ne changiez pas le nom et/ou le prototype des méthodes demandées.





La lisibilité et la compréhensibilité du listing jouera une part importante dans la note. Veillez donc, d'une part, à commenter toute partie non forcément évidente de votre code ; et d'autre part à respecter les conventions de codage standard de Java :
classes: 
    CapitalizedWithInternalWordsAlsoCapitalized 
constants (finals): 
    UPPER_CASE_WITH_UNDERSCORES 
private or protected: (pick one!) 
    firstWordLowerCaseButInternalWordsCapitalized OR 
    trailingUnderscore_, OR 
    thisVar (i.e. prefix with this), OR 
    myVar (i.e. prefix with my), OR 
    fVar (i.e. prefix with f) 
static private or protected: 
    firstWordLowerCaseButInternalWordsCapitalized OR 
    twoTrailingUnderscores__ 
local variables: 
    firstWordLowerCaseButInternalWordsCapitalized OR 
    lower_case_with_underscores 
methods: 
    firstWordLowerCaseButInternalWordsCapitalized() 
(Extrait de : http://gee.cs.oswego.edu/dl/html/javaCodingStd.html, par Doug Lea.)





Cette convention n'est pas une camisole de force, mais un moyen de s'assurer, si vous la suivez, que non seulement votre correcteur lira facilement votre code, mais également vos camarades, si vous faites appel à eux en cas de problème sur un point particulier, puisqu'ils se seront eux-mêmes familiarisés avec la même convention.

N'oubliez pas non plus d'indenter et d'espacer, de façon à rendre explicite la structure de votre programme. Par exemple, l'examinateur ne sera pas mis de bonne humeur du tout si votre code ressemble au suivant :

class Colour{private String name;private Colour(String s){name=s;}
public static final Colour WHITE=new Colour("W");
public static final Colour YELLOW=new Colour("Y");
public static final Colour RED=new Colour("R");
public static final Colour ORANGE=new Colour("O");
public static final Colour BLUE=new Colour("B");
public static final Colour GREEN=new Colour("G");
public static final Colour GREY=new Colour("*");
public boolean equals(Colour col2){return name.equals(col2.name);}
public String toString(){return name;}}




(Une version préférable peut être vue ci-dessous.)

7  Indications

On pourra utiliser les classes suivantes, en les modifiant si nécessaire :

















Ces classes peuvent être téléchargées à partir de la page http://dpt-info.u-strasbg.fr/~gerner.


This document was translated from LATEX by HEVEA.