Partage
  • Partager sur Facebook
  • Partager sur Twitter

J'aimerais "figer" la fonction readline()

Sujet résolu
    21 mai 2015 à 2:40:49

    Bonjour bonjour,

    C'est un problème de logique.
    J'ai écrit un programme méga-simple en Python :

    • Le programme lit la première ligne d'un fichier "questions.txt", grâce à la fonction readline().
    • Le programme lit la première ligne d'un fichier "réponses_attendues.txt", grâce à la fonction readline().
    • Le programme affiche la question 1
    • L'utilisateur entre la réponse 1.
    • Le programme compare la réponse entrée et la réponse attendue
    • SI la réponse entrée et la réponse attendue correspondent
              > on affiche une question 2
    • Ainsi de suite.


    Le problème c'est que, comme je me sers de la fonction readline() pour déterminer la variable "reponse_attendue", quand l'utilisateur appuie sur le bouton Valider, la réponse attendue change, que l'utilisateur ait bien répondu ou pas à la question précédente.

    Et moi, je voudrais qu'elle ne change pas tant que l'utilisateur n'a pas entré la bonne réponse

    Il faudrait que je puisse séparer ma variable "réponse_attendue" de la fonction readline().
    Ou "figer" la fonction readline().
    Je ne sais pas comment je pourrais faire ça... J'ai passé l'aprèm a me craquer la tête avec des boucles de condition, sans succès.

    Merci d'avoir lu, en tout cas !
    Voilà mon code :

    from __future__ import unicode_literals
    from tkinter import *
    import codecs
    
    f = codecs.open('questions.txt', encoding='utf-8') 				# On ouvre (avec le bon encodage) le fichier qui contient les questions.
    g = codecs.open('reponses_attendues.txt', encoding='utf-8') 				# On ouvre (avec le bon encodage) le fichier qui contient les reponses.
    
    
    def repondre(): 												# Fonction déclenchée par un bouton Valider, plus bas
    	reponse_utilisateur_str=str(reponse_utilisateur.get()) 		# On transforme la reponse de l'utilisateur en str
    	
    	reponse_attendue = g.readline() 						 				# On lit le fichier des réponses ligne par ligne
    	reponse_attendue = reponse_attendue.replace('\n','') 
    	reponse_attendue = reponse_attendue.replace('\r','')
    	
    	
    	affichage2['text'] = 'Réponse attendue :' + reponse_attendue
    	affichage3['text'] = 'Ce que tu viens de répondre : ' + reponse_utilisateur_str
    
    	if reponse_utilisateur_str == reponse_attendue:				# Le problème est là ! Je dois vérifier si la réponse de l'utilisateur correspond a la reponse 		attendue. Pour ça il faut que je déclare au préalable la variable "reponse" ... or a chaque fois que je la declare elle change, puisque je la crée a partir de la fonction readline(). Brain = Fucked.
    		reponse_attendue = g.readline()
    		affichage['text'] = 'Question : ' + f.readline()
    		
    
    		
    Fenetre = Tk()
    Fenetre.title('Coca Sans Bulles')
    Fenetre.geometry("900x200+300+300")
    affichage = Label(Fenetre)
    reponse_utilisateur = Entry(Fenetre, width=200)					# Champ de réponse
    valeur = Button(Fenetre, text =' Valider', command=repondre)	# Bouton Valider
    	
    affichage['text'] = 'Question : ' + f.readline() 				# On affiche la première question
    affichage2 = Label(Fenetre)
    affichage3 = Label(Fenetre)
    
    
    affichage.pack()
    affichage2.pack()
    affichage3.pack()
    reponse_utilisateur.pack()
    valeur.pack()
    Fenetre.mainloop()
    

    Samuel

    -
    Edité par Bemsha Swing 21 mai 2015 à 2:46:40

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      21 mai 2015 à 10:23:47

      Si j'ai bien compris ton problème, tu peux le reformuler comme:

      TANT QUE [la réponse de l'utilisateur n'est pas bonne] ALORS [on dis à l'utilisateur qu'il est nul et on lui repose la question].

      Si tu m'as bien suivi, tu as un élément de réponse à ton problème :)

      • Partager sur Facebook
      • Partager sur Twitter
        21 mai 2015 à 11:34:52

        Oui ! :) C'est l'idée (merci de ta réponse, Nelimee), mais même avec une boucle while() ...

        Pour pouvoir poser la condition

        while(reponse_de_lutilisateur != reponse_attendue):
             affichage['text'] = 'Question : ' + question

        Il faut au préalable que je déclare ma variable "reponse_attendue" ...
        Et je dois la déclarer à l'intérieur de la fonction correspondant au bouton "Valider", qui se déclenche toutes les fois où l'utilisateur appuie sur le bouton
        Or ma variable reponse_attendue change dès qu'on la déclare, puisqu'elle est liée à la fonction readline()

        Y'a sûrement un while() à placer, mais je te promets que j'ai essayé partout ...

        Mon code corrigé avec ton aide :

        def repondre():
        	reponse_utilisateur_str=str(reponse_utilisateur.get()) 		# Je transforme la reponse de l'utilisateur en str
        	
        	reponse = g.readline() 						 		# On lit le fichier des réponses ligne par ligne
        	reponse = reponse.replace('\n','') 
        	reponse = reponse.replace('\r','')
        	question = f.readline()
        	
        	affichage2['text'] = 'Réponse attendue :' + reponse 
        	affichage3['text'] = 'Ce que tu viens de répondre : ' + reponse_utilisateur_str
        	
        	while reponse_utilisateur_str != reponse:	
        		affichage['text'] = question


        PS : Il plante, en fait ...  Tkinter part aux fraises, je crois qu'il n'apprécie pas que je mette un Label() dans une boucle while(). J'y travaille.

        -
        Edité par Bemsha Swing 21 mai 2015 à 12:45:03

        • Partager sur Facebook
        • Partager sur Twitter
          21 mai 2015 à 11:39:56

          data = list()
          with open("questions.txt") as question_fd:
              with open("reponses.txt") as answer_fd:
                  data.append((question_fd.readline(), answer_fd.readline()))
          
          # Le code du dessus ouvre les deux fichiers et génère la variable data qui sera de la forme suivante :
          # [(question, reponse), (question, reponse), ...]
          
          for question, expected in data:
              print(question)
              answer = input()
              while answer != expected:
                  print("Mauvaise réponse.")
                  print(question)
                  answer = input()
          Si ça peut t'aider.
          • Partager sur Facebook
          • Partager sur Twitter
            21 mai 2015 à 12:31:17

            Fire4764 > Merci d'avoir répondu ! J'ai intégré ton code, mais j'ai toujours la même faille logique :

            Python veut que je déclare la variable reponse_attendue avant de vérifier si reponse_attendue == reponse_de_lutilisateur.

            list() ou non, je dois déclarer cette variable dans la fonction activée par l'utilisateur quand il clique surValider

            La déclaration de cette variable implique le changement de cette variable.

            Brain = F***ed >_<

            • Partager sur Facebook
            • Partager sur Twitter
              21 mai 2015 à 12:47:12

              def repondre():
                global f
                global g
                global reponse_utilisateur
                global affichage2
                global affichage3
              
                reponse_utilisateur_str = str(reponse_utilisateur.get())
              
                reponse_attendue = g.readline().replace #...
              
                affichage2['text'] = "Réponse Attendue: " + reponse_attendue
                affichage3.['text'] = "Ta réponse: " + reponse_utilisateur_str
              
                while reponse_utilisateur_str != reponse attendue:
                  reponse_utilisateur_str = str(reponse_utilisateur.get())
              
                #Poser une autre question
              Tu mélanges beaucoup de choses pas logiques ... Dans une fonction tu poses la question suivante mais la première question n'est pas appelée par la fonction ... Ton code est très bizarre et je te conseille de refaire différentes fonctions, en pensant bien à la durée de vie de tes variables.

              -
              Edité par IQbrod 21 mai 2015 à 12:51:30

              • Partager sur Facebook
              • Partager sur Twitter
              OpenClassrooms retire tellement d'aiguilles de nos pieds qu'on pourrait ne plus trouver le foin de notre botte :)
                21 mai 2015 à 13:13:06

                Je te propose la structure suivante :
                #IMPORTS
                
                f = #QUESTIONS
                g = #REPONSES
                
                Fenetre = Tk()
                #...
                affichage = Label(Fenetre)
                affichage2 = Label(Fenetre)
                affichage3 = Label(Fenetre)
                
                rep = Entry(Fenetre,width=200)
                v = Button #...
                
                def poserQuest(Q):
                  global affichage
                  affichage['text'] = "Question: " + Q
                
                def repondre(Vrai):
                  global affichage2
                  global affichage3
                  global rep
                  
                  r = str(rep.get())
                
                  affichage2['text'] = Vrai
                  affichage3['text'] = r
                  
                  if r != Vrai:
                    repondre(Vrai)  
                
                def lancerJeu(nbQuest):
                  global f
                  global g
                  lNumQ = 0
                  while lNumQ < nbQuest:
                    poserQuest(f.readline)
                    repondre(g.readline)
                
                affichage.pack()
                affichage2.pack()
                affichage3.pack()
                rep.pack()
                v.pack()
                
                lancerJeu(1)
                
                Fenetre.mainloop()

                -
                Edité par IQbrod 21 mai 2015 à 13:17:36

                • Partager sur Facebook
                • Partager sur Twitter
                OpenClassrooms retire tellement d'aiguilles de nos pieds qu'on pourrait ne plus trouver le foin de notre botte :)
                  21 mai 2015 à 13:55:36

                  Salut,

                  Il faut juste décomposer ta fonction repondre() en 2 fonctions. Une que tu associera à ton bouton valeur, et qui permettra de passer à la question suivante, et une autre que tu associera à reponse_utilisateur et qui servira à vérifier que le résultat est bon. Dans la première fonction, tu fera en sorte de "cacher" le bouton pour qu'il ne soit pas possible de passer à la question suivante sans avoir la bonne réponse. Et dans la fonction associé à ton Entry, si le résultat est validé, tu affiche de nouveau le bouton:

                  import tkinter as tk
                  
                  def verif(event):
                      if rep_attendue = rep_utilisateur:  #La convertion en str() est inutile
                          #tu peux afficher un message de félicitation
                          valeur["state"] = "normal"  #On réactive le bouton
                      else:  #facultatif
                          #Tu peux afficher un message pour la mauvaise réponse
                  
                  def repondre():
                      #Fonction qui va afficher la question et sauvegarder la réponse
                      
                      #Désactivation du bouton pour ne pas passer la question
                      valeur["state"] = "disabled"


                  Après il faudra sûrement utiliser une variable muable pour enregistrer la réponse (par exemple une liste, dont le premier élément est la réponse).

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Précepte: Le mieux est l'ennemi du bien
                    21 mai 2015 à 14:01:36

                    Et j'ai oublié de préciser que pour associer ta fonction à l'entrée utilisateur, tu utilisera la méthode bind (juste après l'instanciation par exemple):

                    reponse_utilisateur = Entry(Fenetre, width=200)  
                    reponse_utilisateur.bind("<Return>", verif)

                    À l'instar du paramètre command, la méthode bind permet également la gestion des événements à ceci près que command est un raccourci pour le clic gauche, alors que bind prend n'importe quel événement. Ici le <Return> correspond à la touche Entrée de ton clavier.

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Précepte: Le mieux est l'ennemi du bien
                      21 mai 2015 à 20:32:09

                      YES !!

                      Merci beaucoup pour vos réponses, en les combinant (et en utilisant des variables globales, nom d'un petit bonhomme) j'ai réussi à avoir le résultat voulu. :)

                      IQBrod > Oui, j'ai beaucoup de progrès à faire pour structurer mes codes :p ... merci de ta proposition, je vais m'en inspirer

                      -
                      Edité par Bemsha Swing 21 mai 2015 à 20:32:28

                      • Partager sur Facebook
                      • Partager sur Twitter

                      J'aimerais "figer" la fonction readline()

                      × 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