Vous devrez utiliser l'interface TPLab pour envoyer vos TP aux encadrants de TP.
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 TP pour valider votre code.
Travailler avec :
Pour ouvrir un fichier texte en écriture, il suffit de faire
f = open(nom_fichier, mode="w")
On peut ensuite écrire des chaînes de caractères dans le fichier, en faisant attention à bien mettre le caractère « saut de ligne » ("\n"
) lorsque c'est nécessaire :
f.write("Ceci est") f.write(" une seule ligne") f.write(" dans le fichier.\n") f.write("Et ceci est la deuxième ligne...\n")
Écrivez une procédure sauvegarde_nom_score
qui sauvegarde le nom et le score de quelqu'un dans un fichier :
def sauvegarde_nom_score(nom_fichier, nom, score): """sauvegarde un nom et un score dans un fichier : Paramètres : - nom_fichier, de type chaîne de caractères : nom du fichier où sauvegarder le score - nom, de type chaîne de caractères : nom du joueur - score, de type flottant : score du joueur"""
Écrivez une fonction lire_score
qui récupère le score dans un fichier :
def lire_score(nom_fichier): """lit et renvoie le score (deuxième ligne) dans un fichier paramètre : nom_fichier, de type chaîne de caractères : nom du fichier à ouvrir valeur de retour : flottant"""
Pour ceci, il faudra ouvrir le fichier en lecture:
f = open(nom_fichier, mode="r")
et utiliser la méthode f.readline()
qui renvoie les lignes successives du fichier. (Attention, deux appels successifs à f.write()
donnent deux résultats différents : le premier renvoie la première ligne et le second renvoie la deuxième ligne du fichier.)
La méthode f.readline()
renvoie une chaine de caractères, qu'il faudra convertir en nombre. Vous devrez donc utiliser la fonction int(...)
ou float(...)
pour transformer une chaine en nombre entier ou flottant.
Dans ce TP, nous allons écrire un petit programme de QCM. Le logiciel pose des questions à l'utilisateur, qui choisit une réponse parmi celles proposées.
Dans un premier temps, chaque question est représentée par un dictionnaire q
contenant trois cases :
'question'
contenant une chaîne de caractères qui est la question à poser,
'correcte'
contenant une chaîne de caractères qui est la bonne réponse à la question,
'incorrecte'
contenant une chaîne de caractères qui est la mauvaise réponse.
Par exemple :
q_test1 = {'question': "Quelle est la couleur des bananes ?", 'correcte': "jaune", 'incorrecte': "bleue"}
Si q
est un tel dictionnaire, on peut accéder aux différentes cases avec la notation
q['question']
pour récupérer la question,
q['correcte']
pour récupérer la bonne réponse,
q['incorrecte']
pour récupérer la mauvaise réponse.
Avec l'exemple précédent, on aura par exemple :
>>> print(q_test1['question']) Quelle est la couleur des bananes ?
É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(q_test2) Quelle est la couleur du cheval blanc d'Henry IV ? 1 - blanc 2 - gris Entrez votre choix: 1 Bonne réponse !
Un questionnaire est une liste de plusieurs questions, c'est à dire une liste de dictionnaires.
Voici un exemple de code python définissant un tel questionnaire :
qs_test = [{'question': "Quelle est la couleur du cheval blanc d'Henry IV ?", 'correcte': "blanc", 'incorrecte': "gris"}, {'question': "2 + 2 = ?", 'correcte': "4", 'incorrecte': "42"}, {'question': "Un brelan de rois gagne une couleur.", 'correcte': "faux", 'incorrecte': "vrai"}]
Vous pouvez maintenant poser toutes les questions d'un questionnaire grâce à la procédure suivante
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.")
Testez la procédure questionnaire
ci-dessus.
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.
question
" en une fonction qui renvoie un +1
ou -1
.
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 : Combienfait 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%.
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 Combien fait 2 + 2 ? - 42 + 4 Un brelan de rois gagne une couleur - vrai + faux
Rappel : on peut supprimer les deux premiers caractères d'une chaîne avec
s = s[2:]
Écrivez une fonction "lecture_quizz
" qui prend un nom de fichier en argument et renvoie le questionnaire (liste de dictionnaires) correspondant.
Par exemple, le fichier ci-dessus donnera exactement le questionnaire qc
donné précédemment.
Chaque question comporte exactement 4 lignes :
Lorsque la ligne blanche devient vide, cela veut dire qu'on a atteint la fin du fichier.
Il est donc possible de récupérer les questions une par une, dans une boucle while :
tant qu'on n'a pas trouvé la dernière ligne, on fait quatre readline
pour récupérer la question, les deux réponses et la ligne blanche...
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...
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 à jour.
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
En utilisant les fonctions de la partie "Préliminaires", é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 (avec la fonction input
),
score.txt
".
Incorporez vos fonctions dans une unique procédure principale "quizz(fichier)
" qui :
Nous allons maintenant gérer les QCM où le nombre de réponses proposées peut-être supérieur à deux.
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 champ "incorrecte
" du dictionnaire par une liste de mauvaises réponses. Par symétrie, le champ "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"]}]
Attention : le score est calculé de la manière suivante : s'il y a n bonnes réponses et m mauvaises réponses, le joueur
Ceci permet d'assurer qu'en moyenne un joueur répondant au hasard à 0pt.
Écrivez une fonction "question_qcm
" similaire à la fonction "question
" pour prendre les réponses multiples en compte.
Pour mélanger les réponses, le plus simple est de :
reponses
qui contient toutes les réponses, bonnes et mauvaises,
shuffle
),
in q["correctes"]
ou in q["incorrectes"]
).
Le format de fichier pour les QCM est le même que pour les quizz. La seule différence est qu'il peut y avoir plusieurs bonnes / mauvaises réponses. 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_qcm()
" qui prend un nom de fichier en argument et renvoie le questionnaire (liste de dictionnaires) correspondant.
Par exemple :
>>> lecture_questionnaire("questions.qcm") [{'incorrectes': ['gris', 'transparent', 'rouge à pois verts'], 'correctes': ['blanc'], 'question': "Quelle est la couleur du cheval blanc d'Henry IV ?"}, {'incorrectes': ["c'est trop dur"', '42', 'rouge à pois verts'], 'correctes': ['0', 'la tête à Toto'], 'question': 'Combien fait 2 + 2 ?'}]
(Un fichier exemple questions.qcm
est disponible ici.)
Écrivez une variante de la procédure quizz()
pour utiliser les fonctions précédentes.