Bien démarrer un exercice de programmation
Avant de taper la moindre ligne de code, je réponds à 6 questions. Chaque question a sa couleur : je m'en sers pour surligner l'énoncé.
Qu'est-ce que je dois RETENIR ?
Ce que l'utilisateur me donne et ce que je calcule : tout ce qui doit rester en mémoire.
int age;Qu'est-ce que je dois DEMANDER ?
Les informations que l'utilisateur doit taper. Une question = une réponse à lire.
Console.ReadLine()Qu'est-ce que je dois RÉPÉTER ?
Les actions qui reviennent plusieurs fois : combien de fois, et jusqu'à quand ?
while · forQu'est-ce que je dois VÉRIFIER ?
Les cas où le programme doit choisir : « si… alors… sinon… ».
if · switchQu'est-ce que je dois CALCULER ?
Les opérations à faire avec mes variables : un prix, un total, un texte à compléter…
prix = prix + 15;Qu'est-ce que je dois AFFICHER ?
Tout ce que l'utilisateur voit : le titre, les questions, et bien sûr le résultat.
Console.WriteLine()Astuce : je surligne l'énoncé avec les 6 couleurs
« Le héros entre dans un donjon avec 100 PV. Le programme demande le nombre de salles à parcourir. Dans chaque salle, on tire un nombre au hasard. S'il vaut 1, le héros perd 10 PV, sinon il gagne 10 PO. À la fin, on affiche ses PV. »
Souligné violet : à retenir · bleu : à demander · vert : à répéter · turquoise : à vérifier · rose : à calculer · orange : à afficher.
Ensuite, mon programme suit 5 étapes
↻ Ce n'est pas une ligne droite. Vérifier et calculer s'alternent souvent, et je reviens en arrière quand il me manque quelque chose (voir page 5).
Étape 1 · Repérer les variables
Qu'est-ce que je dois retenir ?
- Quelles informations l'utilisateur va-t-il me donner ?
- Quels résultats dois-je calculer et garder ?
- Pour chaque variable : quel type ? (nombre entier, nombre à virgule, texte…)
- Quel nom clair ?
nbPersonnesouprixTotal, plutôt queaoux.
| Ce que je retiens | Type | Je déclare | Pour lire la réponse |
|---|---|---|---|
| Un nombre entier (âge, personnes) | int | int age; | int.Parse(Console.ReadLine()) |
| Un nombre à virgule (prix, moyenne) | double | double prix; | double.Parse(Console.ReadLine()) |
| Du texte (nom, « oui » / « non ») | string | string nom; | Console.ReadLine() · rien à convertir |
| Un seul caractère (choix de menu) | char | char choix; | char.Parse(Console.ReadLine()) |
| Vrai ou faux | bool | bool estMembre; | souvent calculé par le programme |
| Un nombre tiré au hasard (dé, salle…) | Random | Random de = new Random(); | de.Next(1, 5) · donne 1, 2, 3 ou 4 |
Étape 2 · Les entrées
Qu'est-ce que je dois demander ?
Pour chaque information à demander, j'écris toujours le même trio :
Console.Write("…");Console.ReadLine()// ① afficher la question Console.Write("Quel est ton âge ? : "); // ② lire la réponse ③ la ranger (int.Parse : c'est un nombre) age = int.Parse(Console.ReadLine()); Console.Write("Quel est ton prénom ? : "); prenom = Console.ReadLine(); // du texte : pas de conversion
Write ou WriteLine ?
WriteLine passe à la ligne après le texte. Write reste sur la même ligne : la réponse s'écrit juste après la question, comme « Quel est ton âge ? : 15 ».
Attention au texte
« oui », « Oui » et « OUI » sont trois textes différents pour l'ordinateur. J'indique dans la question ce qu'il faut taper : (oui/non).
Étape 3 · Répéter
Qu'est-ce que je dois répéter ? Combien de fois ?
- Que dois-je répéter ? Les actions qui reviennent à l'identique (le « corps » de la boucle).
- Combien de fois, ou jusqu'à quand ? C'est la condition : tant qu'elle est vraie, je recommence.
- Que dois-je tester à chaque tour ? Une variable qui change à chaque tour (le compteur) et qui finira par rendre la condition fausse.
// ① AVANT : je prépare le compteur int salleActuelle = 1; // ② TEST : tant que c'est vrai, je fais un tour de plus while (salleActuelle <= nbreSalles) { // ③ CORPS : ce que je répète à chaque tour Console.WriteLine("Salle " + salleActuelle); // ④ je fais avancer le compteur (sinon : boucle infinie !) salleActuelle++; } // ⑤ APRÈS : la boucle est finie, le programme continue ici
Je suis la boucle pas à pas, avec nbreSalles = 3
| Tour | salleActuelle | Test salleActuelle <= 3 | Affichage | Après le tour |
|---|---|---|---|---|
| 1 | 1 | vrai : j'entre | Salle 1 | devient 2 |
| 2 | 2 | vrai : j'entre | Salle 2 | devient 3 |
| 3 | 3 | vrai : j'entre | Salle 3 | devient 4 |
| 4 | 4 | faux : je sors | rien | la boucle s'arrête |
Les raccourcis et les combinaisons à connaître
| J'écris | Cela veut dire | Exemple |
|---|---|---|
x++; | ajoute 1 à x (comme x = x + 1;) | salleActuelle++; |
x += 10; · x -= 10; | ajoute / retire 10 à x | pv -= 10; |
&& (et) | les deux tests doivent être vrais | salleActuelle <= nbreSalles && pv > 0 |
|| (ou) | un des deux tests suffit | nbre == 1 || nbre == 4 |
Pièges fréquents
- J'oublie
salleActuelle++;: le test reste vrai pour toujours, c'est une boucle infinie (je l'arrête avecCtrl + C). - Avec
<au lieu de<=, je fais un tour de moins. - Je crée le
Randomavant la boucle, une seule fois.
while ou for ?
while teste avant chaque tour : si la condition est fausse dès le départ (0 salle), il ne fait aucun tour.
for regroupe compteur, test et avance sur une seule ligne, pratique quand je connais le nombre de tours : for (int i = 1; i <= 3; i++)
Étape 4 · Vérifier et calculer
Qu'est-ce que je dois vérifier ? Qu'est-ce que je dois calculer ?
Vérifier
- Le programme doit-il choisir ? Entre combien de cas ?
- Quelle est la condition de chaque cas ?
- Ai-je prévu le « sinon » quand rien n'est vrai ?
Calculer
- Quelle opération, avec quelles variables ?
- Dans quelle variable je range le résultat ?
- Le calcul dépend-il d'un choix ? Alors il va dans le
if.
| Ma situation | Mon outil | Exemple |
|---|---|---|
| Deux cas : oui ou non | if … else | majeur ou mineur |
| Plusieurs cas avec des plages (moins de 12 ans, 65 ans et plus…) | if … else if … else | prix selon l'âge |
| Une variable comparée à des valeurs précises (1, 2, 3 ou 'A', 'B') | switch … case … default | choix dans un menu |
L'ordre des tests compte !
L'ordinateur lit les tests de haut en bas et s'arrête au premier test vrai. Les tests en dessous ne sont même pas lus.
Au cinéma : 65 ans et plus → 7 €, 12 ans et plus → 10 €, sinon 6 €. Je teste avec age = 70.
if (age >= 12) // VRAI : stop { prix = 10; } else if (age >= 65) // jamais lu ! { prix = 7; } else { prix = 6; }
Résultat : 10 €. Faux : la réduction des 65 ans n'est jamais atteinte.
if (age >= 65) // VRAI : stop
{
prix = 7;
}
else if (age >= 12)
{
prix = 10;
}
else
{
prix = 6;
}
Résultat : 7 €. Correct !
Règle : je teste d'abord le cas le plus précis (le plus « rare »), puis le plus large. Le else final attrape tout ce qui reste.
Pièges fréquents
=range une valeur ;==compare deux valeurs.- Un texte se compare entre guillemets :
reponse == "oui". - Jamais de
;juste aprèsif (…): le test ne servirait plus à rien. - Dans un
switch, chaquecasefinit parbreak;etdefaultgère les réponses imprévues.
Étape 5 · Afficher et tester
Qu'est-ce que je dois afficher ?
- Qu'est-ce que l'utilisateur doit voir ? Pas seulement le résultat : aussi le titre et les questions.
- Mon message est-il une phrase claire, et pas juste un nombre seul ?
- Mon affichage est-il identique au visuel demandé (espaces, ponctuation, lignes vides) ?
Console.WriteLine("Ta place coûte "
+ prix + " euros.");
À l'écran : Ta place coûte 7 euros.
Console.WriteLine(); seul affiche une ligne vide.
Puis je teste avec plusieurs valeurs
- Une valeur normale : l'exemple de l'énoncé doit donner exactement le résultat attendu.
- Une valeur limite, pile sur la frontière d'un test : 12 ans, 65 ans, 3 personnes…
- Chaque branche au moins une fois : chaque
if, chaqueelse if, leelse.
↻ Ce n'est pas une ligne droite
Les 5 étapes donnent l'ordre général. Mais dans un vrai programme, j'alterne : je demande, je répète, et à chaque tour je calcule, je vérifie, je calcule encore. Voici l'ordre réel du programme Radakass (pages 6 à 8). Les étapes 4 à 8 sont répétées à chaque tour de boucle :
Je reviens en arrière quand…
- il me manque une information → j'ajoute une variable (étape 1) et une question (étape 2) ;
- un résultat dépend d'un autre résultat → j'écris un deuxième
ifaprès le premier ; - mon programme ne s'arrête jamais → je vérifie que mon compteur avance (
salleActuelle++) et que la condition de la boucle peut devenir fausse ; - le résultat est faux → je relis l'énoncé et je vérifie l'ordre de mes tests.
Mes bonnes habitudes
- J'écris d'abord mon plan en français, en commentaires :
// demander l'âge, puis je traduis en C#. - J'exécute mon programme souvent, après chaque petite partie, au lieu de tout taper d'un coup.
Exemple complet : le donjon de Radakass
D'abord je lis l'énoncé, ensuite j'analyse avec les 6 questions. Le code vient seulement après.
Énoncé
- Radakass entre dans un donjon avec 100 PV : on l'affiche.
- On demande à l'utilisateur le nombre de salles que Radakass doit parcourir.
- Dans chaque salle, on tire un nombre aléatoire entre 1 et 4.
- Si le nombre est 1 ou 4 : Radakass perd 10 PV. Si c'est 2 : il gagne 10 PO. Sinon (3) : il regagne 5 PV.
- À la fin, on affiche que Radakass est mort, sinon les PO gagnés.
Mon analyse avant de coder
pv, po : int (départ 100 et 0)
nbreSalles : int
salleActuelle : int (départ 1)
nbreAleatoire : int
dice : Random
int.Parse.
salleActuelle++
pv > 0 ?
dice.Next(1, 5)
pv -= 10 · po += 10 · pv += 5
Le compteur : salleActuelle++
Next(1, 5) donne 1, 2, 3 ou 4 : la borne haute est exclue. Les 3 cas ne se chevauchent pas, donc leur ordre n'a pas d'importance ici. $"…{pv}…" insère la valeur d'une variable dans le texte.
Le code Radakass (1/2)
Chaque commentaire porte la couleur de sa question : on retrouve l'analyse de la page 6.
// ===== 1. RETENIR : les variables ===== int pv = 100; int po = 0; int nbreSalles; int salleActuelle = 1; int nbreAleatoire; Random dice = new Random(); // ===== AFFICHER : l'accroche ===== Console.WriteLine($"Radakass entre dans le donjon avec {pv} PV"); // ===== 2. DEMANDER : le nombre de salles ===== Console.Write("Combien de salles de donjon doit-il parcourir ? : "); nbreSalles = int.Parse(Console.ReadLine()); // ===== 3. RÉPÉTER : tant qu'il reste des salles ET que Radakass est vivant ===== while (salleActuelle <= nbreSalles && pv > 0) { // CALCULER : tirer le nombre (1, 2, 3 ou 4) nbreAleatoire = dice.Next(1, 5); // AFFICHER : la salle et le nombre tiré Console.WriteLine($"Dans la salle {salleActuelle} : {nbreAleatoire}"); // 4. VÉRIFIER puis CALCULER : que se passe-t-il dans cette salle ? if (nbreAleatoire == 1 || nbreAleatoire == 4) { pv -= 10; Console.WriteLine($"Radakass perd 10PV, il lui reste {pv} pv"); } else if (nbreAleatoire == 2) { po += 10; Console.WriteLine($"Radakass trouve 10PO, il a en tout {po} po"); } else // tous les autres cas : 3 { pv += 5; Console.WriteLine($"Radakass se repose et regagne 5pv, il a en tout {pv} pv"); } Console.ReadKey(); // attend qu'on appuie sur une touche salleActuelle++; // le compteur avance : la boucle finira par s'arrêter }
Sans salleActuelle++, la boucle ne s'arrêterait jamais. Suite du code page 8.
Le code Radakass (2/2)
// ===== 4. VÉRIFIER : Radakass a-t-il survécu ? (après la boucle) ===== if (pv > 0) { // AFFICHER : le bilan Console.WriteLine($"Radakass est vivant et a empoché : {po} po"); } else { Console.WriteLine($"Radakass a péri... ses {po} po gisent dans les ténèbres..."); } Console.ReadKey();
Je teste avant de rendre
| Nombre de salles | Ce que je dois voir | Ce que je vérifie |
|---|---|---|
| 3 | 3 messages « Dans la salle… », puis le bilan | l'exemple de l'énoncé |
| 0 | aucune salle, bilan direct : vivant, 0 po | la boucle ne fait aucun tour |
| 1 | un seul message de salle, puis le bilan | limite : un seul tour |
| 50 | Radakass meurt très probablement avant la salle 50 : la boucle s'arrête | le test pv > 0 dans la condition |
| 1 à 3 | je remplace dice.Next(1, 5) par 1, puis 2, puis 3, puis 4 | chaque branche du if, y compris 4 |