Ce programme propose une version complète du célèbre jeu Lights Out, entièrement écrite en pseudo-code français. Le principe est simple : chaque clic bascule une case et ses quatre voisines. Le but est d’éteindre toutes les lumières du plateau… mais derrière cette simplicité se cache une mécanique algorithmique très riche.
Un plateau 5×5, entre logique et stratégie
Le jeu repose sur une grille de 25 cases, chacune pouvant être :
- éteinte (0),
- allumée (1).
Chaque niveau commence par un brouillage aléatoire, obtenu en simulant des appuis au hasard. Cette méthode garantit que la grille est toujours résoluble, ce qui est essentiel pour un puzzle logique.
Le fonctionnement du clic : un basculement en croix
Lorsqu’on clique sur une case :
- la case centrale bascule,
- la case de droite bascule,
- la case de gauche bascule,
- la case du haut bascule,
- la case du bas bascule.
Ce comportement en croix est la signature du jeu Lights Out.
Une propriété mathématique intéressante est exploitée : appuyer deux fois au même endroit annule l’effet, ce qui permet de gérer la solution comme un simple ensemble de bascules.
Un indice intégré : les appuis restants pour gagner
Le programme calcule et affiche un indice optionnel : les cases sur lesquelles il reste à appuyer pour résoudre la grille.
Ces cases apparaissent sous forme de points blancs, uniquement lorsque le joueur clique sur le bouton "Indice".
C’est une aide précieuse pour comprendre la logique du puzzle, sans donner la solution complète d’un coup.
Un brouillage progressif selon le niveau
Chaque victoire :
- augmente le niveau,
- augmente le nombre d’appuis aléatoires utilisés pour brouiller la grille
- rend donc la grille plus complexe.
Le jeu devient progressivement plus difficile, tout en restant toujours résoluble.
Une interface claire et agréable
Le programme affiche :
- un en-tête avec le niveau, le nombre de coups et le nombre de lumières allumées,
- un plateau coloré avec halo lumineux pour les cases allumées,
- un bouton "Nouvelle grille",
- un bouton "Indice",
- un message d’aide dynamique.
L’ensemble donne une expérience fluide, intuitive et très visuelle.
Un écran de victoire motivant
Quand toutes les lumières sont éteintes :
- un écran de victoire apparaît,
- le nombre de coups est affiché,
- le joueur est invité à passer au niveau suivant.
C’est une boucle de progression simple mais efficace.
Un excellent exercice d’algorithmique
Ce programme est idéal pour travailler :
- la manipulation de tableaux 2D,
- la gestion d’un puzzle logique,
- la mise en place d’un système d’indice,
- la création d’une interface graphique interactive,
- la logique des transformations locales (basculement en croix),
- la génération de grilles résolubles.
C’est un projet parfait pour les élèves en SNT, NSI, ou toute personne souhaitant comprendre comment on code un puzzle logique de A à Z.
Programme :
@ Configuration
maToile est une toile
dimension(maToile, 400, 570)
// Plateau 5x5 : 0 = lumière éteinte, 1 = lumière allumée
plateau est un tableau
// Cases sur lesquelles il reste à appuyer pour gagner (l'indice)
plateauIndice est un tableau
pour i de 0 à 4
ligne_p est un tableau
ligne_a est un tableau
pour j de 0 à 4
ligne_p ajoute 0
ligne_a ajoute 0
fin pour
plateau ajoute ligne_p
plateauIndice ajoute ligne_a
fin pour
niveau est un nombre
niveau vaut 1
coups est un nombre
coups vaut 0
avecIndice est un booléen
avecIndice vaut faux
message est un texte
message vaut "Un clic bascule la case et ses 4 voisines"
// Décalages des 5 cases touchées par un appui : centre, droite,
// gauche, bas, haut. Décalés de +1 pour éviter les nombres négatifs.
decCol est un tableau
decLig est un tableau
decCol ajoute 1
decLig ajoute 1
decCol ajoute 2
decLig ajoute 1
decCol ajoute 0
decLig ajoute 1
decCol ajoute 1
decLig ajoute 2
decCol ajoute 1
decLig ajoute 0
@ Appui sur une case
// Bascule la case et ses voisines, puis met à jour l'indice.
// Astuce mathématique : appuyer deux fois au même endroit ne change
// rien, donc l'ensemble des appuis restants se met à jour par une
// simple bascule lui aussi.
procédure basculerCases(lig, cln)
rr est un nombre
cc est un nombre
pour d de 0 à 4
rr vaut lig + decLig[d] - 1
cc vaut cln + decCol[d] - 1
si rr >= 0 et rr <= 4 et cc >= 0 et cc <= 4 alors
si plateau[rr][cc] = 1 alors
plateau[rr][cc] vaut 0
sinon
plateau[rr][cc] vaut 1
fin si
fin si
fin pour
si plateauIndice[lig][cln] = 1 alors
plateauIndice[lig][cln] vaut 0
sinon
plateauIndice[lig][cln] vaut 1
fin si
fin procédure
@ Brouillage du plateau
// On part d'un plateau entièrement éteint et on appuie au hasard :
// la grille obtenue est donc forcément résoluble.
procédure brouillerPlateau(nbClics)
ligH est un nombre
clnH est un nombre
pour i de 0 à 4
pour j de 0 à 4
plateau[i][j] vaut 0
plateauIndice[i][j] vaut 0
fin pour
fin pour
pour n de 1 à nbClics
ligH vaut hasard(0, 4)
clnH vaut hasard(0, 4)
appelle basculerCases(ligH, clnH)
fin pour
fin procédure
@ Comptage des lumières allumées
fonction nbAllumees()
n est un nombre
n vaut 0
pour i de 0 à 4
pour j de 0 à 4
si plateau[i][j] = 1 alors
n ajoute 1
fin si
fin pour
fin pour
retourne n
fin fonction
@ Comptage des appuis restants dans l'indice
fonction nbIndices()
n est un nombre
n vaut 0
pour i de 0 à 4
pour j de 0 à 4
si plateauIndice[i][j] = 1 alors
n ajoute 1
fin si
fin pour
fin pour
retourne n
fin fonction
@ Affichage complet
procédure afficherJeu(t, niv, cp, msg, aide)
effacer(t)
remplir(t, #0B1020)
nbOn est un nombre
nbAide est un nombre
nbOn vaut nbAllumees()
nbAide vaut nbIndices()
// En-tête
rectangle_arrondi(t, 10, 10, 380, 100, 16, #1E293B)
label(t, 22, 44, "LIGHTS OUT", #F8FAFC, 24)
label(t, 22, 72, "Niveau " + niv, #CBD5E1, 15)
label(t, 230, 72, "Coups : " + cp, #93C5FD, 15)
label(t, 22, 98, "Allumées : " + nbOn + " / 25", #CBD5E1, 13)
label(t, 230, 98, "Indice : " + nbAide + " appuis", #FDE68A, 13)
// Plateau : case de 64 px, écart de 72 px, coin en 20 et 130
xP est un nombre
yP est un nombre
pour i de 0 à 4
pour j de 0 à 4
xP vaut 20 + j * 72
yP vaut 130 + i * 72
// Ombre portée
rectangle_arrondi(t, xP + 2, yP + 4, 64, 64, 16, #070B16)
si plateau[i][j] = 1 alors
// Lumière allumée : halo puis tuile jaune
rectangle_arrondi(t, xP - 4, yP - 4, 72, 72, 20, #3A2E12)
rectangle_arrondi(t, xP, yP, 64, 64, 16, #FFC53D)
rectangle_arrondi(t, xP + 8, yP + 7, 48, 14, 7, #FFE9A8)
sinon
// Lumière éteinte
rectangle_arrondi(t, xP, yP, 64, 64, 16, #172036)
rectangle_arrondi(t, xP + 8, yP + 7, 48, 14, 7, #1F2B45)
fin si
// Point blanc : case faisant partie de la solution
si aide = vrai alors
si plateauIndice[i][j] = 1 alors
rectangle_arrondi(t, xP + 26, yP + 26, 12, 12, 6, #FFFFFF)
fin si
fin si
fin pour
fin pour
// Boutons
rectangle_arrondi(t, 10, 496, 180, 44, 14, #334155)
label(t, 50, 524, "Nouvelle grille", #F8FAFC, 15)
rectangle_arrondi(t, 210, 496, 180, 44, 14, #334155)
label(t, 275, 524, "Indice", #FDE68A, 15)
label(t, 14, 560, msg, #FDE68A, 13)
affiche t
fin procédure
@ Écran de victoire
procédure afficherFin(t, niv, cp)
rectangle_arrondi(t, 40, 190, 320, 180, 20, #1E293B)
label(t, 70, 240, "TOUT ÉTEINT !", #FDE68A, 26)
label(t, 70, 278, "Niveau " + niv + " réussi en " + cp + " coups", #F8FAFC, 15)
label(t, 70, 306, "Le niveau suivant sera plus brouillé", #CBD5E1, 13)
label(t, 70, 348, "Clique pour continuer", #93C5FD, 14)
affiche t
fin procédure
@ Boucle principale
nbBrouillage est un nombre
nbBrouillage vaut 3
appelle brouillerPlateau(nbBrouillage)
tant que nbAllumees() = 0
appelle brouillerPlateau(nbBrouillage)
fin tant que
enJeu est un booléen
enJeu vaut vrai
tant que enJeu = vrai
appelle afficherJeu(maToile, niveau, coups, message, avecIndice)
x_clic est un nombre
y_clic est un nombre
cliquer maToile dans x_clic, y_clic
// L'indice ne reste affiché que le temps d'un clic
avecIndice vaut faux
si y_clic >= 496 et y_clic <= 540 alors
si x_clic <= 195 alors
// Bouton "Nouvelle grille" : même niveau, autre brouillage
appelle brouillerPlateau(nbBrouillage)
tant que nbAllumees() = 0
appelle brouillerPlateau(nbBrouillage)
fin tant que
coups vaut 0
message vaut "Nouvelle grille au niveau " + niveau
sinon
// Bouton "Indice"
avecIndice vaut vrai
message vaut "Les points blancs sont les appuis à faire"
fin si
sinon si y_clic >= 130 et y_clic < 490 et x_clic >= 20 et x_clic < 380 alors
clnClic est un nombre
ligClic est un nombre
clnClic vaut arrondi_inferieur((x_clic - 20) / 72)
ligClic vaut arrondi_inferieur((y_clic - 130) / 72)
clnClic vaut limiter(clnClic, 0, 4)
ligClic vaut limiter(ligClic, 0, 4)
appelle basculerCases(ligClic, clnClic)
coups ajoute 1
message vaut "5 lumières basculées"
si nbAllumees() = 0 alors
appelle afficherJeu(maToile, niveau, coups, "Bravo !", faux)
appelle afficherFin(maToile, niveau, coups)
xFin est un nombre
yFin est un nombre
cliquer maToile dans xFin, yFin
niveau ajoute 1
coups vaut 0
nbBrouillage vaut limiter(2 + niveau, 3, 14)
appelle brouillerPlateau(nbBrouillage)
tant que nbAllumees() = 0
appelle brouillerPlateau(nbBrouillage)
fin tant que
message vaut "Niveau " + niveau + " : " + nbBrouillage + " appuis cachés"
fin si
fin si
fin tant que





