Le jeu de la bataille

04-03-2023

Le matériel fourni

Préparer le travail

  1. Récupérer le fichier tp_bataille_carte.zip et le décompresser dans votre dossier de travail.

  2. Renommer le fichier card_squelette.py en card.py.

  3. Renommer le fichier war_squelette.py en war.py.

Le module card

Le fichier card.py contient l’implantation d’une structure de donnée permettant de représenter des cartes.

Les « couleurs » des cartes sont représentées par les chaînes de caractères appartenant au tuple COLORS : « spade » = pic, « heart » = coeur, …

Les « valeurs » des cartes sont représentées par les chaînes de caractères appartenant au tuple VALUES : « Ace » pour l’as, « 2 » pour le deux, …, « Queen » pour la reine, …

Une carte sera représentée par un dictionnaire à deux associations : une pour la couleur et une pour la valeur. Vous pouvez choisir librement les deux clés correspondantes.

Chaque fonction du module card est documentée. Vous devez compléter les fonctions pour que les tests présents dans les docstring soient satisfaits.

Pour cela vous pouvez utiliser le module doctest utilisé par le programme principal du fichier : Si vous exécutez le script, l’exécution des tests signaleront des erreurs. Le but est donc de compléter les fonctions pour qu’il n’y ait plus d’erreurs.

  1. Réaliser une fonction create qui renvoie une nouvelle carte de la couleur et de la valeur fournies en paramètres.

  2. Réaliser une fonction get_color prenant en paramètre une carte et qui renvoie sa couleur sous la forme d’un élément du tuple COLORS.

  3. Réaliser une fonction get_value prenant en paramètre une carte et qui renvoie sa valeur sous la forme d’un élément du tuple VALUES.

  4. Réaliser une fonction is_card paramétrée par un dictionnaire et qui renvoie True si le dictionnaire représente une carte, c’est-à-dire s’il possède deux associations dont les clés sont celles que vous aurez choisies et les valeurs associées des éléments des tuples COLORS ou VALUES.

On définit un ordre sur les cartes. L’ordre utilisé sur les cartes s’appuie sur l’ordre des valeurs tel que défini par le tuple VALUES des valeurs (ainsi Ace < 2 < 3 < … < King).

  1. Réaliser une fonction compare prenant en paramètre deux cartes, et qui renvoie :

    • 1 si la première carte est supérieure à la deuxième ;

    • -1 si la première carte est inférieure à la deuxième ;

    • 0 si les cartes sont égales.

  2. Réaliser une fonction to_str paramétrée par une carte et qui renvoie une chaîne de caractères représentant la carte.

  3. Réaliser une fonction deck prenant en paramètre un entier n_card compris entre 1 et 52, et qui renvoie une liste (python) de n_card cartes choisies au hasard. On pourra utiliser la fonction shuffle du module random pour mélanger les cartes.

Le jeu de bataille

Le jeu de la bataille est un jeu de cartes à deux joueurs, appelons les j1 et j2. À chaque instant, j1 et j2 disposent d’un ensemble de cartes appelé main.

Avant de commencer, on choisit un nombre de tours à effectuer. À chaque tour, j1 et j2 prennent la première carte de leur main. On compare les deux cartes :

  • Si la carte de j1 est supérieure à celle de j2, alors j1 remporte toutes les cartes sur la table ;

  • Si la carte de j1 est inférieure à celle de j2, alors j2 remporte toutes les cartes sur la table ;

  • Si les cartes sont égales, alors elles sont empilées sur la table : d’abord celle de j2, puis celle de j1.

Le jeu se poursuit tant que les deux joueurs ont des cartes et que le nombre de tours n’est pas atteint.

Lorsqu’un joueur remporte les cartes, celles-ci sont ajoutées une par une à la fin de sa main :

  • On ajoute d’abord les deux cartes comparées : celle de j1 d’abord puis celle de j2 ;

  • Puis, tant qu’il y a des cartes sur la table, on prend la carte en haut du tas de cartes, et on l’ajoute à la fin de la main.

À la fin du jeu, le joueur qui a le plus de cartes est déclaré vainqueur. Si les deux joueurs ont le même nombre de cartes, alors il y a égalité.

La description de ce jeu fait apparaitre deux structures de données pour gérer les cartes :

  • Les mains des joueurs seront représentées par des files de cartes : ainsi l’opération enqueue permettra d’ajouter une carte en fin de main, alors que l’opération dequeue permettra d’enlever et obtenir la première carte de la main. Le module apqueue.py fourni définit une classe ApQueue permettant de manipuler de telles files ;

  • Le tas de carte de la table sera représenté par une pile de cartes : L’opération push permet d’ajouter une carte sur le tas, alors que l’opération pop permet d’enlever et d’obtenir la carte située au sommet de la pile. Le module apstack.py fournit définit une classe ApStack permettant de manipuler de telles piles.

Les fonctions suivantes sont à compléter dans le script war.py. Les entêtes et les docstrings sont fournies. Comme pour le module card vous devez compléter les fonctions pour satisfaire les tests. En aucun cas vous ne devez modifier les doctests.

  1. Réaliser une fonction distribute paramétrée par un entier n_card et qui renvoie un tuple de deux files, chacune contenant n_card cartes. Les 2*n_card sont distinctes et choisies au hasard. On pourra utiliser la fonction deck du module card.

  2. Réaliser une procédure gather_stack paramétrée par la main main d’un joueur et une pile de cartes pile et qui ajoute toutes les cartes prises une par une sur le tas dans la main du joueur comme décrit plus haut. À la fin de l’exécution de la procédure, la pile est vide.

  3. Réaliser une procédure play_one_round paramétrée par les mains des deux joueurs et la pile des cartes sur la table, et qui simule une étape du jeu. À la fin de l’exécution de cette procédure, soit la pile et vide et l’une des deux mains contient ses cartes, soit la pile contient deux cartes supplémentaires et les deux mains une carte en moins (cas d’égalité). Exceptionnellement, vous utiliserez des print dans cette fonction pour rendre compte du déroulé du jeu. Voici un exemple de déroulé possible :

    >>> play_oue_round(m1, m2, pile)
    joueur 1 joue 3 of spade et joueur 2 joue 3 of club
    Bataille !!
    2 cartes sur la table
    
  4. Réaliser une procédure play paramétrée par le nombre de cartes à distribuer à chaque joueur et le nombre de tours maximal à effectuer. Cette procédure simule une partie de bataille et affiche l’état du jeu comme illustré ci-dessous, ainsi que le vainqueur :

    >>> play(4, 10)
    ------ Tour 1 --------
    joueur 1 joue 6 of heart et joueur 2 joue King of club
    joueur 2 gagne
    Le joueur 1 a 3 cartes et le joueur 2 a 5 cartes
    ------ Tour 2 --------
    joueur 1 joue 3 of club et joueur 2 joue 2 of club
    joueur 1 gagne
    Le joueur 1 a 4 cartes et le joueur 2 a 4 cartes
    ------ Tour 3 --------
    joueur 1 joue 2 of heart et joueur 2 joue 9 of spade
    joueur 2 gagne
    Le joueur 1 a 3 cartes et le joueur 2 a 5 cartes
    ------ Tour 4 --------
    joueur 1 joue 3 of spade et joueur 2 joue Ace of club
    joueur 1 gagne
    Le joueur 1 a 4 cartes et le joueur 2 a 4 cartes
    ------ Tour 5 --------
    joueur 1 joue 3 of club et joueur 2 joue 6 of heart
    joueur 2 gagne
    Le joueur 1 a 3 cartes et le joueur 2 a 5 cartes
    ------ Tour 6 --------
    joueur 1 joue 2 of club et joueur 2 joue King of club
    joueur 2 gagne
    Le joueur 1 a 2 cartes et le joueur 2 a 6 cartes
    ------ Tour 7 --------
    joueur 1 joue 3 of spade et joueur 2 joue 2 of heart
    joueur 1 gagne
    Le joueur 1 a 3 cartes et le joueur 2 a 5 cartes
    ------ Tour 8 --------
    joueur 1 joue Ace of club et joueur 2 joue 9 of spade
    joueur 2 gagne
    Le joueur 1 a 2 cartes et le joueur 2 a 6 cartes
    ------ Tour 9 --------
    joueur 1 joue 3 of spade et joueur 2 joue 3 of club
    Bataille !!
    2 cartes sur la table
    Le joueur 1 a 1 cartes et le joueur 2 a 5 cartes
    ------ Tour 10 --------
    joueur 1 joue 2 of heart et joueur 2 joue 6 of heart
    joueur 2 gagne
    Le joueur 1 a 0 cartes et le joueur 2 a 8 cartes
    Le joueur 2 a gagné