La sérialisation
PROBLÉMATIQUE
Je souhaiterais ajouter à mon jeu, un tableau des 5 meilleurs scores et pour faire cela rien de tel que d'utiliser la sérialisation des données qui me permettront de rendre persistant mes scores dans le temps.
Le principe est simple, vous avez une variable python (une liste par exemple) et voulez là garder en mémoire pour là réutiliser plus tard (par exemple au redémarrage du jeu)
Quels outils utiliser avec le langage Python ?
Un seul, on va utiliser le module pickle...
Nous utiliserons le protocole 4, le dernier mise à jour et optimisé pour la version python (>= 3.4)
Création de nos joueurs
Pour avoir un tableau de scores, il nous faut des joueurs et leur score. Pour cela on va créer une liste de scores dont les noms des joueurs sont inconnus et les scores sont nuls.
Code:
from collections import namedtuple PLAYER_MAX = 5 Player = namedtuple('Player', ['name', 'score']) def PlayersInit(): players = [] for i in range(PLAYER_MAX): p = Player(name='', score=0) # initialisation des joueurs au score 0 players.append(p) return players
Ne vous inquiétez pas trop si vous ne connaissez pas, c'est plus pour vous donner une idée de conception si vous voulez fabriquer un tableau de scores, mais l'enjeu ici est d'expliquer comment sauvegarder et réutiliser ce tableau plus tard, lors d'un redémarrage du jeu par exemple...
Ajout d'un nom de joueur et son score
C'est une mise à jour du tableau, je vais l'appeler update !
Code:
def update(listPlayers, me): ''' listPlayers est la liste des joueurs enregistrée me est un joueur, donc un objet de type Player ''' for idx, player in enumerate(listPlayers): n, s = player.name, player.score if me.score > s: # si mon score dépasse l'ancien newList = [] # création de la liste updatée rightList = listPlayers[idx:] del rightList[-1] # suppression du dernier score à droite leftList = listPlayers[:idx] # récup des scores avant le score courant newList.extend(leftList) # ajout scores avant score courant newList.append(me) # ajout score courant newList.extend(rightList) # ajout scores après score courant listPlayers = newList[:] # copie dans listPlayers break # on quitte la boucle return listPlayers
Création de nouveaux joueurs
Bon là j'ai pas cherché loin, j'ai ajouté 3 joueurs
Code:
Fred = Player(name='Fred', score=50) # Création d'un joueur + score pour test Dreamus = Player(name='Dreamus', score=35) Sakarov = Player(name='Sakarov', score=40)
Enregistrement dans le tableau
Code:
listPlayers = update(listPlayers, Fred) # Mise à jour du tableau de scores listPlayers = update(listPlayers, Dreamus) listPlayers = update(listPlayers, Sakarov) # on va voir si ça se met bien dans l'ordre décroissant
Oui vous le souhaitiez tellement fort que j'ai dû éviter des détails lors de l'écriture de ce tutoriel.
On va utiliser le module pickle et ouvrir un fichier, s'il n'existe pas, le fichier sera créé automatiquement.
Le principe ici, est la sauvegarde !
Code:
import pickle # ... suite du code def save(path): ''' path est le chemin du fichier ''' with open(path, "wb") as f: # création + ouverture du fichier en mode binaire pickle.dump(listPlayers, f, 4) # sauvegarde de l'objet listPlayers dans le fichier f
Non mais tu déconnes Fred, ça peut pas être aussi simple ? Eh bien si, rien de plus simple, on vient de sauvegarder dans le fichier avec le chemin absolu path, le tableau de scores...
Ce qui rend le fichier très moche à lire
fichier.jpg
C'est bien si vous avez des mots de passe à enregistrer, mieux vaut que ça ne soit pas lisibles, n'est-ce pas ?
C'est bien beau mais je fais quoi avec ce fichier maintenant ? On y arrive !
Chargement du tableau de scores au démarrage du jeu
Rien de compliquer, regardez !
Code:
def load(path): ''' path est le chemin du fichier ''' var = None if os.path.exists(path): # Si le chemin existe try: with open(path, 'rb') as f: # on essaye d'ouvrir le fichier var = pickle.load(f) # on charge notre liste dans la variable var except: pass # Sinon on fait rien, la valeur de var vaut None return var
Je l'appelle simplement de cette manière
Code:
listPlayers = load(".../sauvegarde.txt") # chargement des scores
Pour faire beau, niveau affichage, nous allons créer une forme joueur -> score
Code:
def displayScores(): pattern = "{name} -> {score}" # format de l'affichage for player in listPlayers: name, score = player if name: # S'il y a un nom print(pattern.format(name=name, score=score)) # on affiche le score
Le code en entier
Voilà c'est terminé, le code en entier vous permettra de tester et vérifier, n'hésitez pas à me prévenir si vous voyez des erreurs
Code:
from collections import namedtuple import pickle import os.path PLAYER_MAX = 5 Player = namedtuple('Player', ['name', 'score']) def PlayersInit(): players = [] for i in range(PLAYER_MAX): p = Player(name='', score=0) # initialisation des joueurs au score 0 players.append(p) return players def update(listPlayers, me): ''' listPlayers est la liste des objets Player enregistrée me est un joueur, donc un objet de type Player ''' for idx, player in enumerate(listPlayers): n, s = player.name, player.score if me.score > s: # si mon score dépasse l'ancien newList = [] # création de la liste updatée rightList = listPlayers[idx:] del rightList[-1] # suppression du dernier score à droite leftList = listPlayers[:idx] # récup des scores avant le score courant newList.extend(leftList) # ajout scores avant score courant newList.append(me) # ajout score courant newList.extend(rightList) # ajout scores après score courant listPlayers = newList[:] # copie dans listPlayers break # on quitte la boucle return listPlayers def save(path): ''' path est le chemin du fichier ''' with open(path, "wb") as f: # création + ouverture du fichier en mode binaire pickle.dump(listPlayers, f, 4) # sauvegarde de l'objet listPlayers dans le fichier f def load(path): ''' path est le chemin du fichier ''' var = None if os.path.exists(path): # Si le chemin existe try: with open(path, 'rb') as f: # on essaye d'ouvrir le fichier var = pickle.load(f) # on charge notre liste dans la variable var except: pass # Sinon on fait rien, la valeur de var vaut None return var def displayScores(): pattern = "{name} -> {score}" # format de l'affichage for player in listPlayers: name, score = player if name: # S'il y a un nom print(pattern.format(name=name, score=score)) # on affiche le score listPlayers = PlayersInit() # Initialisation du tableau de scores # Ajout des nouveaux scores # ------------------------- Fred = Player(name='Fred', score=50) # Création d'un joueur + score pour test Dreamus = Player(name='Dreamus', score=35) Sakarov = Player(name='Sakarov', score=40) listPlayers = update(listPlayers, Fred) # Mise à jour du tableau de scores listPlayers = update(listPlayers, Dreamus) listPlayers = update(listPlayers, Sakarov) # on va voir si ça se met bien dans l'ordre décroissant save("/home/fred1599/Bureau/sauvegarde.txt") # sauvegarde des scores listPlayers = load("/home/fred1599/Bureau/sauvegarde.txt") # chargement des scores print(listPlayers) # Affichage de la liste des scores # [Player(name='Fred', score=50), Player(name='Sakarov', score=40), Player(name='Dreamus', score=35), Player(name='', score=0), Player(name='', score=0)] displayScores() # bel affichage des scores # Fred -> 50 # Sakarov -> 40 # Dreamus -> 35
Commentaire