:: Enseignements :: ESIPE :: E3INFO :: 2013-2014 :: Programmation Objet avec Java ::
[LOGO]

Itérateurs, enumérations, factory method, mutabilité


Exercice 1 - Stack

Ecrire une classe Stack qui représente une pile, permettant de stocker des objets, et implémentée par un tableau. Cette classe doit disposer de deux constructeur: l'un ayant un argument, correspondant à la capacité de la pile, et l'autre sans argument qui initialise utilise une capacité par défaut de 10.

  1. Ajouter les méthodes void push(Object o) et Object pop() qui respectivement ajoute un élément au sommet de la pile ou dépile et retourne l'élément au sommet.
  2. Faire en sorte que les variables de type Stack puissent être utilisées dans les structures for-each (l'ordre dans lequel elles doivent être listées est du fond de la pile au sommet de la pile). Par exemple:
        Stack s = new Stack();
        s.push("a");
        s.push("b");
        s.push("+");
        for(Object o : s) {
          System.out.println(o);
        }
        System.out.println("--------");
        s.push("d");
        s.push("e");
        s.push("-");
        s.push("*");
        for(Object o : s) {
          System.out.println(o);
        }
        System.out.println("--------");
    
    doit afficher:
    a
    b
    +
    --------
    a
    b
    +
    d
    e
    -
    *
    --------
    
  3. Paramétrer la classe par le type des éléments qui y sont stockés (par exemple Stack<String> dans le code ci-dessus).

Exercice 2 - Jeu de cartes

Considérez la classe Suit qui répresente une couleur dans un jeu de cartes (pique, trèfle, coeur ou carreau)
et la classe Card qui représente une carte à jouer
Dans cet exercice, on va écrire une classe Deck (dans le package fr.upem.card) représentant un jeu de cartes. Cette classe utilisera la classe java.util.ArrayList pour stocker les cartes.

  1. Commencer par créer une classe Main et afficher dans le main de celle-ci la valeur de SPADES.
    Rappeler quelle est la différence principale entre un enum en C et un enum en Java ?
  2. Créer une classe Deck, avec un constructeur prenant deux paramètres:
    • un nombre cardsPerSuit de cartes par couleur;
    • un tableau suits de couleurs de cartes (Suit).
    Ce constructeur crée un jeu de carte qui comprend cardsPerSuit cartes pour chacune des couleurs de suits.
    Pour deux cartes par couleur et avec les couleurs CLUBS et HEARTS, le jeu doit contenir quatre cartes [1 of CLUBS, 2 of CLUBS, 1 of HEARTS, 2 of HEARTS] dans cet ordre.
    Pour tester, vous écrirez aussi la fonction d'affichage habituelle.
  3. Modifier le constructeur pour que l'on puisse l'appeler en séparant les couleurs par des virgules:
    Deck deck = new Deck(2, Suit.CLUBS, Suit.HEARTS);
    Utiliser la notation varargs (ou ellipsis) pour cela.
  4. Utiliser un import static pour pouvoir désigner CLUBS et HEARTS sans les préfixer par Suit ce qui permettra d'écrire le code suivant:
    Deck deck = new Deck(2, CLUBS, HEARTS);
  5. Expliquer pourquoi utiliser un constructeur pour cela n'est pas une bonne idée.
    Modifier le code pour utiliser une factory method à la place.
  6. Pourquoi le constructeur doit maintenant être privé ?
  7. Ecrire une méthode equals qui compare deux Decks (l'ordre des cartes est important).
    Pourquoi doit-on modifier la classe Card ?

Exercice 3 - Mutabilité

  1. En réutilisant la classe Deck, écrire une méthode getCardList qui renvoie une liste de carte.
    Pourquoi le type de retour de la méthode ne doit pas être ArrayList ?
  2. Le code suivant montre que votre méthode getCardList est mal codée
         Deck deck = ...
         deck.getCardList().remove(0);
        
    Pourquoi ?
    Résoudre le problème en utlisant une copie défensive.
  3. Quelle est le problème de la copie défensive sur une collection ?
    Pourquoi est-il plus efficace d'utiliser la méthode java.util.Collections.unmodifiableList() ?
    Modifier votre code en conséquence.

Exercice 4 - Bataille [A la maison]

  1. Modifier la classe Card pour afficher valets, dames, roi, as (en anglais SVP) à la place de leur valeur numérique.
    Pitié pour le processeur éviter les if ... else imbriqués.
  2. Dans l'exemple suivant, on mélange une liste et le tableau se retrouve mélangé
           String[] array = new String[] { "baz", "foo", "bar" };
           List<String> list = Arrays.asList(array);
           Collections.shuffle(list);
           System.out.println(Arrays.toString(array));
         
    Expliquez ce mystère.
  3. Ecrire dans la classe Deck une méthode shuffle qui renvoie un nouveau Deck dont les cartes sont mélangés.
    Attention, l'ordre des cartes du Deck existant ne doit pas être modifié.
  4. Ecrire dans la classe Deck une méthode split qui après avoir vérifié que le deck contenait un nombre pair de cartes créé deux nouveaux Deck ayant chacun la moitié des cartes.
    Attention, l'ordre des cartes du Deck existant ne doit pas être modifié.
  5. Ecrire une méthode fight qui prend une liste de decks et renvoie une liste de nouveaux decks en ayant appliqué entre eux un tour des règles de la bataille. On considérera qu'en cas de bataille alors qu'il n'y a plus assez de carte, que les cartes sont laissés dans chaque deck.
  6. Ecrire un main de test, qui génére deux decks à partir d'un jeu de 32 cartes, affiche ceux ci, puis affiche tour par tour les decks résultant du jeu de la bataille.
    Attention à vérifier que le jeu ne part pas dans une boucle infinie (règle du pat!).