La partie obligatoire de ce TP sera notée par votre intervenant pendant la séance de TP. Vous devrez donc appeler votre intervenant à chaque fois que vous avez terminé une question.
Les questions « bonus » peuvent être envoyée par email à votre intervenant pendant la semaine (7 jours) qui suivent votre séance de TP. N'oubliez pas de mettre votre nom ainsi que votre filière en commentaire dans les fichiers que vous nous envoyez...
Attention : pour que les questions bonus soient prises en compte, il faut que les questions obligatoires aient été traitées. Si vous n'avez pas fini les questions obligatoires en TP, il faut donc les finir chez vous avant de traiter les questions bonus...
La note ne valide pas seulement le résultat de votre programme, mais également son style :
Vérifiez ces points avant de demander à votre intervenant de valider votre code.
Dans ce TP, nous allons écrire un petit programme de QCM. Le logiciel pose des questions à l'utilisateur, qui choisit une réponse parmi celle proposées.
Dans un premier temps, chaque question est représentée par un dictionnaire q
contenant trois champs :
q['question']
est une chaîne qui est la question à poser.
q['correcte']
est la bonne réponse
q['incorrecte']
est la mauvaise réponse
Un questionnaire est donc simplement une liste de questions, c'est à dire une liste de dictionnaires.
Voici un exemple de code python définissant un tel questionnaire:
qs = [ {'question': "Quelle est la couleur du cheval blanc d'Henry IV ?", 'correcte': "blanc", 'incorrecte': "gris"}, {'question': "2 + 2 = ?", 'correcte': "4", 'incorrecte': "42"} ]
Écrivez une procédure question(q)
qui prend une question en argument, et qui :
input
")
Bonne réponse !
" ou "Mauvaise réponse !
"
Par exemple :
>>> question(qs[0]) Quelle est la couleur du cheval blanc d'Henry IV ? 1 - gris 2 - blanc Entrez votre choix: 2 Bonne réponse !
Vous pouvez maintenant faire tout le questionnaire grace à la procédure
def questionnaire(qs): """Pose toutes les questions du questionnaire "qs" passé en argument.""" for i in range(len(qs)): print("Question", i+1, ":", end=" ") question(qs[i]) print() print("Fin du questionnaire.")
Le score à un questionnaire est calculé de la manière suivante : on compte 1 point par bonne réponse et -1 point par mauvaise réponse. Ceci fait qu'un utilisateur qui répond au hasard aura, en moyenne, un score de 0.
Transformez votre procédure "question
" en une fonction qui renvoie un "+1
" ou "-1
".
Transformez la procédure "questionnaire
" en une fonction pour qu'elle calcule le score et le renvoie, comme une note sur 100 :
>>> score = questionnaire(qs) Question 1 : Quelle est la couleur du cheval blanc d'Henry IV ? 1 - gris 2 - blanc Entrez votre choix: 2 Bonne réponse ! Question 2 : 2 + 2 = ? 1 - 4 2 - 42 Entrez votre choix: 2 Mauvaise réponse ! Fin du questionnaire. >>> print("Votre score est de {}%.".format(score)) Votre score est de 0%.
Toujours poser les questions dans le même ordre n'est pas une très bonne idée. Pour mélanger les questions, vous pouvez utiliser la procédure "shuffle
" de la bibliothèque "random
". Cette procédure permet de mélanger une liste existante :
>>> from random import shuffle >>> t = [1,2,3,4,5,6] >>> shuffle(t) >>> t [5, 6, 1, 4, 3, 2]
Modifier la fonction "questionnaire
" pour qu'elle affiche les questions dans le désordre.
Pour afficher les réponses possibles dans un ordre aléatoire (avec parfois la bonne réponse en premier et parfois la bonne réponse en second), on peut utiliser la fonction "randint(0,1)
" du module "random
". Elle permet de tirer un bit ("0
" ou "1
") aléatoirement.
>>> from random import randint >>> for i in range(10): >>> for i in range(10): ... print(randint(0,1)) ... 0 1 0 0 0 1 1 1 1 1
Modifiez-votre fonction "question
" pour que l'ordre des réponses possibles soit aléatoire.
Vérifiez que le score reste correct...
f = open("nom du fichier", "r")
"
ligne = f.readline()
", s'il n'y a plus de ligne dans le fichier, le résultat de la fonction est la chaîne vide ""
, (si on lit une ligne vide, on à au moins le caractère \n
dans le résultat de readline()
)
f = open("nom du fichier", "w")
" ou "f = open("nom du fichier", "a")
",
f.write("blablabla")
", on n'oubliant pas d'ajouter un saut de ligne si nécessaire,
f.close()
".
On peut utiliser un fichier texte "./score.txt
" pour conserver le score et le nom du meilleur joueur. Lorsqu'un utilisateur obtient un nouveau meilleur score, on met ce fichier à jours.
Le plus simple est de mettre le nom du joueur sur la première ligne, et le score sur la deuxième ligne. Par exemple :
Tartempion 75.0
Écrivez une procédure "ecrit_score(nom, s)
" créant le fichier "./score.txt
", avec 2 lignes comme indiqué ci-dessus.
Écrivez une procédure "meilleur_joueur
" qui lit le nom de meilleur joueur et son score dans le fichier "./score.txt
" et les affiche :
>>> meilleur_joueur() **** **** Le meilleur joueur est Tartempion, son score est de 75.00. **** Arriveras tu à le battre ? ****
Écrivez une procédure "gestion_score(s)
" qui prend un score en argument et fait les choses suivantes :
./score.txt
",
s
' est supérieur au meilleur score, demande le nom du joueur,
ecrit_score(nom, s)
".
Incorporez les différentes fonctions dans une unique fonction principale "main()
" qui
Nous allons maintenant gérer les QCM, où le nombre de réponses proposées peut-être supérieur à deux. Nous vous conseillons de sauvegarder ce que vous avez fait jusqu'à présent dans un nouveau fichier et de modifier cette copie.
Lorsque le nombre de réponses proposées est plus grand que 2, il faut gérer les mauvaises réponses différemment. On remplace le champs " ̀`incorrecte" du dictionnaire par une //liste// de mauvaises réponses. Par symétrie, le champs "
correcte``" contiendra lui aussi une liste de bonnes réponses. (La plupart du temps, il n'y aura qu'une seule bonne réponse...)
Voici un exemple de code python produisant un questionnaire modifié :
qcm = [ {'question': "Quelle est la couleur du cheval blanc d'Henry IV ?", 'correctes': ["blanc"], 'incorrectes': ["gris","rouge à pois vert","transparent"]}, {'question': "0 + 0 = ?", 'correctes': ["0", "la tête à Toto"], 'incorrectes': ["42", "c'est trop dur"] } ]
Nous allons écrire une fonction auxiliaire pour mélanger les réponses (la bonne et les mauvaises) tout en gardant l'information des bonnes et des mauvaises réponses.
Le score est calculé de la manière suivante : s'il y a n
bonnes réponses et m
mauvaises réponses, le joueur
1.0
point pour une bonnes réponse,
-n/m
point pour une mauvaises réponse.
Ceci permet d'assurer qu'en moyenne un joueur répondant au hasard à 0pt.
Écrivez une fonction "melange_reponses
" qui prend la liste des réponses correctes et la liste des réponses incorrectes en argument et :
La fonction renverra la liste de toutes les réponses mélangées, avec leur score.
>>> melange_reponses(["blanc"], ["gris","rouge à pois vert","transparent"]) [('gris', -0.33333), ('rouge à pois vert', -0.33333), ('blanc', 1), ('transparent', -0.33333)]
Modifiez la fonction "question
" ainsi que les autres fonctions pour prendre en charge ce type de questionnaires à choix multiples.
Plutôt que d'écrire tout le questionnaire dans votre fichier Python, il peut être pratique de stocker le questionnaire dans un fichier. Ceci permet d'avoir plusieurs questionnaires : "culture_generale.qcm
", "mathematiques.qcm
", "cinema.qcm
", ...
On peut utiliser des fichiers de la forme suivante :
+
",
-
".
Par exemple :
Quelle est la couleur du cheval blanc d'Henry IV ? + blanc - gris - transparent - rouge à pois verts Combien fait 0 + 0 ? + 0 - c'est trop dur - 42 + la tête à Toto - rouge à pois verts
Écrivez une fonction "lecture_questionnaire()
" qui prend un nom de fichier en argument et renvoie le questionnaire (liste de dictionnaires) correspondant.
Par exemple :
>>> lecture_questionnaire("questions.txt") [{'incorrectes': ['gris', 'transparent', 'rouge à pois verts'], 'correcte': ['blanc'], 'question': "Quelle est la couleur du cheval blanc d'Henry IV ?"}, {'incorrectes': ["c'est trop dur"', '42', 'rouge à pois verts'], 'correcte': ['0', 'la tête à Toto'], 'question': 'Combien fait 2 + 2 ?'}]
Adaptez votre procédure main()
pour qu'elle appelle la fonction précédente et lise le questionnaire dans un fichier questions.txt
.