Construire un quiz en ligne de commande en Go

Construisez un quiz en ligne de commande en Go : questions dans une slice de structs, réponses lues avec bufio.Scanner, puis score et résultat affichés.

Temps estimé
~4 h
Compétences
CLI, functions, error-handling, slices
Sur cette page

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 struct et regrouper des enregistrements dans une slice.
  • Lire une saisie interactive ligne par ligne avec bufio.Scanner sur os.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 :

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/rand pour 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.

Recherche

La recherche s’exécute entièrement dans votre navigateur.