Jeu du démineur

sept. 10, 2018

Objectifs

Programmation du jeu du démineur.

Moyens mis en oeuvre

  • programmation modulaire
  • récursion
  • traitement d’exceptions

Présentation du jeu du démineur

Est-il nécessaire de présenter ce célèbre jeu ?

Si vous ne le connaissez pas, vous êtes invité

  • à consulter la page Wikipédia consacrée à ce sujet,
  • et à faire quelques parties (mais pas pendant cette séance de TP).

Préparation du travail

Un matériel de base vous est fourni.

À faire

Récupérez le fichier Minesweeper.zip et décompressez le dans un dossier que vous nommerez Minesweeper.

Outre les fichiers usuels, vous devez obtenir dans le dossier src

  • un fichier cell.py
  • un fichier minesweeper.py
  • un fichier graphicalboard.py
  • un dossier icons contenant quelques icones.

et dans le dossier sourcedoc

  • un fichier index.rst
  • un fichier cell.rst
  • un fichier minesweeper.rst
  • un fichier graphicalboard.rst.

À faire

Ajoutez les noms de votre binôme dans le fichier Makefile.

À faire

Produisez la version HTML de la documentation (make doc).

Le module cell

À faire

Après avoir soigneusement étudié la documentation de ce module, programmez les différentes méthodes de la classe Cell.

Le module minesweeper

À faire

Complétez la documentation dans l’en-tête du fichier minesweeper.py.

À découvrir

Après la directive d’importation from enum import Enum, ce module commence par définir un nouveau type GameState (ou plutôt une nouvelle classe) :

class GameState (Enum):
    """
    A class to define an enumerated type with three values :

    * ``winning``
    * ``losing``
    * ``unfinished``

    for the three state of minesweeper game.
    """
    winning = 1
    losing = 2
    unfinished = 3

Cela permet de définir ce qu’en programmation on appelle un type énuméré. Et dans ce cas, ce type contient trois valeurs : winning, losing et unfinished (les valeurs 1, 2 et 3 qui leur sont associées sont totalement arbitraires). Ce type pourra donc être utilisé pour représenter l’état d’un jeu.

Voici une petite session illustrant l’usage de ce type

>>> import minesweeper
>>> minesweeper.GameState
minesweeper.GameState
>>> minesweeper.GameState.winning
<GameState.winning: 1>
>>> type (minesweeper.GameState.winning)
minesweeper.GameState
>>> minesweeper.GameState.winning == 1
False

Notez que malgré la valeur 1 attribuée à winning dans la définition de GameState, GameState.winning n’est pas le nombre 1.

Ce type permet de représenter les valeurs de l’état du jeu. Ainsi tant que le jeu n’est pas fini, son état a pour valeur GameState.unfinished. Cette valeur est le résultat de la méthode get_state() des objets de la classe Minesweeper (voir ci-dessous). Quand le jeu se termine, selon qu’il soit perdu ou gagné , la valeur de son état, fournie par la cette méthode est GameState.losing ou GameState.winning selon le cas.

À faire

Programmez la fonction neighborhood(). Et testez la sans oublier les cas particuliers des cases dans les coins ou sur les bords.

À faire

Programmez les différentes méthodes de la classe Minesweeper.

Programme principal

À faire

En utilisant les deux modules minesweeper et graphicalboard, réalisez dans un fichier graphical_main.py un programme principal qui permet de jouer au démineur via l’interface graphique.

Ce programme devra pouvoir prendre des arguments sur la ligne de commande, donnant la largeur, la hauteur, et le nombre de bombes. Des valeurs par défaut peuvent être attribuées en l’absence de ces arguments.

Voici un exemple possible d’appel à ce programme :

$ python3 graphical_main.py 10 5 3

qui ouvre cette fenêtre de jeu :

fenêtre de jeu du démineur 10x5

À faire

En utilisant le seul module minesweeper, réalisez dans un fichier console_main.py un programme principal qui permet de jouer au démineur en mode texte dans un terminal.

Ce programme devra pouvoir prendre des arguments sur la ligne de commande, donnant la largeur, la hauteur, et le nombre de bombes. Des valeurs par défaut peuvent être attribuées en l’absence de ces arguments.

Voici un exemple possible de session de jeu :

$ python3 console_main.py 10 5 3
     0   1   2   3   4   5   6   7   8   9
  +---+---+---+---+---+---+---+---+---+---+
 0|   |   |   |   |   |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 1|   |   |   |   |   |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 2|   |   |   |   |   |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 3|   |   |   |   |   |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 4|   |   |   |   |   |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
Your play x,y,C (C=(R)eveal,(S)et,(U)nset): 2,0,R
     0   1   2   3   4   5   6   7   8   9
  +---+---+---+---+---+---+---+---+---+---+
 0| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 1| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 2| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 3| 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 4| 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
Your play x,y,C (C=(R)eveal,(S)et,(U)nset): 3,5,S
     0   1   2   3   4   5   6   7   8   9
  +---+---+---+---+---+---+---+---+---+---+
 0| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 1| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 2| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 3| 0 | 0 | 0 | 0 | 1 | ? |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 4| 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
Your play x,y,C (C=(R)eveal,(S)et,(U)nset): 0,8,R
     0   1   2   3   4   5   6   7   8   9
  +---+---+---+---+---+---+---+---+---+---+
 0| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | B |   |
  +---+---+---+---+---+---+---+---+---+---+
 1| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 2| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 3| 0 | 0 | 0 | 0 | 1 | ? |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
 4| 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |
  +---+---+---+---+---+---+---+---+---+---+
You lose!