Découpage en modules
Une première étape dans l’avancement de notre TP va être de le découper en modules.
En effet, nous l’avons précédemment découpé en fonctions, mais ces fonctions cohabitent toutes ensemble dans un joyeux bordel.
Nous pouvons donc aller plus loin et réunir ces fonctions en unités logiques dans un paquet.
Je vous propose pour cela un paquet tp
contenant des modules pour les différentes parties de notre jeu : définitions des données, gestion des joueurs, gestion des entrées utilisateur.
On gardera aussi un module game
pour les fonctions principales du jeu.
Solution
Un découpage possible est le suivant.
J’ai utilisé un module definitions
pour stocker les dictionnaires monsters
et attacks
.
Ce module est assimilable à une base de données, il n’y a que lui à faire évoluer pour ajouter de nouveaux monstres ou de nouvelles attaques.
En plus de ça, un module prompt
reprend la fonction get_choice_input
et un module get_players
est dédié à l’instanciation des joueurs.
J’ai aussi ajouté un fichier __main__.py
pour exécuter notre TP avec python -m tp
.
Comme vous le voyez, j’ai ici laissé un fichier __init__.py
vide car il ne nous est pas utile.
Sauvegarde
Venons-en maintenant à l’objectif de ce TP : la sauvegarde du jeu.
On pourra pour cela ajouter un fichier save.py
à notre paquet contenant une fonction load_game(filename)
pour charger une sauvegarde depuis un fichier, renvoyant les deux joueurs ainsi chargés, et une fonction save_game(filename, player1, player2)
pour enregistrer la sauvegarde (l’état des deux joueurs) dans un fichier.
Dans la boucle principale de notre jeu, on ajoutera donc une question pour demander à l’utilisateur s’il souhaite continuer ou s’arrêter. En cas d’arrêt, on lui demandera alors s’il souhaite sauvegarder la partie et dans quel fichier.
% python -m tp
Monstres disponibles :
- Pythachu
- Pythard
- Ponytha
Joueur 1 quel monstre choisissez-vous ?
> Pythachu
Quel est son nombre de PV ? 100
Joueur 2 quel monstre choisissez-vous ?
> Ponytha
Quel est son nombre de PV ? 120
Pythachu affronte Ponytha
Voulez-vous continuer ? [O/n] o
Joueur 1 quelle attaque utilisez-vous ?
- Tonnerre -50 PV
- Charge -20 PV
> tonnerre
Pythachu attaque Ponytha qui perd 50 PV, il lui en reste 70
Joueur 2 quelle attaque utilisez-vous ?
- Brûlure -40 PV
- Charge -20 PV
> brûlure
Ponytha attaque Pythachu qui perd 40 PV, il lui en reste 60
Voulez-vous continuer ? [O/n] n
Voulez-vous sauvegarder ? [o/N] o
Dans quel fichier sauvegarder ? game.dat
Dans l’autre sens, on permettra au programme de prendre un argument pour charger le jeu depuis la sauvegarde pointée par ce fichier.
% python -m tp game.dat
Pythachu affronte Ponytha
Voulez-vous continuer ? [O/n]
Joueur 1 quelle attaque utilisez-vous ?
- Tonnerre -50 PV
- Charge -20 PV
> tonnerre
Pythachu attaque Ponytha qui perd 50 PV, il lui en reste 20
[...]
On privilégiera le format JSON pour le fichier de sauvegarde.
Solution
Voici maintenant la solution à cet exercice, qui repose principalement sur le fichier tp/save.py
, dont les fonctions sont appelées dans le module game
.
On peut voir aussi la fonction get_yesno_input
dans le module prompt
.
C’est une fonction qui permet de poser une question qui attend pour réponse oui ou non ([O/n]
).
Elle propose aussi de définir une valeur par défaut, reconnaissable à la lettre en majuscule (O
ici pour Oui
).
Ainsi si l’utilisateur entre une ligne vide, c’est cette valeur par défaut qui sera utilisée.
Tests
Maintenant que l’on a un paquet dédié à notre TP, il va être plus simple de le tester depuis l’extérieur.
On va pouvoir déplacer nos tests dans un fichier test_tp.py
à l’extérieur du paquet.
Depuis ce fichier, on importera les différentes fonctions que l’on souhaite tester.
À notre module, on va ajouter des fonctions pour tester nos fonctions de sauvegarde. Vérifier qu’une sauvegarde se fait correctement vers le fichier et qu’il est possible d’en charger une ensuite.
Solution
Retrouvez maintenant ci-dessous la solution que je propose pour ce TP.
On remarque qu’après l’exécution de nos tests, un fichier test_game.dat
persiste dans le répertoire courant.
Ce n’est pas très grave pour l’instant mais ce n’est pas très propre non plus.
Il existe une manière d’éviter cela à l’aide du module tempfile
de la bibliothèque standard pour créer un fichier temporaire.