Dans ce projet, vous construisez un petit quiz qui s’exécute entièrement dans le
terminal. Le programme range ses questions dans une slice de structs, les pose
une à une, lit la réponse saisie au clavier sur l’entrée standard, puis affiche
un score final du type Vous avez 2 bonnes réponses sur 3.. C’est un programme
Go complet et compilable, lançable avec un simple go run ..
Compétences travaillées
- Modéliser des données avec un
structet regrouper des enregistrements dans une slice. - Lire une saisie interactive ligne par ligne avec
bufio.Scannersuros.Stdin. - Écrire de petites fonctions utilitaires faciles à tester.
- Comparer des chaînes de façon robuste (insensible à la casse, espaces ignorés) pour corriger les réponses.
Prérequis
Assurez-vous de maîtriser les bases avant de commencer :
- Les fonctions en Go — vous isolerez la logique de correction dans sa propre fonction.
- Les tableaux et les slices en Go — les questions vivent dans une slice.
- La gestion des erreurs en Go — vous vous prémunirez contre un flux d’entrée fermé.
Arborescence finale
quiz-cli/
├── go.mod
└── main.go
Étapes
1. Initialiser le module et modéliser une question
Créez le dossier, initialisez un module, puis décrivez ce qu’est une question. Chaque question a un énoncé et la réponse que l’on accepte comme correcte.
package main
type Question struct {
Prompt string
Answer string
}
Lancez go mod init quizcli dans le dossier pour que le code devienne un module
compilable.
2. Écrire une fonction pour corriger une réponse
Une fonction dédiée garde main concise et, surtout, rend la logique de
correction facile à tester. On accepte la réponse quelle que soit la casse et on
ignore les espaces superflus.
import "strings"
// isCorrect indique si la réponse fournie correspond à celle attendue,
// sans tenir compte de la casse ni des espaces autour.
func isCorrect(q Question, given string) bool {
return strings.EqualFold(strings.TrimSpace(given), q.Answer)
}
3. Lire les réponses avec bufio.Scanner
bufio.Scanner lit l’entrée standard ligne par ligne. Scan renvoie false
lorsque le flux est fermé (par exemple en fin de fichier), ce qui permet de
s’arrêter proprement plutôt que de planter.
scanner := bufio.NewScanner(os.Stdin)
for i, q := range questions {
fmt.Printf("Question %d/%d : %s\n> ", i+1, len(questions), q.Prompt)
if !scanner.Scan() {
break
}
// corriger scanner.Text() ici
}
4. Assembler le programme complet
Réunissez les morceaux : une slice de questions, un score courant et un résumé à la fin. Ce programme compile et s’exécute tel quel.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// Question contient un énoncé et la réponse acceptée comme correcte.
type Question struct {
Prompt string
Answer string
}
// isCorrect indique si la réponse fournie correspond à celle attendue,
// sans tenir compte de la casse ni des espaces autour.
func isCorrect(q Question, given string) bool {
return strings.EqualFold(strings.TrimSpace(given), q.Answer)
}
func main() {
questions := []Question{
{Prompt: "Quel mot-clé déclare une fonction en Go ?", Answer: "func"},
{Prompt: "Quelle commande compile et lance un programme ?", Answer: "go run"},
{Prompt: "Quelle est la valeur zéro d'un bool ?", Answer: "false"},
}
scanner := bufio.NewScanner(os.Stdin)
score := 0
for i, q := range questions {
fmt.Printf("Question %d/%d : %s\n> ", i+1, len(questions), q.Prompt)
if !scanner.Scan() {
break
}
if isCorrect(q, scanner.Text()) {
fmt.Println("Correct !")
score++
} else {
fmt.Printf("Faux. Attendu : %s\n", q.Answer)
}
}
fmt.Printf("\nVous avez %d bonnes réponses sur %d.\n", score, len(questions))
}
Lancez-le avec go run . et répondez à chaque question.
Critères de validation
-
go run .démarre le quiz et affiche une question à la fois. - Une bonne réponse incrémente le score ; une mauvaise affiche la valeur attendue.
- Les réponses sont comparées sans tenir compte de la casse ni des espaces.
- Le programme affiche une ligne finale
Vous avez X bonnes réponses sur Y.. - Appuyer sur Ctrl-D (fin d’entrée) arrête le quiz sans panic.
Pour aller plus loin
- Mélangez les questions avec
math/randpour varier chaque partie. - Chargez les questions depuis un fichier JSON ou CSV au lieu de les coder en dur.
- Ajoutez un chronomètre par question et récompensez les réponses rapides.
- Gérez les questions à choix multiples en affichant des options et en lisant une lettre.
Tests
Comme la correction vit dans isCorrect, vous pouvez la tester sans aucune
entrée/sortie. Ajoutez un fichier main_test.go et lancez go test ./....
package main
import "testing"
func TestIsCorrect(t *testing.T) {
q := Question{Prompt: "mot-clé ?", Answer: "func"}
cases := []struct {
name string
given string
want bool
}{
{"exact", "func", true},
{"espaces retirés", " func ", true},
{"casse différente", "FUNC", true},
{"mauvaise réponse", "def", false},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if got := isCorrect(q, c.given); got != c.want {
t.Errorf("isCorrect(%q) = %v, want %v", c.given, got, c.want)
}
})
}
}
Conclusion
Vous avez construit un quiz de terminal fonctionnel et testable, et pratiqué les structs, les slices, la lecture de saisie et un test « table-driven ». L’étape suivante naturelle est de conserver des données entre les exécutions : enchaînez avec le projet gestionnaire de tâches en CLI, où vous sauvegardez l’état dans un fichier JSON.