Console
Clique sur « Exécuter » pour lancer le programme.
Code CoddyRun
@ CONFIGURATION
ecran est une toile
dimension(ecran, 400, 560)
MAXN est une constante vaut 12
// Réglages des 3 niveaux (index 0, 1, 2)
cfgTaille est un tableau
cfgMines est un tableau
cfgNom est un tableau
cfgTaille ajoute 8
cfgTaille ajoute 10
cfgTaille ajoute 12
cfgMines ajoute 10
cfgMines ajoute 18
cfgMines ajoute 30
cfgNom ajoute "Facile"
cfgNom ajoute "Moyen"
cfgNom ajoute "Difficile"
@ PLATEAU (12 x 12 au maximum)
mine est un tableau
voisins est un tableau
etatCase est un tableau
// etatCase : 0 = cachée, 1 = ouverte, 2 = drapeau
pour i de 0 à MAXN - 1
ligMine est un tableau
ligVois est un tableau
ligEtat est un tableau
pour j de 0 à MAXN - 1
ligMine ajoute faux
ligVois ajoute 0
ligEtat ajoute 0
fin pour
mine ajoute ligMine
voisins ajoute ligVois
etatCase ajoute ligEtat
fin pour
@ RECORDS ET STATISTIQUES (conservés entre deux lancements)
meilleurs est un tableau
valeurLue est un nombre
pour d de 1 à 3
essayer
valeurLue vaut paramètre('demineur', 'record' + convertir_texte(d))
attraper
valeurLue vaut 0
paramètre('demineur', 'record' + convertir_texte(d), 0)
fin essayer
meilleurs ajoute valeurLue
fin pour
jouees est un nombre
gagnees est un nombre
essayer
jouees vaut paramètre('demineur', 'jouees')
attraper
jouees vaut 0
paramètre('demineur', 'jouees', 0)
fin essayer
essayer
gagnees vaut paramètre('demineur', 'gagnees')
attraper
gagnees vaut 0
paramètre('demineur', 'gagnees', 0)
fin essayer
@ VARIABLES DE LA PARTIE
ecranActuel est un nombre
// 0 = menu, 1 = partie
ecranActuel vaut 0
quitter, lancer, aideVisible, redessiner est un booléen
redessiner vaut vrai
diff, NL, nbMines, cs, x0, y0 est un nombre
premierCoup, fini, gagne, modeDrapeau, nouveauRecord est un booléen
drapeaux, revelees, indicesRestants, penalite est un nombre
tempsDebut, tempsFinal, secondes, derniereSeconde est un nombre
explL, explC, indiceL, indiceC est un nombre
survolL, survolC, ancienSurvolL, ancienSurvolC est un nombre
message est un texte
diff vaut 1
NL vaut 8
cs vaut 45
x0 vaut 20
y0 vaut 96
// Variables de travail
clic, toucheF, toucheEchap, toucheR est un booléen
xc, yc, lClic, cClic, vr, vc, rl, rc, places, compte, codeCase est un nombre
boum, open, encore, claire, montrer, explose, survole, voisinOuvert est un booléen
cand1, cand2 est un tableau
px, py, pct est un nombre
txt est un texte
@ PROCÉDURES DE DESSIN
procédure dessinerMine(t, cx, cy, r)
ligne(t, cx - r * 1.35, cy, cx + r * 1.35, cy, #212121, 2)
ligne(t, cx, cy - r * 1.35, cx, cy + r * 1.35, #212121, 2)
ligne(t, cx - r, cy - r, cx + r, cy + r, #212121, 2)
ligne(t, cx - r, cy + r, cx + r, cy - r, #212121, 2)
cercle(t, cx, cy, r, #212121)
cercle(t, cx - r * 0.35, cy - r * 0.35, r * 0.28, #FFFFFF)
fin procédure
procédure dessinerDrapeau(t, cx, cy, s)
rectangle_arrondi(t, cx - s * 0.26, cy + s * 0.24, s * 0.44, s * 0.09, 2, #5D4037)
ligne(t, cx - s * 0.06, cy - s * 0.32, cx - s * 0.06, cy + s * 0.26, #5D4037, maximum(2, s / 16))
triangle(t, cx - s * 0.06, cy - s * 0.34, cx - s * 0.06, cy + s * 0.02, cx + s * 0.32, cy - s * 0.16, #F44336)
fin procédure
procédure dessinerHorloge(t, cx, cy, r)
cercle(t, cx, cy, r, #FFFFFF)
cercle(t, cx, cy, r * 0.75, #4A752C)
ligne(t, cx, cy, cx, cy - r * 0.55, #FFFFFF, 2)
ligne(t, cx, cy, cx + r * 0.45, cy, #FFFFFF, 2)
fin procédure
procédure dessinerFondBouton(t, bx, by, lb, hb, fond)
rectangle_arrondi(t, bx, by + 3, lb, hb, 12, rgba(0, 0, 0, 0.3))
rectangle_arrondi(t, bx, by, lb, hb, 12, fond)
rectangle_arrondi(t, bx + 8, by + 5, lb - 16, hb / 6, 4, rgba(255, 255, 255, 0.15))
fin procédure
procédure dessinerBouton(t, bx, by, lb, hb, texteB, fond, coulTexte, taillePolice)
rectangle_arrondi(t, bx, by + 3, lb, hb, 12, rgba(0, 0, 0, 0.3))
rectangle_arrondi(t, bx, by, lb, hb, 12, fond)
rectangle_arrondi(t, bx + 8, by + 5, lb - 16, hb / 6, 4, rgba(255, 255, 255, 0.15))
label(t, bx + lb / 2 - label_largeur(texteB, taillePolice) / 2, by + hb / 2 + taillePolice * 0.36, texteB, coulTexte, taillePolice)
fin procédure
procédure dessinerCase(t, x, y, c, etatC, estMine, nbV, claire2, montrer2, explose2, survol2)
fond est un texte
coulN est un texte
chiffreTxt est un texte
taillePolice est un nombre
cx est un nombre
cy est un nombre
cx vaut x + c / 2
cy vaut y + c / 2
si etatC = 1 alors
// ---- Case ouverte ----
si explose2 = vrai alors
fond vaut #E53935
sinon si claire2 = vrai alors
fond vaut #E5C29F
sinon
fond vaut #D7B899
fin si
rectangle(t, x, y, c, c, fond)
si estMine = vrai alors
appelle dessinerMine(t, cx, cy, c * 0.24)
sinon si nbV > 0 alors
si nbV = 1 alors
coulN vaut #1976D2
sinon si nbV = 2 alors
coulN vaut #388E3C
sinon si nbV = 3 alors
coulN vaut #D32F2F
sinon si nbV = 4 alors
coulN vaut #7B1FA2
sinon si nbV = 5 alors
coulN vaut #FF8F00
sinon si nbV = 6 alors
coulN vaut #0097A7
sinon si nbV = 7 alors
coulN vaut #424242
sinon
coulN vaut #9E9E9E
fin si
chiffreTxt vaut convertir_texte(nbV)
taillePolice vaut arrondi(c * 0.55)
label(t, cx - label_largeur(chiffreTxt, taillePolice) / 2, cy + taillePolice * 0.36, chiffreTxt, coulN, taillePolice)
fin si
sinon
// ---- Case cachée (herbe) ----
si claire2 = vrai alors
fond vaut #AAD751
sinon
fond vaut #A2D149
fin si
rectangle(t, x, y, c, c, fond)
rectangle(t, x, y, c, c * 0.12, rgba(255, 255, 255, 0.18))
si survol2 = vrai alors
rectangle(t, x, y, c, c, rgba(255, 255, 255, 0.35))
fin si
si montrer2 = vrai et estMine = vrai et etatC = 0 alors
rectangle(t, x, y, c, c, rgba(0, 0, 0, 0.12))
appelle dessinerMine(t, cx, cy, c * 0.24)
fin si
si etatC = 2 alors
appelle dessinerDrapeau(t, cx, cy, c)
// Drapeau posé au mauvais endroit : on le barre en fin de partie
si montrer2 = vrai et estMine = faux alors
ligne(t, x + c * 0.2, y + c * 0.2, x + c * 0.8, y + c * 0.8, #B71C1C, 3)
ligne(t, x + c * 0.8, y + c * 0.2, x + c * 0.2, y + c * 0.8, #B71C1C, 3)
fin si
fin si
fin si
fin procédure
procédure dessinerBoutonRejouer(t, x, y)
rectangle_arrondi(t, x, y + 3, 40, 40, 10, rgba(0, 0, 0, 0.3))
rectangle_arrondi(t, x, y, 40, 40, 10, #5E8C3A)
cercle(t, x + 20, y + 21, 12, #FFFFFF)
cercle(t, x + 20, y + 21, 7, #5E8C3A)
rectangle(t, x + 20, y + 7, 14, 14, #5E8C3A)
pF est un tableau
pF ajoute x + 16
pF ajoute y + 5
pF ajoute x + 30
pF ajoute y + 9
pF ajoute x + 22
pF ajoute y + 19
polygone(t, pF, #FFFFFF)
fin procédure
procédure dessinerBoutonMenu(t, x, y)
rectangle_arrondi(t, x, y + 3, 40, 40, 10, rgba(0, 0, 0, 0.3))
rectangle_arrondi(t, x, y, 40, 40, 10, #5E8C3A)
rectangle_arrondi(t, x + 10, y + 11, 20, 4, 2, #FFFFFF)
rectangle_arrondi(t, x + 10, y + 18, 20, 4, 2, #FFFFFF)
rectangle_arrondi(t, x + 10, y + 25, 20, 4, 2, #FFFFFF)
fin procédure
@ BOUCLE PRINCIPALE
tant que non quitter
// ---------- Lecture souris / clavier (une fois par tour) ----------
clic vaut souris_clic(ecran)
xc vaut souris_x(ecran)
yc vaut souris_y(ecran)
toucheF vaut touche_pressée('f')
toucheEchap vaut touche_pressée('échap')
toucheR vaut touche_pressée('r')
si clic ou toucheF ou toucheEchap ou toucheR alors
redessiner vaut vrai
fin si
// ---------- Nouvelle partie ----------
si lancer alors
lancer vaut faux
NL vaut cfgTaille[diff - 1]
nbMines vaut cfgMines[diff - 1]
cs vaut arrondi_inferieur(360 / NL)
x0 vaut (400 - NL * cs) / 2
y0 vaut 96
pour i de 0 à MAXN - 1
pour j de 0 à MAXN - 1
mine[i][j] vaut faux
voisins[i][j] vaut 0
etatCase[i][j] vaut 0
fin pour
fin pour
premierCoup vaut vrai
fini vaut faux
gagne vaut faux
modeDrapeau vaut faux
nouveauRecord vaut faux
drapeaux vaut 0
revelees vaut 0
indicesRestants vaut 3
penalite vaut 0
secondes vaut 0
derniereSeconde vaut 0
explL vaut 0 - 1
explC vaut 0 - 1
indiceL vaut 0 - 1
indiceC vaut 0 - 1
message vaut "Clique sur une case pour commencer"
ecranActuel vaut 1
aideVisible vaut faux
redessiner vaut vrai
fin si
// ==================================================
// LOGIQUE DU MENU
// ==================================================
si ecranActuel = 0 alors
si aideVisible alors
si clic ou toucheEchap alors
aideVisible vaut faux
fin si
sinon
si clic alors
si clique(xc, yc, 50, 170, 300, 64) alors
diff vaut 1
lancer vaut vrai
sinon si clique(xc, yc, 50, 250, 300, 64) alors
diff vaut 2
lancer vaut vrai
sinon si clique(xc, yc, 50, 330, 300, 64) alors
diff vaut 3
lancer vaut vrai
sinon si clique(xc, yc, 50, 418, 300, 46) alors
aideVisible vaut vrai
sinon si clique(xc, yc, 50, 476, 300, 46) alors
quitter vaut vrai
fin si
fin si
si toucheEchap alors
quitter vaut vrai
fin si
fin si
// ==================================================
// LOGIQUE DE LA PARTIE
// ==================================================
sinon
si aideVisible alors
si clic ou toucheEchap alors
aideVisible vaut faux
fin si
sinon
si toucheEchap alors
ecranActuel vaut 0
fin si
si toucheR alors
lancer vaut vrai
fin si
si toucheF et non fini alors
modeDrapeau vaut non modeDrapeau
fin si
si clic alors
boum vaut faux
open vaut faux
// ----- Boutons du haut -----
si clique(xc, yc, 250, 20, 40, 40) alors
aideVisible vaut vrai
sinon si clique(xc, yc, 296, 20, 40, 40) alors
lancer vaut vrai
sinon si clique(xc, yc, 342, 20, 40, 40) alors
ecranActuel vaut 0
// ----- Boutons du bas en fin de partie -----
sinon si fini alors
si clique(xc, yc, 222, 482, 76, 52) alors
lancer vaut vrai
sinon si clique(xc, yc, 306, 482, 76, 52) alors
ecranActuel vaut 0
fin si
// ----- Bouton mode creuser / drapeau -----
sinon si clique(xc, yc, 18, 478, 176, 60) alors
modeDrapeau vaut non modeDrapeau
// ----- Bouton indice -----
sinon si clique(xc, yc, 206, 478, 176, 60) alors
si premierCoup alors
message vaut "Creuse d'abord une première case"
sinon si indicesRestants <= 0 alors
message vaut "Plus d'indice pour cette partie"
sinon
vide cand1
vide cand2
pour i de 0 à NL - 1
pour j de 0 à NL - 1
si etatCase[i][j] = 0 et mine[i][j] = faux alors
voisinOuvert vaut faux
pour di de 0 à 2
pour dj de 0 à 2
vr vaut i + di - 1
vc vaut j + dj - 1
si vr >= 0 et vr < NL et vc >= 0 et vc < NL alors
si etatCase[vr][vc] = 1 alors
voisinOuvert vaut vrai
fin si
fin si
fin pour
fin pour
si voisinOuvert alors
cand1 ajoute i * 100 + j
sinon
cand2 ajoute i * 100 + j
fin si
fin si
fin pour
fin pour
codeCase vaut 0 - 1
si longueur(cand1) > 0 alors
codeCase vaut cand1[hasard(0, longueur(cand1) - 1)]
sinon si longueur(cand2) > 0 alors
codeCase vaut cand2[hasard(0, longueur(cand2) - 1)]
fin si
si codeCase >= 0 alors
indiceL vaut arrondi_inferieur(codeCase / 100)
indiceC vaut codeCase mod 100
etatCase[indiceL][indiceC] vaut 1
open vaut vrai
indicesRestants soustrait 1
penalite ajoute 10
message vaut "Indice : case sûre ouverte (+10 s)"
fin si
fin si
// ----- Clic sur le plateau -----
sinon si xc >= x0 et xc < x0 + NL * cs et yc >= y0 et yc < y0 + NL * cs alors
cClic vaut limiter(arrondi_inferieur((xc - x0) / cs), 0, NL - 1)
lClic vaut limiter(arrondi_inferieur((yc - y0) / cs), 0, NL - 1)
indiceL vaut 0 - 1
indiceC vaut 0 - 1
si modeDrapeau alors
// --- Poser / retirer un drapeau ---
si premierCoup alors
message vaut "Creuse d'abord une case (bouton Creuser)"
sinon si etatCase[lClic][cClic] = 0 alors
etatCase[lClic][cClic] vaut 2
drapeaux ajoute 1
message vaut "Drapeau posé"
sinon si etatCase[lClic][cClic] = 2 alors
etatCase[lClic][cClic] vaut 0
drapeaux soustrait 1
message vaut "Drapeau retiré"
fin si
sinon si etatCase[lClic][cClic] = 2 alors
message vaut "Case protégée par un drapeau"
sinon si etatCase[lClic][cClic] = 0 alors
// --- Creuser une case cachée ---
si premierCoup alors
// Les mines sont placées APRÈS le premier clic,
// jamais sur la case cliquée ni autour d'elle.
places vaut 0
tant que places < nbMines
rl vaut hasard(0, NL - 1)
rc vaut hasard(0, NL - 1)
si mine[rl][rc] = faux et (absolue(rl - lClic) > 1 ou absolue(rc - cClic) > 1) alors
mine[rl][rc] vaut vrai
places ajoute 1
fin si
fin tant que
pour i de 0 à NL - 1
pour j de 0 à NL - 1
compte vaut 0
pour di de 0 à 2
pour dj de 0 à 2
vr vaut i + di - 1
vc vaut j + dj - 1
si vr >= 0 et vr < NL et vc >= 0 et vc < NL alors
si mine[vr][vc] = vrai alors
compte ajoute 1
fin si
fin si
fin pour
fin pour
voisins[i][j] vaut compte
fin pour
fin pour
premierCoup vaut faux
tempsDebut vaut chrono()
jouees ajoute 1
paramètre('demineur', 'jouees', jouees)
message vaut "Bonne chance !"
fin si
etatCase[lClic][cClic] vaut 1
si mine[lClic][cClic] = vrai alors
boum vaut vrai
explL vaut lClic
explC vaut cClic
sinon
open vaut vrai
fin si
sinon si etatCase[lClic][cClic] = 1 et voisins[lClic][cClic] > 0 alors
// --- Clic sur un chiffre : ouverture rapide ---
compte vaut 0
pour di de 0 à 2
pour dj de 0 à 2
vr vaut lClic + di - 1
vc vaut cClic + dj - 1
si vr >= 0 et vr < NL et vc >= 0 et vc < NL alors
si etatCase[vr][vc] = 2 alors
compte ajoute 1
fin si
fin si
fin pour
fin pour
si compte = voisins[lClic][cClic] alors
pour di de 0 à 2
pour dj de 0 à 2
vr vaut lClic + di - 1
vc vaut cClic + dj - 1
si vr >= 0 et vr < NL et vc >= 0 et vc < NL alors
si etatCase[vr][vc] = 0 alors
etatCase[vr][vc] vaut 1
si mine[vr][vc] = vrai alors
boum vaut vrai
explL vaut vr
explC vaut vc
fin si
fin si
fin si
fin pour
fin pour
open vaut vrai
sinon
message vaut "Il faut " + convertir_texte(voisins[lClic][cClic]) + " drapeaux autour de ce chiffre"
fin si
fin si
fin si
// ----- Ouverture en cascade des zones vides -----
si open et non boum alors
encore vaut vrai
tant que encore
encore vaut faux
pour i de 0 à NL - 1
pour j de 0 à NL - 1
si etatCase[i][j] = 1 et voisins[i][j] = 0 et mine[i][j] = faux alors
pour di de 0 à 2
pour dj de 0 à 2
vr vaut i + di - 1
vc vaut j + dj - 1
si vr >= 0 et vr < NL et vc >= 0 et vc < NL alors
si etatCase[vr][vc] = 0 et mine[vr][vc] = faux alors
etatCase[vr][vc] vaut 1
encore vaut vrai
fin si
fin si
fin pour
fin pour
fin si
fin pour
fin pour
fin tant que
fin si
// ----- Défaite -----
si boum alors
fini vaut vrai
gagne vaut faux
modeDrapeau vaut faux
tempsFinal vaut minimum(999, arrondi_inferieur((chrono() - tempsDebut) / 1000) + penalite)
message vaut "BOUM ! Une mine a explosé"
fin si
// ----- Victoire ? -----
si non fini et non premierCoup alors
revelees vaut 0
pour i de 0 à NL - 1
pour j de 0 à NL - 1
si etatCase[i][j] = 1 alors
revelees ajoute 1
fin si
fin pour
fin pour
si revelees = NL * NL - nbMines alors
fini vaut vrai
gagne vaut vrai
modeDrapeau vaut faux
tempsFinal vaut minimum(999, arrondi_inferieur((chrono() - tempsDebut) / 1000) + penalite)
// Toutes les mines reçoivent un drapeau
pour i de 0 à NL - 1
pour j de 0 à NL - 1
si mine[i][j] = vrai alors
etatCase[i][j] vaut 2
fin si
fin pour
fin pour
drapeaux vaut nbMines
gagnees ajoute 1
paramètre('demineur', 'gagnees', gagnees)
si meilleurs[diff - 1] = 0 ou tempsFinal < meilleurs[diff - 1] alors
meilleurs[diff - 1] vaut tempsFinal
paramètre('demineur', 'record' + convertir_texte(diff), tempsFinal)
nouveauRecord vaut vrai
fin si
message vaut "Terrain entièrement déminé !"
fin si
fin si
fin si
fin si
// ----- Chronomètre : on redessine à chaque nouvelle seconde -----
si non premierCoup et non fini alors
secondes vaut minimum(999, arrondi_inferieur((chrono() - tempsDebut) / 1000) + penalite)
si secondes <> derniereSeconde alors
derniereSeconde vaut secondes
redessiner vaut vrai
fin si
fin si
si fini alors
secondes vaut tempsFinal
fin si
// ----- Survol de la souris sur le plateau -----
survolL vaut 0 - 1
survolC vaut 0 - 1
si non fini et non aideVisible et xc >= x0 et xc < x0 + NL * cs et yc >= y0 et yc < y0 + NL * cs alors
survolC vaut limiter(arrondi_inferieur((xc - x0) / cs), 0, NL - 1)
survolL vaut limiter(arrondi_inferieur((yc - y0) / cs), 0, NL - 1)
fin si
si survolL <> ancienSurvolL ou survolC <> ancienSurvolC alors
ancienSurvolL vaut survolL
ancienSurvolC vaut survolC
redessiner vaut vrai
fin si
fin si
// ==================================================
// AFFICHAGE (seulement quand quelque chose a changé)
// ==================================================
si redessiner et non lancer et non quitter alors
redessiner vaut faux
effacer(ecran)
contour(ecran, #0)
remplir(ecran, #2F4A22)
si ecranActuel = 0 alors
// ---------------- MENU ----------------
// Décor : une bande de cases d'herbe
pour j de 0 à 9
si pair(j) alors
rectangle(ecran, j * 40, 0, 40, 40, #AAD751)
sinon
rectangle(ecran, j * 40, 0, 40, 40, #A2D149)
fin si
fin pour
appelle dessinerDrapeau(ecran, 60, 20, 34)
appelle dessinerMine(ecran, 340, 20, 8)
txt vaut "DÉMINEUR"
label(ecran, 200 - label_largeur(txt, 40) / 2, 100, txt, #FFFFFF, 40)
txt vaut "Choisis ta difficulté"
label(ecran, 200 - label_largeur(txt, 15) / 2, 140, txt, #C5E1A5, 15)
pour d de 0 à 2
py vaut 170 + d * 80
si d = 0 alors
appelle dessinerFondBouton(ecran, 50, py, 300, 64, #7CB342)
sinon si d = 1 alors
appelle dessinerFondBouton(ecran, 50, py, 300, 64, #F9A825)
sinon
appelle dessinerFondBouton(ecran, 50, py, 300, 64, #E53935)
fin si
label(ecran, 70, py + 30, cfgNom[d], #FFFFFF, 20)
txt vaut convertir_texte(cfgTaille[d]) + " × " + convertir_texte(cfgTaille[d]) + " · " + convertir_texte(cfgMines[d]) + " mines"
label(ecran, 70, py + 50, txt, #FFFFFF, 12)
si meilleurs[d] > 0 alors
txt vaut "🏆 " + convertir_texte(meilleurs[d]) + " s"
sinon
txt vaut "🏆 —"
fin si
label(ecran, 330 - label_largeur(txt, 16), py + 38, txt, #FFFFFF, 16)
fin pour
appelle dessinerBouton(ecran, 50, 418, 300, 46, "Comment jouer", #5E8C3A, #FFFFFF, 16)
appelle dessinerBouton(ecran, 50, 476, 300, 46, "Quitter", #3E5F2C, #C5E1A5, 16)
si jouees > 0 alors
pct vaut arrondi(pourcentage(gagnees, jouees))
sinon
pct vaut 0
fin si
txt vaut "Parties : " + convertir_texte(jouees) + " · Victoires : " + convertir_texte(gagnees) + " (" + convertir_texte(pct) + " %)"
label(ecran, 200 - label_largeur(txt, 12) / 2, 548, txt, #C5E1A5, 12)
sinon
// ---------------- PARTIE ----------------
// Bandeau du haut
rectangle_arrondi(ecran, 10, 10, 380, 60, 14, #4A752C)
appelle dessinerDrapeau(ecran, 34, 40, 34)
label(ecran, 54, 48, convertir_texte(nbMines - drapeaux), #FFFFFF, 22)
appelle dessinerHorloge(ecran, 122, 40, 12)
label(ecran, 142, 48, convertir_texte(secondes), #FFFFFF, 22)
label(ecran, 190, 46, cfgNom[diff - 1], #C5E1A5, 13)
appelle dessinerBouton(ecran, 250, 20, 40, 40, "?", #5E8C3A, #FFFFFF, 20)
appelle dessinerBoutonRejouer(ecran, 296, 20)
appelle dessinerBoutonMenu(ecran, 342, 20)
// Message
label(ecran, 20, 88, message, #C5E1A5, 12)
// Plateau
rectangle_arrondi(ecran, x0 - 6, y0 - 6, NL * cs + 12, NL * cs + 12, 10, #4A752C)
montrer vaut fini et non gagne
pour i de 0 à NL - 1
pour j de 0 à NL - 1
px vaut x0 + j * cs
py vaut y0 + i * cs
claire vaut pair(i + j)
explose vaut (i = explL et j = explC)
survole vaut (i = survolL et j = survolC)
appelle dessinerCase(ecran, px, py, cs, etatCase[i][j], mine[i][j], voisins[i][j], claire, montrer, explose, survole)
fin pour
fin pour
// Case révélée par un indice : cadre doré
si indiceL >= 0 alors
contour(ecran, #FFD600, 3)
rectangle(ecran, x0 + indiceC * cs, y0 + indiceL * cs, cs, cs, rgba(255, 214, 0, 0.15))
contour(ecran, #0)
fin si
// Zone du bas
rectangle_arrondi(ecran, 10, 468, 380, 82, 14, #4A752C)
si non fini alors
// Bouton de mode
si modeDrapeau alors
appelle dessinerFondBouton(ecran, 18, 478, 176, 60, #E53935)
appelle dessinerDrapeau(ecran, 48, 508, 36)
label(ecran, 72, 506, "Drapeau", #FFFFFF, 17)
sinon
appelle dessinerFondBouton(ecran, 18, 478, 176, 60, #8D6E63)
rectangle_arrondi(ecran, 32, 492, 30, 30, 6, #E5C29F)
label(ecran, 41, 514, "1", #1976D2, 18)
label(ecran, 72, 506, "Creuser", #FFFFFF, 17)
fin si
label(ecran, 72, 526, "touche F pour changer", #FFFFFF, 10)
// Bouton indice
si indicesRestants > 0 et non premierCoup alors
appelle dessinerFondBouton(ecran, 206, 478, 176, 60, #F9A825)
sinon
appelle dessinerFondBouton(ecran, 206, 478, 176, 60, #6D7F5F)
fin si
label(ecran, 226, 506, "Indice (" + convertir_texte(indicesRestants) + ")", #FFFFFF, 17)
label(ecran, 226, 526, "+10 s de pénalité", #FFFFFF, 10)
sinon
// Résultat de la partie
si gagne alors
label(ecran, 24, 498, "BRAVO !", #FFEB3B, 22)
label(ecran, 24, 520, "Temps : " + convertir_texte(tempsFinal) + " s", #FFFFFF, 14)
si nouveauRecord alors
label(ecran, 24, 540, "🏆 Nouveau record !", #FFEB3B, 13)
sinon
label(ecran, 24, 540, "Record : " + convertir_texte(meilleurs[diff - 1]) + " s", #C5E1A5, 13)
fin si
sinon
revelees vaut 0
pour i de 0 à NL - 1
pour j de 0 à NL - 1
si etatCase[i][j] = 1 et mine[i][j] = faux alors
revelees ajoute 1
fin si
fin pour
fin pour
pct vaut arrondi(pourcentage(revelees, NL * NL - nbMines))
label(ecran, 24, 498, "BOUM !", #FF8A80, 22)
label(ecran, 24, 520, "Terrain déminé : " + convertir_texte(pct) + " %", #FFFFFF, 14)
label(ecran, 24, 540, "Temps : " + convertir_texte(tempsFinal) + " s", #C5E1A5, 13)
fin si
appelle dessinerBouton(ecran, 222, 482, 76, 52, "Rejouer", #7CB342, #FFFFFF, 14)
appelle dessinerBouton(ecran, 306, 482, 76, 52, "Menu", #5E8C3A, #FFFFFF, 14)
fin si
fin si
// ---------------- AIDE (par-dessus tout) ----------------
si aideVisible alors
rectangle(ecran, 0, 0, 400, 560, rgba(0, 0, 0, 0.72))
rectangle_arrondi(ecran, 24, 70, 352, 420, 16, #3E5F2C)
label(ecran, 50, 112, "COMMENT JOUER", #FFFFFF, 22)
label(ecran, 50, 150, "Ouvre toutes les cases sans mine.", #E8F5E9, 13)
label(ecran, 50, 180, "Un chiffre indique combien de mines", #E8F5E9, 13)
label(ecran, 50, 200, "touchent cette case (diagonales aussi).", #E8F5E9, 13)
label(ecran, 50, 230, "Le premier clic est toujours sûr.", #E8F5E9, 13)
label(ecran, 50, 260, "Mode Drapeau (bouton ou touche F) :", #E8F5E9, 13)
label(ecran, 50, 280, "marque une case que tu crois minée.", #E8F5E9, 13)
label(ecran, 50, 310, "Clic sur un chiffre déjà entouré du bon", #E8F5E9, 13)
label(ecran, 50, 330, "nombre de drapeaux : ouvre ses voisines.", #E8F5E9, 13)
label(ecran, 50, 360, "Indice : ouvre une case sûre (+10 s).", #E8F5E9, 13)
label(ecran, 50, 390, "R : rejouer Échap : menu", #E8F5E9, 13)
label(ecran, 50, 420, "Bats ton meilleur temps à chaque niveau !", #FFEB3B, 13)
label(ecran, 50, 465, "Clique pour fermer", #FFEB3B, 14)
fin si
affiche ecran
fin si
pause 40
fin tant que
affiche "Merci d'avoir joué au Démineur !"