games / lua
Conditions et boucles
Explication
Contrôler l'ordre d'exécution du programme
Une fois qu'on sait manipuler des valeurs (leçon précédente), l'étape suivante est de décider QUAND et COMBIEN DE FOIS une portion de code doit s'exécuter. C'est le rôle des structures conditionnelles (if/else) et des boucles (while, for, repeat).
Ce que vous allez apprendre
- Écrire des conditions
if/elseif/elseà plusieurs branches - Choisir entre
whileetrepeat...untilselon que la condition doit être testée avant ou après - Parcourir une plage de nombres avec
for i = début, fin, pas - Distinguer
ipairs(ordre garanti) depairs(toutes les clés, ordre non garanti) - Simuler un
continueavecgoto ::label::, absent nativement de Lua
Dans quel contexte ?
Un script de serveur RP doit parcourir la liste des joueurs connectés pour leur envoyer un message de bienvenue, tout en ignorant ceux qui sont encore en cours de chargement. Ce genre de traitement — répéter une action pour chaque élément d'une liste, en sautant certains cas particuliers — revient dans presque tous les scripts Lua un peu sérieux, et repose entièrement sur les structures présentées dans cette leçon.
| Structure | Condition testée | Nombre minimum d'exécutions |
|---|---|---|
while | Avant chaque itération | 0 |
repeat...until | Après chaque itération | 1 |
for i = a, b, pas | Implicite (bornes numériques) | 0 |
Astuce
Si tu dois absolument exécuter un bloc au moins une fois (par exemple demander une saisie tant qu'elle n'est pas valide), repeat...until évite d'initialiser artificiellement une variable juste pour entrer dans un while.
while vs repeat...until : une nuance qui a un vrai impact
La différence n'est pas juste stylistique. while teste sa condition AVANT d'exécuter le bloc — si la condition est fausse dès le départ, le bloc ne s'exécute jamais. repeat...until teste sa condition APRÈS avoir exécuté le bloc au moins une fois — et particularité propre à Lua, la condition du until peut voir les variables locales déclarées à l'intérieur du bloc repeat, ce qui n'est généralement pas possible avec un while. Choisir la bonne structure évite des bugs "off-by-one" (une itération en trop ou en moins).
Deux façons de parcourir une collection
for i = début, fin, pas sert pour les boucles numériques classiques (compter de 1 à 10, par exemple). Mais dès qu'on veut parcourir une table (l'équivalent Lua des tableaux/dictionnaires, vue en détail dans la prochaine leçon), on utilise ipairs (pour l'ordre séquentiel) ou pairs (pour toutes les clés, sans ordre garanti) — une distinction essentielle à bien comprendre avant même d'aborder les tables en profondeur.
L'absence volontaire de "continue"
Contrairement à beaucoup de langages, Lua n'a pas de mot-clé continue pour passer directement à l'itération suivante. Le langage propose à la place goto avec une étiquette, un choix de conception qui peut surprendre mais reste parfaitement lisible une fois l'habitude prise — et qui permet même de sortir proprement de boucles imbriquées, ce qu'un simple break ne peut pas faire seul (il ne sort que d'UNE seule boucle).
Commandes & code
Conditions et boucles
-- if / elseif / else
local score = 87
if score >= 90 then
print("A")
elseif score >= 80 then
print("B")
elseif score >= 70 then
print("C")
else
print("F")
end-- Boucle "while" : condition testée avant chaque itération
local hp = 100
while hp > 0 do
hp = hp - 25
print("HP restant: " .. hp)
end-- Boucle "repeat...until" : condition testée APRÈS chaque itération (exécute au moins une fois)
-- Particularité Lua : la condition "until" a accès aux variables locales déclarées dans le bloc "repeat"
local attempts = 0
repeat
attempts = attempts + 1
local success = attempts >= 3 -- visible dans la condition "until" ci-dessous
until success
print("Réussi après " .. attempts .. " tentatives")-- Boucle "for" numérique : for var = début, fin, pas do ... end
for i = 1, 5 do
print(i) -- 1 2 3 4 5
end
for i = 10, 0, -2 do -- pas négatif : compte à rebours par pas de 2
print(i) -- 10 8 6 4 2 0
end-- Boucle "for" générique avec ipairs (tableaux séquentiels, indices entiers 1..n sans trou)
local weapons = {"epee", "arc", "baton"}
for index, value in ipairs(weapons) do
print(index, value) -- 1 epee 2 arc 3 baton
end
-- pairs (parcourt TOUTES les clés, y compris non-entières, ordre non garanti)
local player = {name = "Alice", level = 12, class = "Mage"}
for key, value in pairs(player) do
print(key, value) -- ordre non déterministe entre les exécutions
end-- break interrompt la boucle ; Lua N'A PAS de "continue" natif -> pattern de contournement classique
for i = 1, 10 do
if i > 5 then
break -- sort complètement de la boucle
end
print(i)
end
for i = 1, 10 do
if i % 2 == 0 then
goto continue -- goto vers un label : pattern idiomatique pour simuler "continue"
end
print(i) -- n'affiche que les nombres impairs
::continue::
end-- Boucles imbriquées avec labels distincts pour un "break" ciblé (goto au niveau externe)
for i = 1, 3 do
for j = 1, 3 do
if i == 2 and j == 2 then
goto continue_outer -- sort des DEUX boucles d'un coup
end
print(i, j)
end
end
::continue_outer::Résumé
whileteste avant,repeat...untilteste après (et voit les locales du bloc dans sa condition).for i = début, fin, paspour les boucles numériques ;ipairs/pairspour parcourir des tables.- Lua n'a pas de
continue: le patterngoto ::continue::en tient lieu. breakne sort que d'une seule boucle ; ungotoexterne permet de sortir de boucles imbriquées.
Exercices pratiques
Mission : réparer la boucle de bienvenue du serveur RP
Objectif : Corriger un script qui doit saluer les joueurs connectés en ignorant ceux encore en chargement, et justifier chaque choix de structure.
Contexte
Un script de bienvenue RP contient ce code, censé saluer chaque joueur connecté sauf ceux encore marqués loading = true :
local players = {
{ name = "Alice", loading = false },
{ name = "Bob", loading = true },
{ name = "Chloe", loading = false },
}
for i, p in pairs(players) do
if p.loading then
print("Bienvenue " .. p.name)
end
endRésultat en production : seul Bob reçoit un message de bienvenue (celui encore en chargement !), et l'ordre d'affichage change parfois d'une exécution à l'autre sur un serveur avec beaucoup plus de joueurs et des clés supplémentaires dans la table.