TD 5 noté : partie de dominos

Une partie de dominos à Haïti

Ce TD sera noté. Vous devrez utiliser un fichier unique du nom de Partie.java. Ce fichier contiendra les diverses classes qui vous sont demandées. Déposez régulièrement vos programmes en utilisant la ligne de commande :
/users/profs/info/Depot/INF_421/deposer Partie.java TD_5 numéro_du_groupe
Le numéro de groupe est celui que vous avez en INF421, compris entre 1 et 6. Pour voir les fichiers que vous aurez déposés :
/users/profs/info/Depot/INF_421/voir
La clarté et la concision des programmes seront prises en compte dans la notation.

Au bout des deux heures de TD, il ne sera plus possible de déposer de fichier.

1  Jeux de dominos

Le but de ce TD sera de faire jouer des parties de dominos à l'ordinateur. Un domino est composé de deux chiffres entre 0 et 6. Un jeu est composé des 28 dominos possibles avec ces deux chiffres. La valeur d'un domino est le nombre composé de son plus grand chiffre suivi de son plus petit chiffre.

Une partie comporte de 2 à 4 joueurs. À 2 joueurs, on donne à chaque joueur 7 dominos tirés au hasard, à 3 ou 4 joueurs, 6 dominos. Le joueur qui a le domino de plus forte valeur commence à jouer. On doit poser les dominos à la suite les uns des autres en les combinant (c'est-à-dire qu'un des côtés du domino posé doit porter le même nombre de points que le domino sur la table).

Une suite valide de dominos
Lorsqu'un joueur n'a pas de domino à jouer il en pioche (il en prend) un au hasard parmis ceux qui restent. S'il ne reste plus de domino à piocher, il "boude" (il ne fait rien). Le premier qui a posé tous ses dominos a gagné. Si personne ne pose tous ses dominos, c'est celui à qui il en reste le moins qui gagne.

2  Les dominos

Vous devrez écrire vos fonctions dans un fichier Partie.java. Toutes les fonctions statiques, dont la fonction main, pourront être regroupées dans une classe Partie.

Les dominos seront représentés par des éléments de la classe suivante :

class Domino {
  int gauche, droite;

  Domino(int g, int d) {
    gauche = g;
    droite = d;
  }

  public String toString() {
    return gauche + "-" + droite;
  }

  public boolean equals(Object o) {
    if(this==o) return true;
    if(o instanceof Domino) {
      Domino d = (Domino) o;
      return (gauche==d.gauche && droite==d.droite)
            || (gauche==d.droite && droite==d.gauche);
    }
    return false;
  }
}
Les ensembles de dominos (pioche, mains des joueurs) seront représentés par des listes.

Question 2.1

Écrivez une classe Liste de listes de dominos avec son constructeur.

Question 2.2

Écrivez dans une classe Partie une méthode static int longueur(Liste l) qui renvoie la longueur d'une liste.

Question 2.3

Écrivez une méthode static void lister(Liste l) qui imprime une liste.

Pensez à tester vos fonctions. Exemple :

Liste l = new Liste(new Domino(1,4), new Liste(new Domino(2,0), null));
lister(new Liste(new Domino(6,6), new Liste(new Domino(5,3), l)));
pourra imprimer 6-6 5-3 1-4 2-0.

3  Mise en place du jeu

Toutes les méthodes et variables de cette section sont à écrire dans la classe Partie.

Pour représenter une partie en cours, le programme utilisera deux variables statiques : static Liste pioche qui contiendra au départ tous les dominos, puis les dominos restant à piocher, et static Liste[] mains qui contiendra les mains, c'est-à-dire les dominos de chaque joueur.

Question 3.1

Écrivez une méthode static void creerPioche() qui initialise pioche avec la liste de tous les 28 dominos possibles. Notez que les dominos sont réversibles, c'est-à-dire que le domino dont le chiffre gauche est i et le chiffre droit j est le même que celui avec j à gauche est i à droite. Si la pioche contient déjà le domino 1-5, elle ne doit pas contenir 5-1. Cette liste est donc constituée des dominos 0-0, 1-1, 2-2, 3-3, 4-4, 5-5, 6-6, 0-1, 1-2, 2-3, 3-4, 4-5, 5-6, 2-0, 3-1, 4-2, 5-3, 6-4, 0-3, 1-4, 2-5, 3-6, 4-0, 5-1, 6-2, 0-5, 1-6, 6-0 (ou leur version retournée) dans l'ordre de votre choix.

Question 3.2

Écrivez une méthode static Domino nieme(Liste l, int n) qui renvoie le domino numéro n de la liste l. On considérera que la première cellule de la liste a le numéro 0.

Question 3.3

Écrivez une méthode static Liste supprimer(Liste l, Domino d) qui renvoie la liste l sans le domino d.

Question 3.4

Écrivez une méthode static Domino piocher() qui enlève un domino au hasard de pioche et le renvoie. Pour tirer au hasard un nombre entre 0 et max-1, on pourra utiliser la fonction :
static int entierAuHasard(int max) {
  return (int) (Math.random() * max);
}

Question 3.5

Écrivez une méthode static void creerMain(int nombre, int joueur) qui tire au hasard (à l'aide de piocher) les nombre dominos de la main du joueur numéro joueur (dans le tableau mains), les retire de la pioche et les range à leur place dans le tableau mains.

Question 3.6

Écrivez les méthodes valeurDomino qui donne la valeur d'un domino (10 fois son plus grand chiffre plus son plus petit), valeurMain qui donne la plus grande valeur d'une main, et plusForteMain qui renvoie le numéro du joueur qui devra commencer à jouer.

Pensez à tester vos fonctions.

4 La séquence de dominos

Les joueurs doivent placer les dominos selon une séquence de dominos compatibles. Ils peuvent placer les dominos à gauche ou à droite de cette séquence.
Une séquence commence quand un joueur pose un domino. Une séquence ne peut donc pas être vide !

Question 4.1

Écrivez une classe Sequence avec un champ contenant une liste de dominos. Dans cette classe, écrivez le constructeur Sequence(Domino d) et la méthode void imprimer() qui servira à imprimer une séquence.

Question 4.2

Écrivez dans la classe Sequence la méthode void ajouterAGauche(Domino d) qui ajoute un domino à gauche de la séquence (c'est-à-dire en tête de liste). Ajoutez la méthode int valeurGauche() qui renvoie le chiffre de gauche du domino le plus à gauche de la séquence.

Question 4.3

De même, écrivez les méthodes ajouterADroite qui ajoute un domino à droite de la séquence (c'est-à-dire en queue de liste) et valeurDroite qui renvoie le chiffre de droite du domino le plus à droite.

Question 4.4

Proposez et implémentez une façon de réaliser les méthodes ajouterADroite et valeurDroite en temps constant (en gardant les méthodes ajouterAGauche et valeurGauche en temps constant).

5  Faire jouer le programme

Question 5.1

Écrivez dans la classe Partie une méthode static boolean jouer(int joueur, Sequence jeu) qui fait jouer le joueur joueur. Celui-ci devra poser un domino si possible, sinon piocher et sinon "bouder". La méthode renverra false si et seulement si le joueur boude (le jeu n'avance pas). Il pourra être utile d'écrire une méthode qui renverse un domino.

Question 5.2

Écrivez votre fonction main de manière à faire jouer une partie à l'ordinateur (entre 2, 3 ou 4 joueurs). Il pourra être utile d'écrire une méthode qui imprime le ou les gagnants.

Pour départager les éventuels ex-aequo, on peut compter la somme des valeurs des dominos restant en main. Celui qui aura la plus petite valeur de main aura gagné. Afin de faire jouer l'ordinateur dans cette optique (sans trop modifier le programme), on peut écrire une méthode pour mettre en premier dans la main le domino jouable de plus grande valeur.

Question 5.3

Écrivez une méthode static Liste mettreMeilleurDevant(Liste l, Sequence jeu) qui retourne une liste composée des cellules de l telle que la première cellule contienne le domino jouable sur la séquence jeu de plus grande valeur. Cette méthode sera appelée au début de jouer. Modifiez ensuite votre fonction qui imprime les gagnants pour départager les ex-aequo en fonction de la valeur de leur main.