Page 1 of 1

[Python3] Le Pendu

Unread postPosted: 25 Aug 2015, 19:28
by alan2010
pendu.py
J'ai développé un petit programme de jeu de Pendu en Python 3... voué à être étoffé...

Mais en fait le "cœur" du programme ne marche pas: testez-le et vous verrez de quoi je parle...
Je pense que l'erreur se trouve probablement parmi ces lignes (indices):
Code: Select all
for i in range(0, len(motATrouver)):
            if  motATrouver[i]==lettre:
                debut=motActuel[0:(i-1)]
                fin=motActuel[i:len(motActuel)]
                if i==0:
                    motActuel=lettre+motActuel[1, len(motActuel)]
                else:
                    motActuel=debut+lettre+fin
                nbOcc+=1


Autre problème: Avec mon système d'exceptions, lorsque l'utilisateur fait une fausse entrée, le programme s'arrête. Ce ne serait peut-être pas le cas avezc Break ou Continue (retour au début de la boucle, ce qui est plus logique)?

Je fournis évidemment en pièce jointe le fichier .py complet

Quelques remarques:
- Oui, c'est artisanal :)
- Ce programme n'est que la "base": il est voué à être étoffé... Je pense notamment à la création d'une IA pour des matchs Humain vs. Ordinateur, avec différents niveaux (du hasard à la sélection des lettres en fonction de leur occurrence moyenne dans la langue française, mais pas de recours à une BDD, pour moi, c'est un peu triché...)
- La sauvegarde à chaque fois du dictionnaire lors de l'entrée par les joueurs pour alimenter la sélection aléatoire du mot
- Les meilleurs scores
- Peut-être développer une petite interface graphique avec Tkinter ou Qt-Designer (au passage, avec le second, je n'ai pas compris comment obtenir un ficher .py et des méthodes à la fin...)
- Si vous avez d'autres idées d'amélioration, n'hésitez pas!

J'attends donc un petit déblocage pour partir sur une base qui marche :)

alan2010

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 10:08
by Bisam
Tu as un décalage d'indices.
La tranche mot[a:b] correspond aux lettres numérotées de a à b-1.
Par défaut, a vaut 0 et b vaut len(mot)... donc tu peux les omettre.

Ainsi, ton code devient :
Code: Select all
for i in range(len(motATrouver)):
    if  motATrouver[i] == lettre:
        motActuel = motActuel[:i] + lettre + motActuel[i+1:]
        nbOcc+=1


Par ailleurs, pense à utiliser les dictionnaires pour simplifier ton code.
Notamment, ils seraient bien utiles pour savoir si une lettre a déjà été jouée.

Enfin, pour ce qui est de la présentation du code et des bonnes pratiques à acquérir, je te conseille d'aller lire CECI.

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 10:25
by alan2010
Merci de votre aide, je vais tester si ça marche...

Au fait, vous l'avez testé?

Sinon, avez-vous d'autres idées d'amélioration, et que pensez-vous de mon code?



Edit: Malheureusement, ça ne semble pas fonctionner...

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 10:41
by Bisam
Pardon, j'ai oublié de décaler à droite... C'est corrigé ci-dessus.

Pour d'autres améliorations, par exemple, tu peux remplacer :
Code: Select all
if ord(lettre)<65 or ord(lettre)>90:

par
Code: Select all
if lettre < 'A' or lettre > 'Z':

C'est plus lisible !

Par ailleurs, il y a plein de cas non gérés... en particulier, il se produit une erreur quand on tape "STOP" pour arrêter, et le jeu ne s'arrête pas quand on a trouvé le mot.

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 10:43
by alan2010
Merci beaucoup, ça fonctionne maintenant!!

Par contre, le programme redemande des lettres une fois le mot trouvé...

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 13:28
by Bisam
C'est loin d'être le seul problème...
- Le programme oublie de changer de joueur car l'incrémentation ne se fait pas au bon endroit
- Il oublie de quitter quand on a gagné
- Si une lettre a déjà été jouée, on compte quand même le coup au lieu de redemander une lettre (peut-être est-ce voulu ?)

Mais surtout, le gros problème, c'est que tu devrais utiliser des fonctions pour chaque petit bout de ton programme. Par exemple, une pour l'affichage du pendu, une pour tester si la lettre a déjà été jouée, une pour tester si la lettre est présent dans le mot à trouver, etc.

Cela permet de modifier des morceaux de ton code sans risquer de compromettre le reste et en plus cela améliore la lisibilité.

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 19:24
by alan2010
Je publie en pièce jointe la nouvelle version du programme, qui fonctionne correctement.
- Il est désormais possible d'enchaîner plusieurs parties :)
- L'alternance de rôles des deux joueurs est désormais gérée :D
- En cas d'erreur de saisie, le programme re-demande une saisie et ne se termine plus brutalement, ce qui permet de poursuivre la partie en cours :p


... en l'attente d"améliorations futures...

Re: [Python3] Le Pendu

Unread postPosted: 26 Aug 2015, 20:18
by Bisam
Tu n'as pas suivi mon conseil de faire des fonctions !
En plus des avantages déjà cités, cela permet la "factorisation" de code : un code qui est répété plusieurs fois n'est écrit qu'une seule fois.

Par exemple, tu testes à 3 endroits différents si une lettre est bien comprise entre 'A' et 'Z'...
Si tu en fais une fonction, tu n'as plus qu'une seule fois à l'écrire.
Mais surtout, s'il te prend l'envie d'améliorer en acceptant aussi les lettres minuscules, il n'y a qu'un seul endroit à modifier !

De même, tu pourrais faire une fonction qui prend comme argument le numéro du gagnant et renvoie la bonne phrase en fonction de ce numéro, en utilisant une liste à 2 éléments (ou mieux, un tuple...) pour enregistrer les noms des joueurs plutôt que 2 variables.

En gros, ton code devrait ressembler à ça :
Code: Select all
nb_joueurs = message_accueil()
noms = demande_noms(nb_joueurs)
motsAtrouver = fabrique_mot(nb_joueurs)
jeu_fini = False
joueur = 1
motActuel = "-" * len(motAtrouver)
pendu = 0
lettres_jouees = {}
while not jeu_fini:
    motAtrouver = motsAtrouver[joueur]
    affiche(motActuel, pendu)
    lettre = demande_lettre(joueur)
    motActuel = teste_lettre(lettre, motAtrouver, motActuel)
    if motActuel == motAtrouver:
        jeu_fini = True
    elif nb_joueurs != 1:
        joueur = joueur_suivant(joueur)


def message_accueil():
    """Message d'accueil et demande du nombre de joueurs"""
    return nb


def demande_noms(nb):
    """Demande le nom de chaque joueur"""
    names = []
    for i in range(nb):
        names.append(input("Nom du joueur" + str(i) + " : ")
   return names


def fabrique_mot(nb):
    if nb == 1:
        """Choix d'un mot au hasard"""
    else:
        """On demande un mot à chaque joueur"""
        mots = []
        for joueur in range(nb):
            mots.append(demande_mot(joueur))
    return mots


def affiche(mot, p):
    """Affiche le mot actuel et l'état du pendu"""
   ...


def demande_lettre(j):
    """Demande une lettre au joueur j"""
   lettre = "." #mettre une lettre non valide
   while not est_valide(lettre):
       ...
   return lettre


def est_valide(lettre):
    """Teste si la lettre vérifie certaines conditions"""
   return (lettre >= 'A' and lettre <= 'Z') or (lettre >= 'a' and lettre <= 'z')


def teste_lettre(lettre, motAtrouver, motActuel):
    """Teste si la lettre existe dans le mot à trouver et modifie le mot actuel si c'est le cas."""
    nouveau_mot = motActuel
    ...
   return nouveau_mot


def joueur_suivant(joueur):
    """Renvoie le numéro du joueur suivant"""
    ...
    return j