⌂ Programmation
Fiche 9 sur 13

Choisir entre plusieurs cas

Quand il y a plus de deux possibilités.

Après cette fiche, vous saurez :

1else if : enchaîner les cas

Le if / else ne gère que deux possibilités. Souvent, il en faut plus.

Exemple : afficher une appréciation selon une note sur 20.

Console.Write("Votre note sur 20 : ");
int note = int.Parse(Console.ReadLine());

if (note >= 16)
{
    Console.WriteLine("Excellent");
}
else if (note >= 14)
{
    Console.WriteLine("Très bien");
}
else if (note >= 12)
{
    Console.WriteLine("Bien");
}
else if (note >= 10)
{
    Console.WriteLine("Satisfaisant");
}
else
{
    Console.WriteLine("Insuffisant");
}
Ce que l'ordinateur affiche
Votre note sur 20 : 13
Bien

À retenir

Comment l'ordinateur lit cet enchaînement.

  1. Il teste la première condition. Vraie ? Il exécute le bloc et saute tout le reste.
  2. Fausse ? Il passe à la suivante.
  3. Et ainsi de suite jusqu'au else final, qui attrape tout ce qui reste.

Un seul bloc s'exécute, toujours. Dès qu'une condition est vraie, l'ordinateur sort de l'enchaînement.

Attention

L'ordre des tests est capital.

Inversons l'enchaînement :

if (note >= 10) { Console.WriteLine("Satisfaisant"); }
else if (note >= 12) { Console.WriteLine("Bien"); }
else if (note >= 16) { Console.WriteLine("Excellent"); }

Avec une note de 18, le programme affiche « Satisfaisant ».

Pourquoi ? Parce que 18 est bien supérieur à 10. La première condition est vraie, donc l'ordinateur s'arrête là et ne regarde jamais les suivantes.

La règle : testez toujours du cas le plus restrictif au plus large. Du plus grand seuil au plus petit.

Et le pire : ce programme compile et s'exécute sans la moindre erreur. Il donne simplement des résultats faux. C'est exactement ce qu'il faut apprendre à traquer.

2Combiner des conditions

Parfois, une seule condition ne suffit pas.

OpérateurSe litIl faut que…
&&ETles deux conditions soient vraies
||OUau moins une soit vraie
!NONla condition soit fausse
// ET : les deux doivent être vraies
if (age >= 18 && aLePermis == true)
{
    Console.WriteLine("Vous pouvez conduire.");
}

// OU : une seule suffit
if (jour == "samedi" || jour == "dimanche")
{
    Console.WriteLine("C'est le week-end !");
}

À retenir

Le || se tape avec la touche AltGr + 1 sur un clavier belge. Deux barres verticales, collées.

Et le &&, deux esperluettes collées : touche 1 avec Shift, deux fois.

Attention

Le ET est prioritaire sur le OU. Mettez des parenthèses.

// Ambigu
if (note >= 10 || presence >= 80 && travail == "rendu")

// Comment C# le comprend
if (note >= 10 || (presence >= 80 && travail == "rendu"))

// Ce que vous vouliez peut-être
if ((note >= 10 || presence >= 80) && travail == "rendu")

Les deux dernières lignes ne donnent pas le même résultat. Dans le doute, parenthésez : ça ne coûte rien et ça enlève toute ambiguïté.

Comparer du texte

Console.Write("Votre réponse (oui/non) : ");
string reponse = Console.ReadLine();

if (reponse == "oui")
{
    Console.WriteLine("Très bien !");
}

Attention

La comparaison de texte tient compte des majuscules.

"oui", "Oui" et "OUI" sont trois textes différents. Un utilisateur qui tape « Oui » ne serait pas reconnu.

La solution : tout mettre en minuscules avant de comparer.

string reponse = Console.ReadLine().ToLower();

if (reponse == "oui")
{
    Console.WriteLine("Très bien !");
}

ToLower() transforme le texte en minuscules. C'est une petite attention qui distingue un programme fini d'un prototype.

3switch : quand on teste une seule valeur

Quand toutes vos conditions comparent la même variable à des valeurs précises, le switch est plus lisible.

Console.Write("Choisissez un plat (1 à 3) : ");
int choix = int.Parse(Console.ReadLine());

switch (choix)
{
    case 1:
        Console.WriteLine("Carbonnades flamandes - 18,50 euros");
        break;

    case 2:
        Console.WriteLine("Waterzooi - 16,00 euros");
        break;

    case 3:
        Console.WriteLine("Moules frites - 22,00 euros");
        break;

    default:
        Console.WriteLine("Ce plat n'existe pas.");
        break;
}
MorceauRôle
switch (choix)La variable qu'on examine
case 1:Si elle vaut 1
break;Obligatoire. Sort du switch
default:Tous les autres cas. Comme un else

Attention

N'oubliez jamais le break;

Sans lui, C# refuse de compiler. Dans d'autres langages, il compile et exécute tous les cas suivants — une source de bogues célèbre.

C# vous protège en l'imposant. Profitez-en.

À retenir

if ou switch ?

L'exemple des notes de la section 1 ne peut pas se faire en switch : on y compare des intervalles, pas des valeurs exactes.

4Le hasard : Random

Un jeu a besoin d'imprévu : un dé, une carte, un monstre qui apparaît ou non. L'ordinateur sait tirer un nombre au hasard grâce à un outil livré avec C# : Random.

Il faut faire deux choses : créer le générateur de hasard, puis lui demander un nombre.

// je crée le générateur de hasard
Random de = new Random();

// je tire un nombre : 1, 2, 3, 4, 5 ou 6
int resultat = de.Next(1, 7);

Console.WriteLine($"Le dé affiche : {resultat}");
Ce que l'ordinateur affiche
Le dé affiche : 4

Relancez le programme : le nombre change à chaque exécution. Le 4 ci-dessus n'est qu'un exemple.

new Random() fabrique le générateur, que l'on range dans une variable (ici de). de.Next(1, 7) lui demande un nombre.

À retenir

La borne haute est exclue.

Next(1, 7) donne un nombre de 1 à 6, jamais 7. La règle : Next(min, max) donne les nombres de min jusqu'à max - 1. Pour un nombre de 1 à 4, on écrit Next(1, 5).

Tirer un nombre, puis décider

Le tirage se combine avec ce que vous venez de voir. Exemple : une salle de donjon où il peut arriver trois choses.

Random de = new Random();
int tirage = de.Next(1, 5);   // 1, 2, 3 ou 4

Console.WriteLine($"Tirage : {tirage}");

if (tirage == 1 || tirage == 4)
{
    Console.WriteLine("Aïe ! Vous perdez 10 points de vie.");
}
else if (tirage == 2)
{
    Console.WriteLine("Vous trouvez 10 pièces d'or.");
}
else
{
    Console.WriteLine("Vous vous reposez un instant.");
}
Ce que l'ordinateur affiche
Tirage : 2
Vous trouvez 10 pièces d'or.

Attention

Créez le Random une seule fois, au début du programme, et réutilisez-le à chaque tirage.

N'écrivez pas new Random() à chaque tirage, surtout dans une boucle : selon la version de .NET, des générateurs créés coup sur coup peuvent donner les mêmes nombres.

Le hasard complique aussi les tests. Pour vérifier une branche précise, remplacez temporairement le tirage par un nombre fixe, par exemple int tirage = 4;, puis remettez de.Next(1, 5).

→Exercices

1Les appréciationsRecopier

Recopiez le programme des notes de la section 1. Testez avec 18, 13, 10, 9, puis 20 et 0.

Ensuite, inversez l'ordre des tests comme dans l'encadré rouge, et testez à nouveau avec 18. Que se passe-t-il ?

Solution

Dans le bon ordre : 18 → Excellent, 13 → Bien, 10 → Satisfaisant, 9 → Insuffisant, 20 → Excellent, 0 → Insuffisant.

Dans l'ordre inversé : 18 affiche « Satisfaisant ».

L'ordinateur teste note >= 10 en premier. C'est vrai pour 18, donc il affiche « Satisfaisant » et sort. Les conditions suivantes ne sont jamais examinées.

Ce qui rend cette erreur dangereuse : aucun message, aucun plantage. Le programme fonctionne parfaitement et donne un résultat faux. Un étudiant excellent serait noté « satisfaisant ».

Le réflexe à prendre : dans un enchaînement de else if sur des seuils, allez toujours du plus grand au plus petit. Ou du plus petit au plus grand si vous testez avec <=. Mais jamais dans le désordre.

2Le tarif de la piscineModifier

La piscine communale applique ces tarifs :

  • moins de 6 ans : gratuit
  • de 6 à 17 ans : 2,50 euros
  • de 18 à 64 ans : 4,50 euros
  • 65 ans et plus : 3,00 euros
  1. Écrivez le programme qui demande l'âge et affiche le tarif.
  2. Ajoutez une réduction : le mercredi, tout le monde paie 1 euro de moins (sauf les gratuits).
  3. Testez avec les âges frontières : 5, 6, 17, 18, 64, 65.

Solution

Console.Write("Âge du visiteur : ");
int age = int.Parse(Console.ReadLine());

Console.Write("Sommes-nous mercredi ? (oui/non) ");
string jour = Console.ReadLine().ToLower();

double tarif;

if (age >= 65)
{
    tarif = 3.00;
}
else if (age >= 18)
{
    tarif = 4.50;
}
else if (age >= 6)
{
    tarif = 2.50;
}
else
{
    tarif = 0.00;
}

// La réduction du mercredi, sauf pour les entrées gratuites
if (jour == "oui" && tarif > 0)
{
    tarif = tarif - 1.00;
}

Console.WriteLine();
Console.WriteLine($"Tarif à payer : {tarif:F2} euros");

Console.ReadKey();
Ce que l'ordinateur affiche
Âge du visiteur : 17
Sommes-nous mercredi ? (oui/non) oui

Tarif à payer : 1,50 euros

Les points importants.

L'ordre des tests va du plus grand âge au plus petit. C'est indispensable : avec l'ordre inverse, une personne de 70 ans paierait 2,50 euros.

La variable tarif est déclarée AVANT le if, et non à l'intérieur. Sinon elle n'existerait plus une fois les accolades fermées, et le programme ne compilerait pas.

Le && de la réduction évite de donner un tarif négatif aux enfants gratuits. Sans la condition tarif > 0, un enfant de 4 ans paierait −1 euro le mercredi.

Les tests aux frontières : 5 → 0,00 ; 6 → 2,50 ; 17 → 2,50 ; 18 → 4,50 ; 64 → 4,50 ; 65 → 3,00. Si l'un d'eux ne tombe pas juste, c'est un >= écrit >.

3Le menu du restaurantCréer

Écrivez la borne de commande d'un restaurant.

  1. Affichez un menu de quatre plats numérotés, avec leur prix.
  2. Demandez le numéro du plat choisi, puis la quantité.
  3. Utilisez un switch pour retrouver le nom et le prix du plat.
  4. Si le numéro n'existe pas, affichez un message et arrêtez le programme.
  5. Sinon, affichez un ticket avec le plat, la quantité et le total.

Aide : l'instruction return; arrête le programme immédiatement.

Solution

Console.WriteLine("=== CHEZ MARIE ===");
Console.WriteLine();
Console.WriteLine("  1. Carbonnades flamandes ... 18,50 euros");
Console.WriteLine("  2. Waterzooi ............... 16,00 euros");
Console.WriteLine("  3. Moules frites ........... 22,00 euros");
Console.WriteLine("  4. Croquettes aux crevettes  11,00 euros");
Console.WriteLine();

Console.Write("Votre choix (1 a 4) : ");
int choix = int.Parse(Console.ReadLine());

Console.Write("Quantité            : ");
int quantite = int.Parse(Console.ReadLine());

string plat;
double prix;

switch (choix)
{
    case 1:
        plat = "Carbonnades flamandes";
        prix = 18.50;
        break;

    case 2:
        plat = "Waterzooi";
        prix = 16.00;
        break;

    case 3:
        plat = "Moules frites";
        prix = 22.00;
        break;

    case 4:
        plat = "Croquettes aux crevettes";
        prix = 11.00;
        break;

    default:
        Console.WriteLine();
        Console.WriteLine("Ce plat n'existe pas au menu.");
        Console.ReadKey();
        return;
}

double total = prix * quantite;

Console.Clear();
Console.WriteLine("+-------------------------------------+");
Console.WriteLine("              TICKET");
Console.WriteLine("+-------------------------------------+");
Console.WriteLine($"  Plat     : {plat}");
Console.WriteLine($"  Quantité : {quantite}");
Console.WriteLine($"  Prix     : {prix:F2} euros");
Console.WriteLine();
Console.WriteLine($"  TOTAL    : {total:F2} euros");
Console.WriteLine("+-------------------------------------+");

Console.ReadKey();
Ce que l'ordinateur affiche
Votre choix (1 a 4) : 3
Quantité            : 2

+-------------------------------------+
              TICKET
+-------------------------------------+
  Plat     : Moules frites
  Quantité : 2
  Prix     : 22,00 euros

  TOTAL    : 44,00 euros
+-------------------------------------+

Pourquoi un switch ici ? Parce qu'on compare une seule variable, choix, à quatre valeurs précises. C'est exactement son domaine.

Les variables plat et prix sont déclarées avant le switch, pour la même raison qu'à l'exercice 2 : elles doivent survivre à la fermeture des accolades.

Le return; dans le default arrête tout. Sans lui, le programme continuerait et tenterait d'afficher un ticket avec des variables jamais remplies — ce que le compilateur refuserait.

À tester : tapez 7 comme choix. Vous devez voir le message d'erreur, et aucun ticket.

4Le déCréer

Écrivez un petit jeu de plateau où l'on lance un dé à 6 faces.

  1. Lancez le dé et affichez le résultat.
  2. Si le dé donne 6 : « Un six ! Vous rejouez. » Si le dé donne 1 : « Un un... vous passez votre tour. » Sinon : « Vous avancez de X cases », où X est le résultat du dé.
  3. Exécutez le programme plusieurs fois, puis testez chaque cas en remplaçant temporairement le tirage par un nombre fixe (1, 6, puis 3).

Solution

Random de = new Random();
int lancer = de.Next(1, 7);

Console.WriteLine($"Vous lancez le dé : {lancer}");

if (lancer == 6)
{
    Console.WriteLine("Un six ! Vous rejouez.");
}
else if (lancer == 1)
{
    Console.WriteLine("Un un... vous passez votre tour.");
}
else
{
    Console.WriteLine($"Vous avancez de {lancer} cases.");
}
Ce que l'ordinateur affiche
Vous lancez le dé : 4
Vous avancez de 4 cases.

Pourquoi Next(1, 7) ? Parce que la borne haute est exclue : pour obtenir un 6, il faut écrire 7.

Le else final attrape tous les autres résultats : 2, 3, 4 et 5. Ici l'ordre des tests n'a pas d'importance, car un dé ne peut pas valoir 6 et 1 en même temps.

Pour tester un cas : remplacez de.Next(1, 7) par 6, puis par 1, puis par 3. N'oubliez pas de remettre de.Next(1, 7) à la fin.

Je sais faire

Une case qui coince ? Relisez la partie concernée avant de passer à la fiche suivante.

← Fiche 8 Fiche 10 : Répéter tant que →