Le jeu de Nim

Les jeux combinatoires occupent une place importante en informatique. Ce sont des jeux dans lequels deux joueurs jouent alternativement en ayant une connaissance totale de l’information et où le hasard n’intervient pas dans le déroulement. Beaucoup de jeux ancestraux font parti de cette catégorie. C’est le cas du Nim.

Cette partie du cours est un cas d’étude qui permet de suivre le développement d’un tel programme.

Organisation générale du programme

Voici le fonctionnement du programme que l’on souhaite réaliser.

  • afficher un message au lancement du programme ;
  • jouer autant de parties que les joueurs le souhaitent ;
  • afficher un message lorsque l’on quite le programme.

À partir de la description ci-dessus, nous pouvons déterminer les différentes fonctions dont nous aurons besoin. Pour le premier et le dernier point nous avons besoin de deux fonctions affichant un message. Nous les noterons display_welcome_message et display_bye_message. Ces fonctions ne prendrons pas de paramètre.

Le deuxième est plus complexe, nous allons donc le découper en deux et créer deux fonctions. Une fonction play_again affichant un message demandant si les joueurs souhaitent jouer encore. Elle renverra True ou False. Nous utiliserons également une seconde fonction play_game réalisant une partie.

En supposans que ces fonctions existent déjà et qu’elle font strictement ce qui est indiqué ci-dessus, nous pouvons déjà réaliser la méthode principale (main) du programme.

def main():
    """
    Fonction principale du programme.
    """
    display_welcome_message()
    while play_again() :
        play_game( )

    display_bye_message()

main()

Nous voyons dans l’extrait de code ci-dessus que nous regroupons tous les éléments dans une seule fonction main. Cette fonction main est ensuite appelée une fois. L’intérêt est qu’un développeur lisant notre code soit capable d’identifier rapidement ce qu’il fait. Il lui suffit de voir que la seule méthode directement appelée est main (ce qui est une convention) puis d’aller voir le détail de cette seule méthode. Sa lecture est relativement simple. Ceci vient entre autres du choix des noms des méthodes. Il n’est pas nécessaire de connaître le détail des fonctions pour comprendre ce que fait globalement le programme.

Nous allons maintenant réaliser l’implémentation de chacune des fonctions. Elles pouront être testées indépendament. Ceci facilite beaucoup leur écriture et le débugage du programme. Rappelez-vous que l’objectif principal n’est pas de faire un programme court ou s’exécutant rapidement mais bien un programme qui fonctionne, sans bug et sans perdre un temps en débugage.

Implémentation des fonctions

Nous débutons avec l’implémentations des fonctions d’affichage des messages d’accueil et de fin.

def display_welcome_message():
    """
    Affiche le message d'accueil au lancement du jeu
    """
    print("***************************************")
    print("************ LE JEU DE NIM ************")
    print("***************************************")
    print("*         développé par : Mawe        *")
    print("***************************************")
    print("\n")
#Test du message affiché au lancement
display_welcome_message()
def display_bye_message():
    print("\n")
    print("***************************************")
    print("    Merci d'avoir joué, à bientôt.     ")
    print("***************************************")
#Test du message affiché de fin
display_bye_message()

Poursuivons avec l’implémentation de la fonction play_again. Celle-ci doit afficher un message demandant à l’utilisateur s’il veut jouer ou non. L’utilisateur doit alors saisir "o" ou "n". Suivant sa réponse la fonction renvoie True ou False.

Avec une boucle, on peut tester les cas où l’utilisateur ne saisit ni "o" ni "n" pour lui reposer la question.

def play_again():
    """
    Demande aux joueurs s'ils veulent rejouer et renvoie True ou False.
    """
    print("Voulez-vous faire une partie du jeu de Nim ? (o/n)")
    c = input()
    while c != 'o' and c != 'n' :
        print("Saisissez 'o' pour oui et 'n' pour non")
        c = input()
    if c == 'o' :
        return True
    else :
        return False
#Test de la fonction play_again, pensez à vérifier tous les cas possibles
play_again()
Voulez-vous faire une partie du jeu de Nim ? (o/n)

Saisissez 'o' pour oui et 'n' pour non
o
True

Il ne nous reste que la fonction play_game à réaliser. Cette dernière est un peu complexe. Nous allons donc lui donner un comportement par défaut. Cela nous permet de tester, avant de poursuivre, que l’ensemble des briques déjà codées s’ageancent correctement.

#Comportement par défaut de la fonction play_game
def play_game():
    """
    Réalise une partie.
    """
    print( "TODO : Le déroulement d'une partie" )
def main():
    """
    Fonction principale du programme.
    """
    display_welcome_message()
    while play_again() :
        play_game( )

    display_bye_message()

main()

Implémentation d’une partie

Pour que le jeu soit fonctionnel, il convient de développer la fonction play_game. Cette fonction étant relativement complexe, nous allons la découper. Voici les étapes que l’on peut identifier :

  • initialiser le jeu, c’est à dire définir que le joueur en cours est le numéro 1 et déterminer un nombre aléatoire de batons ;
  • tant qu’il reste au moins un baton
    • afficher le nombre de batons restant,
    • demander au joueur de choisir un nombre de batons à supprimer,
    • mettre à jour le nombre de batons,
    • changer le joueur courant ;
  • afficher le gagnant.

Le programme dans son ensemble

Voici une correction possible de ce sujet, réuni dans une seule cellule. Si l’on copie/colle cette cellule dans un fichier au format texte, avec l’extension .py, on pourra l’exécuter.

TODO : vidéo pour expliquer ça.

import random

def display_welcome_message():
    """
    Affiche le message d'accueil au lancement du jeu
    """
    print("***************************************")
    print("************ LE JEU DE NIM ************")
    print("***************************************")
    print("*         développé par : Mawe        *")
    print("***************************************")
    print("\n")

def display_bye_message():
    print("\n")
    print("***************************************")
    print("    Merci d'avoir joué, à bientôt.     ")
    print("***************************************")

def play_again():
    """
    Demande aux joueurs s'ils veulent rejouer et renvoie True ou False.
    """
    print("Voulez-vous faire une partie du jeu de Nim ? (o/n)")
    c = input()
    while c != 'o' and c != 'n' :
        print("Saisissez 'o' pour oui et 'n' pour non")
        c = input()
    if c == 'o' :
        return True
    else :
        return False


def play_game():
    """
    Réalise une partie.
    """
    print( "TODO : Le déroulement d'une partie" )

def main():
    """
    Fonction principale du programme.
    """
    display_welcome_message()
    while play_again() :
        play_game( )

    display_bye_message()

main()
***********************************
******** LE JEU DE NIM ********
***********************************
*         développé par : Mawe        *
***********************************


Voulez-vous faire une partie du jeu de Nim ? (o/n)
o
TODO : Le déroulement d'une partie
Voulez-vous faire une partie du jeu de Nim ? (o/n)
o
TODO : Le déroulement d'une partie
Voulez-vous faire une partie du jeu de Nim ? (o/n)
n


***********************************
    Merci d'avoir joué, à bientôt.
***********************************
Next Section - Les séquences immutables