Python aide jeu du pendu

Fermé
plopeiogyolp - Modifié le 23 nov. 2022 à 10:47
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - 23 nov. 2022 à 12:07

Bonjour,

J'essaye désespérément de coder un jeu du pendu en python, mais il ne fonctionne qu'a moitié. Jje ne comprends pas mes erreurs, il faut dire que je ne suis pas super douée.

J'apprécierais beaucoup avoir un peu d'aide

Merci beaucoup

""""""
Programme pour jouer au pendu
Auteur:Mahée
Date: 12 novembre 2022
"""

import random

mots=['voiture','ordinateur','poker','stylo','lycee','trousse','spatule', 'souris', 'menthe','seisme']


def select_random(mots):
    """choisi un mot au hasard"""
    mot_secret=random.choice(mots)
    return mot_secret


def commencer_la_partie():
    """permet de choisir un mot et d'afficher les tirets selon le nombre de lettres"""
    mot_secret=select_random(mots)
    print(mot_secret)
    longueur = len(mot_secret)
    mot_rempli=longueur*'-'
    print(mot_rempli)
    return  mot_rempli


def demande_lettre():
    """demande une lettre"""
    alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l',
        'm','n','o','p','q','r','s','t','u','v','w','x','y','z']
    majuscule = ['A','B','C','D','E','F','G','H','I','J','K','L'
        'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
    while True:
        proposition=input("Proposez une lettre : ")
        if proposition not in alphabet and proposition not in majuscule :
            print('Merci de saisir une lettre')
        else:
            break
        return proposition.lower


def verification_du_mot(mot_secret, proposition):
    """permet de savoir si la lettre est dans le mot ou non"""
    est_present = False
    emplacement_lettre = 0
    for lettre in mot_secret:
        if proposition==lettre:
            est_present = True
        emplacement_lettre += 1
    return  est_present, emplacement_lettre

def definir_compteur():
    compteur=0
    return compteur

def dessin_pendu(compteur):
    tab=[
    """
       +-------+
       |
       |
       |
       |
       |
    ==============
    """,
    """
       +-------+
       |       |
       |       O
       |
       |
       |
    ==============
    """
        ,
    """
       +-------+
       |       |
       |       O
       |       |
       |
       |
    ==============
    """,
    """
       +-------+
       |       |
       |       O
       |      -|
       |
       |
    ==============
    """,
    """
       +-------+
       |       |
       |       O
       |      -|-
       |
       |
    ==============
    """,
    """
       +-------+
       |       |
       |       O
       |      -|-
       |      |
       |
    ==============
    """,
    """
       +-------+
       |       |
       |       O
       |      -|-
       |      | |
       |
    ==============
    """
    ]
    return tab[compteur]


def verification_avec_compteur(proposition,mot_rempli,mot_secret):
    """affiche le dessin correspondant au nombre d'erreurs et dit si c'est correct ou non"""
    compteur = 0
    while mot_rempli!=mot_secret and compteur<6:
        for i in range(len(mot_secret)):
            if proposition == mot_secret[i]:
                mot_rempli = mot_rempli[:i] + proposition + mot_rempli[i+1:]#remplace la lettre dans le mot
                print('Cette lettre est correcte')
            else :
                compteur+=1
                print(dessin_pendu(compteur))
                print('Cette lettre est incorrecte')
            print(mot_rempli)
            return mot_rempli


def verification_victoire(mot_rempli):
    """savoir si la partie est gagnée ou perdue"""
    if  mot_rempli==mot_secret :
        print('Vous avez gagné la partie!')
    elif compteur == 6 :
        print ('Vous avez perdu...')

# MAIN ----------------------
def main():
    """appelle les fonctions de la partie"""
    print("""JEU DU PENDU""")
    compteur = 0
    mot_secret = select_random(mots)
    mot_rempli = commencer_la_partie()
    proposition = demande_lettre()
    est_present, emplacement_lettre=verification_du_mot(mot_secret,
    proposition)
    if est_present :
        mot_rempli = mot_rempli[:emplacement_lettre] + proposition + mot_rempli[emplacement_lettre+1:]#remplace la lettre dans le mot
        print('Cette lettre est correcte')
    else:
        compteur += 1
        print(dessin_pendu(compteur))
        print('Cette lettre est incorrecte')
    verification_victoire(mot_rempli)
    dessin_pendu(compteur)
main()

6 réponses

Tu as beaucoup de fonctions pour peu de "fonctionnalités". Tu ne dis pas ce qui ne marche pas.
Il me semble que tu te répètes pour remplacer les '-' par la bonne lettre.
Ton alphabet pourrait être une chaîne au lieu d'une liste :

alphabet = "abcdefghijklmnopqrstuvwxyz"


Utilises la méthode .lower() quand tu saisis le caractère. Ça évitera de tester les majuscules.

Que se passe-t-il si j'entre plus d'une lettre à la fois? Vérifie que ton input est de longueur 1.

Dans:

def verification_du_mot(mot_secret, proposition):

Tu auras la position de la dernière occurence. Tu fais un meilleur test ailleurs.
Tu répètes plusieurs choses. Essaies de simplifier ton algorithme et laisse le dessin de côté pour l'instant.

Algorithme simplifié:

  • Choisir le mot mystère
  • Tant que compteur < limite et mots différents:
    • Saisir lettre et valider
    • Vérifier si lettre dans mot mystère et remplacer
    • Sinon augmenter compteur.

Je te propose mon truc pour ne pas s'embêter avec le compteur :

augmenter = 1
for i in range(len(mot_secret)):
    if proposition == mot_secret[i]:
        mot_rempli = mot_rempli[:i] + proposition + mot_rempli[i+1:]
        augmenter = 0   # On n'augmentera pas.
compteur += augmenter   # On augmente seulement si on n'a pas trouvé.
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
20 nov. 2022 à 09:44

Bonjour,

Ce serait bien quand même que tu affiches ton code avec les balises

mode d'emploi:

https://codes-sources.commentcamarche.net/faq/11288-poster-un-extrait-de-code

Visuellement, ça doit ressembler à ça:

for k in range(10):
    print(k)
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
20 nov. 2022 à 16:42

Pour éviter cette longue suite de dessins pour afficher le pendu au fur et à mesure des essais, tu

pourrais faire plus court:

import colorama
colorama.init()

POS = lambda x,y: '\033[{};{}H'.format(x,y)
nb_echecs = 0
pendu = {0:[5,50,'_'], 1:[5,52,'_'], 2:[5,51,'|'], 3:[4,51,'|'], 4:[3,51,'|'], 5:[2,51,'_'], 6:[2,52,'_'],
	7:[2,53,'_'], 8:[3,52,'/'], 9:[3,54,'|'], 10:[4,54,'o']}

nb_echecs +=1 # incrémenter si la lettre n'est pas dans le mot
for i in range(nb_echecs):
	print(POS(pendu[i][0],pendu[i][1])+pendu[i][2])

Comme le pendu s'affiche à un certain endroit sur l'écran, il faut évidemment gérer aussi

la position pour afficher la question "proposer une lettre"

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168 > Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024
21 nov. 2022 à 16:36

Bah, en 45 lignes de code, ça se fait :-)

0

Comme je l'ai suggéré, il serait préférable dans un premier temps de régler le jeu lui-même.
Pas besoin de toutes ces fonctions, peut-être une pour valider l'input, mais pas vraiment plus.

Surtout que j'ai donné l'essentiel de la solution ...

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 22 nov. 2022 à 09:51

Bonjour,

C'est bien ça

45 lignes sans aucune fonction, et ça marche bien

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33433 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 décembre 2024 7 809
23 nov. 2022 à 11:29

Bonjour,

Bonjour,

Outre tous les conseils qui t'ont été donnés, tu commences ton programme par :

""""""
Programme pour jouer au pendu
Auteur:Mahée
Date: 12 novembre 2022
"""

import random

Comme le montre la coloration syntaxique, le premier problème vient d'ici, il faut écrire :

"""
Programme pour jouer au pendu
Auteur:Mahée
Date: 12 novembre 2022
"""

import random

Tu peux simplifier le code à plusieurs endroits. Par exemple la distinction minuscule / majuscule est inutile (tu peux choisir de raisonner par convention en minuscules).

def demande_lettre():
    while True:
        s = input("lettre ? ").lower()
        if len(s) == 1 and "a" <= s <= "z":
            return s

Vérifier si une lettre (et plus généralement une chaîne) apparaît dans une chaîne s'écrit :

def verification_du_mot(mot_secret, proposition):
    index = mot_secret.find(proposition)
    est_present = (index != -1)
    return (est_present, index)

Ceci dit, comme une lettre peut apparaître à plusieurs endroits dans le mot (par exemple "r" dans "ordinateur"), tu ne feras pas grand chose du premier index trouvé. Il faudrait donc soit tous les lister, soit juste retourner le résultat du test d'appartenance :

def est_dans_le_mot(mot, lettre):
    return lettre in mot

def trouver_positions(mot, lettre):
    return (i for (i, a) in enumerate(mot) if a == lettre)

print(est_dans_le_mot("ordinateur", "r")) # True
print(list(trouver_positions("ordinateur", "r"))) # [1, 9]

Concernant definir_compteur, il y a une erreur de raisonnement entre variable globales et variables locales. Ton programme travaille sans variable globale (et c'est très bien comme ça !) et du coup ta fonction est équivalente à :

def definir_compteur():
    return 0

Cette variable doit juste être déclarée et (re)initialisée dans main à chaque début de partie.

Pour vérifier si le mot est rempli, tu pourrais faire beaucoup plus simple. Il suffit de maintenir au cours de la partie les lettres proposées et de les comparer aux lettres dans le mot secret. Et du coup, quand tu veux afficher les lettres découvertes, tu te contentes d'itérer sur le mot secret et d'afficher soit la lettre courante si elle est découverte, soit - si la lettre courante n'a pas encore été découverte. Pour cela l'idéal est d'utiliser des ensembles (set en python).

def secret(mot, decouvertes):
    s = ""
    for a in mot:
        if a in decouvertes:
            s += a
        else:
            s += '-'
    return s

decouvertes = set("abcde") # {'a', 'b', 'c', 'd', 'e'}
mot = "ordinateur"
print(secret(mot, decouvertes)) # "--d--a-e--"

... ou de manière plus concise :

def secret(mot, decouvertes):
    return "".join(
        a if a in decouvertes else "-"
        for a in mot
    )

Du coup le test de condition de victoire devient :

def victoire(mot, decouvertes):
    return set(mot) == set(decouvertes)

Ensuite pour le nombre d'essai, tu peux architecturer ton programme plus simplement :

def demander_lettre():
    while True:
        s = input("lettre ? ").lower()
        if len(s) == 1 and "a" <= s <= "z":
            return s

def victoire(mot, decouvertes):
    print(set(mot), set(decouvertes))
    return set(mot) == set(decouvertes)

def pendu(mot, max_echecs):
    decouvertes = set()
    bravo = False
    nombre_echecs = 0
    essai = 0
    while True:
        essai += 1
        print(f"Essai {essai}, il vous reste {max_echecs - nombre_echecs} vies")
        a = demander_lettre()
        if a in mot:
            decouvertes.add(a)
        else:
            nombre_echecs += 1
        if nombre_echecs == max_echecs:
            print(f"Perdu, le mot était {mot}")
            break
        elif victoire(mot, decouvertes):
            print(f"Bravo, le mot était {mot}")
            break
        else:
            print(secret(mot, decouvertes))

pendu("ordinateur", 6)

Bonne chance

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
23 nov. 2022 à 12:07

Bonjour,

Sinon, en 45 lignes ça donne ça:

import os
import random
import colorama
colorama.init()

POS = lambda x,y: '\033[{};{}H'.format(x,y) #"escape sequence" pour placer le curseur sur ligne/colonne données
failures_nb, tries_nb = 0, 0
end, found = False, True
display = []
sketch = {0:[5,50,'_'], 1:[5,52,'_'], 2:[5,51,'|'], 3:[4,51,'|'], 4:[3,51,'|'], 5:[2,51,'_'], 6:[2,52,'_'],
    7:[2,53,'_'], 8:[3,52,'/'], 9:[3,54,'|'], 10:[4,54,'o']}
words = ['voiture','ordinateur','poker','stylo','lycee','trousse','spatule', 'souris', 'menthe','seisme']

print('\n***** Jeu du pendu *****\n')
word = random.choice(words)
input('''Choix  d'un mot au hasard ... appuyer sur Entrée pour continuer''')
display = ['_' for k in range(len(word))]

os.system('cls')
print('\n***** Jeu du pendu *****')
while(not end):
    print('{}{}'.format(POS(3,1),' '.join(display)))
    letter = input('\nUne lettre : ')
    tries_nb += 1
    found = False

    if(letter in word):
        found = True
        inds = [ind for ind, value in enumerate(word) if value == letter]
        for ind in inds: #if letter in word ne suffit pas: il faut traiter les occurences multiples comme 2 e dans lycee
            if(display[ind] == '_'):
                display[ind] = letter
                break

    if(not found):
        failures_nb +=1 #lettre pas dans le mot: on commence a dessiner le pendu ...
        for i in range(failures_nb): print(POS(sketch[i][0],sketch[i][1])+sketch[i][2])

        if(failures_nb == len(sketch)):
            print('''{}Perdu ! C'était {}'''.format(POS(5,1),word))
            end = True

    if(word == ''.join(display)):
        print('{}{}\n\nGagné en {} essais!'.format(POS(3,1),' '.join(display),tries_nb))
        end = True

input('\nAppuyer sur entrée ...')
0