Partage
  • Partager sur Facebook
  • Partager sur Twitter

[TP Pendu] Version Pewe31

Votre avis m'interresse

Sujet résolu
    23 février 2016 à 18:37:48

    Bonjour!

    Voila quelques semaines que je me suis mis au Python sur openclassroom (avec grand plaisir je dois le dire!) et j'aurais aimé avoir votre avis sur ma version du TP sur le jeu de pendu! Ce que j'aimerais savoir c'est si il y'a des choses a ne pas faire dans ce que j'ai fais.

    Normalement, il fonctionne bien.

    Pour rappel, il utilise un fichier scores pour stocker les scores, un fichier liste_mots.txt (ou autre nom, a configurer dans le fichier de données).

    Voici les fichiers associés (y'a de la lecture...logiquement chaque ligne est commentée):

    donnees.py, contient les variable modifiables du programme:

    # -*-coding:Utf-8 -*
    """Ce fichier va contenir toutes les variables dont on a besoin dans notre programme"""
    
    # options
    nomjoueur = "Joueur1"
    score1=0
    chances = 8
    
    # Liste de mots à decouvrir
    fichier_liste_mots="./liste_mots.txt"
    
    
    

    fonctions.py, contient toutes le fonctions:

    # -*-coding:Utf-8 -*
    """ ce fichier contien toutes les fonctions nécessair au pendu"""
    
    # Chargement des modules nécessaires
    import os
    import pickle
    from random import randrange
    
    def loadscores():
    	"""Fonction de chargement des scores depuis un fichier "scores" dans le même dossier"""
    	
    	# On test l'ouverture
    	try:
    		# ouverture avec with du fichier  "scores" se trouvant dans le même dossier, en lecture seul et en mode binaire
    		with open('./scores', 'rb') as fichier:
    			# on utilise le module pickle pour recuperer le contenu du fichier
    			mon_depickler = pickle.Unpickler(fichier)
    			score_recupere = mon_depickler.load()
    	except FileNotFoundError:
    		# si le fichier n'existe pas, on renvoie un dictionnaire vide
    		score_recupere=dict()
    		# Mais on n'interomp pas le programme!
    		pass
    	finally:
    		# quoi qu'il se passe, on renvoie le dictionnaire avec les scores
    		return score_recupere
    
    def monmenu(titre,*chois_possibles):
    	"""Cette fonction va nous permettre d'afficher un menu et de retourner le chois.
    	Il prendra en parametre les options possibles qui doivent être des chaines de char
    	Le premier parametre est toujour le titre du menu
    	
    	"""
    	# On recupere le nombre de chois en verifiant la taille de la liste chois_possibles)
    	maxchois=len(chois_possibles)
    	# On initialise chois comme une chaine non spécifié
    	chois=str()
    	# tant que chois est une chaine
    	while type(chois) is str:
    		# on affiche le titre du menu
    		print(titre)
    		# pour chaque chois possible
    		for id,options in enumerate(chois_possibles):
    			# on affiche le numero du chois (id+1) et le chois
    			print("{}- {}".format(id+1,options))
    		# On saisi le chois en precisant les limite de la saisie
    		chois=input("Votre chois? (veuillez saisir un chiffre entre 1 et {})\n".format(maxchois))
    		# on s'assure que le chois sera un int
    		try:
    			# on essai de convertir chois en int
    			chois = int(chois)
    			# Naturellement, chois est bien dans les limites fixés
    			assert (chois >= 1) and (chois <= maxchois)
    		except ValueError:
    			# Si le joueur n'a pas saisi un numero, on le lui signale
    			print ("\nVous devez saisir un nombre! Vous avez saisi {}!\n".format(chois))
    			# on reinitialise chois comme une chaine non specifie
    			chois=str()
    			# on continue
    			pass
    		except AssertionError:
    			# si le chois n'est pas compri dans la plage accepté, on le signale en reprecisant les limites
    			print ("\nVous devez entrez une valeur entre 1 et {}! Vous avez saisi {}\n".format(maxchois, chois))
    			# on reinitialise chois comme une chaine non specifie
    			chois=str()
    			# on continue
    			pass
    	# On precise bien le chois fait
    	print("\nVous avez choisi {}.".format(chois_possibles[chois-1]))
    	return chois
    
    def mot_cache(fichier_liste_path):
    	"""fonction chargeant la liste des mots depuis un fichier.
    	un mot est tiré au hasard et retourné
    	"""
    	# On va verifier que le fichier existe
    	try:
    		# On va ouvrir le fichier avec with en mode texte et en lecture
    		with open(fichier_liste_path, 'r') as fichierliste:
    			listestr = fichierliste.read()
    		# convertion pour avoir une liste	
    		myliste=listestr.split("\n")
    		# recuperation de la longueur de la liste
    		longueur_listemots=len(myliste)
    		# selection au hasard du mot a devine et mise en majuscule
    		mot=myliste[randrange(0,longueur_listemots)].upper()
    	except FileNotFoundError:
    		# Dans le cas ou le fichier de mot n'existerai pas, on le signale et on explique le type et le contenu attendu
    		print("Le fichier {} n'exite pas! veuillez le créer (fichier texte .txt avec un mot par ligne)!".format(fichier_liste_path)
    		# On signale que l'on va definir un mot par defaut
    		print("Le mot ABCDE sera a deviner par défaut!")
    		# On defini un mot par defaut
    		mot="ABCDE"
    	finally:
    		# quoi qu'il se passe on renvoie un mot a deviner
    		return mot	
    
    def affiche_pendu(nbr_actuel):
    	"""Fonction d'affichage du pendu"""
    	# La premiere liste contien toutes les lignes possibles
    	imgs_pendu=[
    		"\n",
    		"_____________\n",
    		" | /       |\n",
    		" |/        0\n",
    		" |        -|-\n",
    		" |         /\\\n",
    		" |\n",
    		"_|____________\n"
    		]
    	# La deuxieme liste contiens une chaine de caractere avec toutes les image possibles sous formes d'index dans la liste précedente
    	matrice_image=[
    		"1,2,3,4,5,6,7",
    		"1,2,3,4,6,6,7",
    		"1,2,3,6,6,6,7",
    		"0,2,3,6,6,6,7",
    		"0,0,3,6,6,6,7",
    		"0,0,0,6,6,6,7",
    		"0,0,0,0,6,6,7",
    		"0,0,0,0,0,6,7",
    		"0,0,0,0,0,0,7"
    		]
    	# On crée une leiste des lignes a afficher
    	aafficher = matrice_image[nbr_actuel].split(",")
    	# On converti le conten de la liste en entiers
    	for index,entre in enumerate(aafficher):
    		aafficher[index]=int(entre)
    	# On affiche
    	for ligne in aafficher:
    		print(imgs_pendu[ligne])
    
    def saisi_lettre():
    	"""Saisi de lettre plus ou moins securise"""
    	# Tant que l'on n'a pas 1 et 1 seule lettre ou "!"
    	lettre_ko=True
    	while lettre_ko:
    		# on va s'assurer que c'est bien une lettre
    		try:
    			# on demande la saisie d'une lettre ou de "!"
    			lettre_tmp=input("Veuillez saisir une lettre ou ! si vous avez trouvé le mot:")
    			# Si ce n'est pas une lettre ou "!" et si il y a plus de 1 caractère, on leve une exception
    			assert ((lettre_tmp.isalpha() or lettre_tmp=="!") and len(lettre_tmp)==1)
    			# sinon on continue
    			lettre_ko=False
    		except AssertionError:
    			# Si il y'a un problème avec la saisi on explique pourquoi et on redemande de saisir la lettre
    			print("Vous savez saisi {}!".format(lettre_tmp))
    			print("Vous devez saisir une (et une seule!) lettre alphabetique ou ! pour entrer le mot complet.")
    			lettre_ko=True
    	# on renvoir la lettre ou "!"
    	return lettre_tmp.upper()	
    
    def updatescores(joueur,score,listescores):
    	"""met a jour ou crée le fichier de score"""
    	# on ajoute l'entrée au dictionnaire
    	listescores[joueur]=score
    	try:
    		# on recrée le fichier de score avec la nouvelle table
    		with open('./scores', 'wb') as fichier:
    			mon_pickler = pickle.Pickler(fichier)
    			mon_pickler.dump(listescores)
    	except PermissionError:
    		# Si jamais on ne dispose pas des permissions pour créer un fichier on le signale!
    		print("Vous n'avez pas la permission d'ecrire dans le répertoire où est installé le jeu!\n")
    		print("Merci d'executer le jeu avec les permissions nécessaire ou de l'insatller dans un autre répertoire!")
    		input("Appuyez sur ENTREE pour continuer.")
    	# on retourne la liste des scores mise à jour
    	return listescores
    	
    def affichescores(mondictionnaire):
    	"""Fonctionaffichant les scores"""
    	# Un titre bien fomaté
    	print("\nVoici le palmares:\n".upper().center(30))
    	# On essaye d'afficher un dictionnaire non vide avec un certain format
    	try:
    		assert (type(mondictionnaire) is dict) and (len(mondictionnaire) > 0)
    		# on crée une liste vide
    		myliste=list()
    		# On la rempli avec des tuples clé,value
    		for montuple in mondictionnaire.items():
    			myliste.append(montuple)
    		# On inverse l'ordre des tuples pour le trie
    		myliste_reversed=[(score,joueur) for joueur,score in myliste]
    		myliste_reversed_trie=sorted(myliste_reversed,reverse=True)
    		# On affiche proprepement avec le classement
    		for classement,joueur in enumerate(myliste_reversed_trie[:10]):
    			print("{}- {}........:{}".format(classement+1,joueur[1],joueur[0]))
    		print("\n")
    	except AssertionError:
    		# si jamais pas de score on laisse tombé l'affichage!
    		print("Pas de scores disponible\n")
    
    def change_de_nom():
    	"""fonction pour changer de nom de joueur"""
    	nom_ko=True
    	while nom_ko:
    		print("Veuiller entrer un nom de 3 a 10 lettres ou chiffres.")
    		nom=input("Votre nom?")
    		if nom.isalnum():
    			nom_ko=False
    		else:
    			print("Entrée {} incorrecte!Chiffres ou lettres seulement!".format(nom))
    	return nom
    
    

    et pendu.py, le fichier main a executer:

    # -*-coding:Utf-8 -*
    
    # modules
    import os
    from fonctions import *
    from donnees import *
    # Main
    #Variable de fonctionnements
    continuer = True
    # On recupere le nom de joueur par defaut
    joueurpardefault=nomjoueur
    # On charge les scores enregistrés
    scoreslist=loadscores()
    # On rentre dans la boucle pour maintenir le jeu tant que continuer est vrai
    while continuer:
    	# blabla mis en forme
    	print("Bienvenu dans le jeu de pendu!".upper().center(40))
    	# Affichage du nom du joueur et de son score (Joueur1 par defaut et 0 points, voir fichier donnees.py)
    	print("Joueur: {}, Score actuel: {}\n".format(nomjoueur,score1))
    	# joueurpardefault (Joueur1) ne peu enregistrer de score car c'est le joueur par defaut
    	if nomjoueur == joueurpardefault:
    		print("Si vous voulez garder votre score, merci de changer de nom de joueur!\n")
    	# On appel le menu avec le titre en 1er parametre et les chois ensuites
    	action=monmenu("Que voulez-vous faire?","jouer!","Afficher les scores","Changer nom du joueur","quiter")
    	# traitement du chois
    	if action==1:
    		# on joue!
    		# definition du mot a trouvé depuis une liste dans un fichier
    		mot=mot_cache(fichier_liste_mots)
    		# On va utiliser une variable contenant le mot a trouver qui va s'effacer au fur et a mesure du jeu
    		mot_atrouver=mot
    		# On recuperer la longueur du mot a trouver
    		longueur_mot=len(mot_atrouver)
    		# initialisation de variables
    		i=0
    		mot_encour=""
    		# la variable mot_encour sera affiché et sera modifié a chaque lettre trouvé.
    		while i < longueur_mot:
    			# au debut la variable sera rempli de "_", le nombre dependant du nombre de lettre du mot a trouver
    			mot_encour+="_"
    			i+=1
    		# On va definir le nombre d'essai possibles
    		essais_restant=chances
    		# tant qu'il reste des essais
    		while essais_restant > 0:
    			# on affiche le nombre d'essais restant
    			print("Il vous reste {} essais.\n".format(essais_restant))
    			# on affiche le petit dessin
    			affiche_pendu(essais_restant)
    			# On signale le nombre de lettre dans le mot
    			print("Mot de {} lettres".format(longueur_mot))
    			# on affiche ce qui a été trouvé et le "_" sur les lettres a deviner
    			print(mot_encour)
    			# on demande la saisi d'une lettre ou de "!" si on a deviné le mot et que l'on veu le saisir
    			lettre=saisi_lettre()
    			 # Si la lettre est un "!"
    			if lettre == "!":
    				# on demande la saisi du mot
    				tentative=input("Vous pensez a quel mot?")
    				# on test le mot
    				if tentative.upper() == mot:
    					# on met mot_encour a mot si c'est bon
    					mot_encour = mot
    				else:
    					# Sinon c'est raté
    					print("Non, ce n'est pas {}!".format(tentative.upper()))
    			else:
    				# Si on a juste saisi une lettre, on la cherche dans le mot secret
    				result=mot_atrouver.find(lettre)
    				# On initialise le compteur
    				nombre_delettre=0
    				# tant que l'on trouve la lettre (la methode find renvoi -1 si elle ne trouve pas le caractere)
    				while result!=-1:
    					# on retire la lettre du mot a trouvé 1 fois
    					mot_atrouver=mot_atrouver.replace(lettre,"_",1)
    					# on met a jour le mot_encour pour afficher la lettre trouvé
    					mot_encour=mot_encour[0:result]+lettre+mot_encour[result+1:]
    					# on increment le nombre de lettre trouvées
    					nombre_delettre+=1
    					# on cherche a nouveau la lettre des fois qu'elle y soit encore
    					result=mot_atrouver.find(lettre)
    				# on affiche le nombre de fois et la lettre enquestion
    				print("Il y a {} {}!".format(nombre_delettre,lettre))
    			# On diminue le nombre d'essaies dsiponibles
    			essais_restant-=1
    			# si jamais il n'y a plus de "_" dans le mot_encour
    			if mot_encour.find("_")==-1:
    				# on a trouvé le mot, donc feliceitation, recap du nombre de coup restant (le nombre de points gagnés)
    				print("\nFellicitation! vous avez trouvé le mot {} en {} essais!\n".format(mot_encour,chances-essais_restant))
    				# update du score du joueur
    				score1+=essais_restant
    				# mise a 0 du nombre d'essais pour sortir de la boucle
    				essais_restant=0
    			elif essais_restant==0:
    				# si il n'y a plus d'essais disponibles, on affiche le mot a trouver et le pendu complet
    				print("\nvous avez perdu!Le mot était {}!\n".format(mot))
    				affiche_pendu(essais_restant)
    		# Si le joueur n'a pas changé de nom
    		if nomjoueur == joueurpardefault:
    			# on ne peu pas enregistrer, le score est ramené à 0
    			print("Joueur1 ne peu enregistrer son score, merci de changer de nom!")
    			score1=0
    		else:
    			# sinon, on enregistre le score mis a jour
    			scoreslist=updatescores(nomjoueur,score1,scoreslist)
    	elif action==2:
    		# Si on choisi d'afficher les scores, on appel la fonction qui va bien
    		affichescores(scoreslist)
    	elif action==3:
    		# Si on choisi de changer de nom, on appel la fonction qui va bien
    		nomjoueur=change_de_nom()
    		# on recupere le précedent score pour mettre a jour le score actuel!
    		score1=scoreslist.get(nomjoueur,0)
    	else:
    		# Sinon, on a choisi de quiter!
    		print("\n Au revoir et a bientôt!\n")
    		continuer=False
    


    Par avance merci!


    • Partager sur Facebook
    • Partager sur Twitter
      23 février 2016 à 19:41:00

      C'est choix et non chois ;).

      Sinon je trouve que ton code est BEAUCOUP BEAUCOUP trop commenté (pratiquement 1 commentaire pas ligne).

      • Au lieu de: while type(chois) is str c'est mieux de faire: while isinstance(choix, str).
      • enumerate accepte un second argument (l'indice de début):
      for id, options in enumerate(chois_possibles, 1):
          print("{}- {}".format(id,options))


      Après j'ai du mal à prendre du recul, mais ça me paraît être un code relativement long pour un pendu, et la gestion des erreurs me paraît un peu excessif. Par exemple dans la fonction saisie_lettre, je trouve un peu violent l'utilisation d'un try/except/assert. Le code suivant me paraît suffisant:

      lettres = "abcdefghijklmnopqrstuvwxyz!"
      
      choix = input("lettre ou ! si vous avez trouvé: ").lower()
      while choix not in lettres or len(choix) != 1:
          choix = input("1 SEULE LETTRE ou ! si vous avez trouvé: ").lower()

      -
      Edité par Olygrim 23 février 2016 à 19:41:53

      • Partager sur Facebook
      • Partager sur Twitter
      Précepte: Le mieux est l'ennemi du bien
        26 février 2016 à 15:14:27

        Super, merci pour tes commentaires! :)

        Effectivement, j'ai un peu fais n'imp avec les assert...

        Je ne reposte pas mon code, mais je met a jour(même si c'est juste pour l'exercice!)

        • Partager sur Facebook
        • Partager sur Twitter

        [TP Pendu] Version Pewe31

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown