Console
Clique sur « Exécuter » pour lancer le programme.
Code CoddyRun
// REGLAGES ET GEOMETRIE
@ Réglages du jeu
nbDisques est un nombre
nbDisques vaut 4
largToile est un nombre
largToile vaut 600
hautToile est un nombre
hautToile vaut 460
// PALETTE DE COULEURS (pour les disques)
@ Palette
teintes est un tableau
teintes ajoute #ff3d8b
teintes ajoute #a855f7
teintes ajoute #3b82f6
teintes ajoute #22d3ee
teintes ajoute #4ade80
teintes ajoute #fbbf24
// ETAT DU JEU ET SOLVEUR
@ État du jeu
jeu est une toile
tour1 est un tableau
tour2 est un tableau
tour3 est un tableau
selection est un nombre
selection vaut -1
coups est un nombre
coups vaut 0
gagne est un booleen
gagne vaut faux
message est un texte
message vaut "Clique sur une tour ou sur 'Résoudre Pas à Pas'."
partieEnCours est un booleen
partieEnCours vaut vrai
rejouer est un nombre
clicX est un nombre
clicY est un nombre
tourCible est un nombre
disqueBouge est un nombre
sommetDst est un nombre
okMouvement est un booleen
// Tableaux pour le solveur automatique
solutionSrc est un tableau
solutionDst est un tableau
indexEtape est un nombre
srcVal est un nombre
dstVal est un nombre
// PROCEDURE DE GENERATION RECURSIVE DU SOLVEUR
@ Génération des mouvements Hanoï
procédure genererMouvements(n, s, d, x)
si n > 0 alors
appelle genererMouvements(n - 1, s, x, d)
solutionSrc ajoute s
solutionDst ajoute d
appelle genererMouvements(n - 1, x, d, s)
fin si
fin procédure
// FONCTION DE DESSIN COMPLET
@ Affichage graphique et centrage précis
procédure dessinerJeu(ecran, tourSel, avecVictoire)
dimension(ecran, largToile, hautToile)
effacer(ecran)
dégradé(ecran, [#080f1d, #17243f, #080f1d])
sTxt est un texte
sX est un nombre
sY est un nombre
tIdx est un nombre
dIdx est un nombre
dTailles est un nombre
dW est un nombre
dCouleur est un texte
boxMsgY est un nombre
boxMsgH est un nombre
btn1X est un nombre
btn2X est un nombre
btnY est un nombre
btnL est un nombre
btnH est un nombre
// ---- En-tête ----
label(ecran, 30.27, 28.35, "LES TOURS D'HANOÏ", #eaf2ff, 16)
sTxt vaut "Coups : " + convertir_texte(coups)
label(ecran, largToile - 30 - label_largeur(sTxt, 14), 26.35, sTxt, #8fb3e0, 14)
// ---- Socle des tours ----
rectangle_arrondi(ecran, 50, 300, 500, 16, 8, #1d3557)
// Piquets verticaux
rectangle(ecran, 143, 130, 14, 170, #2a4770)
rectangle(ecran, 293, 130, 14, 170, #2a4770)
rectangle(ecran, 443, 130, 14, 170, #2a4770)
// Numéros des tours centrés
sTxt vaut "Tour 1"
label(ecran, 150 - label_largeur(sTxt, 13) / 2, 340, sTxt, #6f8cb8, 13)
sTxt vaut "Tour 2"
label(ecran, 300 - label_largeur(sTxt, 13) / 2, 340, sTxt, #6f8cb8, 13)
sTxt vaut "Tour 3"
label(ecran, 450 - label_largeur(sTxt, 13) / 2, 340, sTxt, #6f8cb8, 13)
// ---- Dessin des disques ----
// Tour 1
pour dIdx de 0 à longueur(tour1) - 1
dTailles vaut tour1[dIdx]
dW vaut 30 + dTailles * 22
dCouleur vaut teintes[(dTailles - 1) mod longueur(teintes)]
sX vaut 150 - dW / 2
sY vaut 284 - (dIdx + 1) * 24
si tourSel = 1 et dIdx = longueur(tour1) - 1 alors
sY vaut 90
fin si
rectangle_arrondi(ecran, sX, sY, dW, 22, 10, dCouleur)
fin pour
// Tour 2
pour dIdx de 0 à longueur(tour2) - 1
dTailles vaut tour2[dIdx]
dW vaut 30 + dTailles * 22
dCouleur vaut teintes[(dTailles - 1) mod longueur(teintes)]
sX vaut 300 - dW / 2
sY vaut 284 - (dIdx + 1) * 24
si tourSel = 2 et dIdx = longueur(tour2) - 1 alors
sY vaut 90
fin si
rectangle_arrondi(ecran, sX, sY, dW, 22, 10, dCouleur)
fin pour
// Tour 3
pour dIdx de 0 à longueur(tour3) - 1
dTailles vaut tour3[dIdx]
dW vaut 30 + dTailles * 22
dCouleur vaut teintes[(dTailles - 1) mod longueur(teintes)]
sX vaut 450 - dW / 2
sY vaut 284 - (dIdx + 1) * 24
si tourSel = 3 et dIdx = longueur(tour3) - 1 alors
sY vaut 90
fin si
rectangle_arrondi(ecran, sX, sY, dW, 22, 10, dCouleur)
fin pour
// ---- Message d'état (Parfaitement centré dans son encadré) ----
boxMsgY vaut 362
boxMsgH vaut 32
rectangle_arrondi(ecran, 30, boxMsgY, largToile - 60, boxMsgH, 10, #0b1526)
label(ecran, 30 + (largToile - 60 - label_largeur(message, 13)) / 2, boxMsgY + 21, message, #a5c3e8, 13)
// ---- Boutons du bas (Centrage horizontal et vertical précis) ----
btnL vaut 220
btnH vaut 36
btnY vaut 410
btn1X vaut 60
btn2X vaut 320
// Bouton Recommencer
rectangle_arrondi(ecran, btn1X, btnY, btnL, btnH, 10, #1d3557)
sTxt vaut "Recommencer"
label(ecran, btn1X + (btnL - label_largeur(sTxt, 13)) / 2, btnY + 23, sTxt, #cfe3ff, 13)
// Bouton Résoudre Pas à Pas
rectangle_arrondi(ecran, btn2X, btnY, btnL, btnH, 10, #1d3557)
sTxt vaut "Résoudre Pas à Pas"
label(ecran, btn2X + (btnL - label_largeur(sTxt, 13)) / 2, btnY + 23, sTxt, #ffd166, 13)
// ---- Bannière de victoire ----
si avecVictoire alors
rectangle_arrondi(ecran, 80, 105, largToile - 160, 140, 20, #0e2c47)
sTxt vaut "VICTOIRE !"
label(ecran, largToile / 2 - label_largeur(sTxt, 24) / 2, 152.05, sTxt, #ffd166, 24)
sTxt vaut "Résolu en " + convertir_texte(coups) + " coups !"
label(ecran, largToile / 2 - label_largeur(sTxt, 14) / 2, 193.01, sTxt, #cfe3ff, 14)
fin si
fin procédure
procédure actualiserAffichage(selVue, gagneVue)
appelle dessinerJeu(jeu, selVue, gagneVue)
affiche jeu
fin procédure
// BOUCLE PRINCIPALE DU JEU
@ Boucle principale
tant que partieEnCours
vide tour1
vide tour2
vide tour3
pour tIdx de nbDisques à 1 pas -1
tour1 ajoute tIdx
fin pour
coups vaut 0
selection vaut -1
gagne vaut faux
message vaut "Clique sur une tour ou sur 'Résoudre Pas à Pas'."
tant que non gagne
appelle actualiserAffichage(selection, faux)
cliquer jeu dans clicX, clicY
// ---- GESTION DES BOUTONS DU BAS ----
si clique(clicX, clicY, 60, 410, 220, 36) alors
// Bouton Recommencer
gagne vaut vrai
selection vaut -2
sinon si clique(clicX, clicY, 320, 410, 220, 36) alors
// Bouton Résoudre Pas à Pas
vide tour1
vide tour2
vide tour3
pour tIdx de nbDisques à 1 pas -1
tour1 ajoute tIdx
fin pour
coups vaut 0
selection vaut -1
vide solutionSrc
vide solutionDst
appelle genererMouvements(nbDisques, 1, 3, 2)
pour indexEtape de 0 à longueur(solutionSrc) - 1
srcVal vaut solutionSrc[indexEtape]
dstVal vaut solutionDst[indexEtape]
disqueBouge vaut 0
si srcVal = 1 alors
disqueBouge vaut dernier(tour1)
tour1 supprime longueur(tour1) - 1
sinon si srcVal = 2 alors
disqueBouge vaut dernier(tour2)
tour2 supprime longueur(tour2) - 1
sinon si srcVal = 3 alors
disqueBouge vaut dernier(tour3)
tour3 supprime longueur(tour3) - 1
fin si
si dstVal = 1 alors
tour1 ajoute disqueBouge
sinon si dstVal = 2 alors
tour2 ajoute disqueBouge
sinon si dstVal = 3 alors
tour3 ajoute disqueBouge
fin si
coups vaut coups + 1
message vaut "Étape " + convertir_texte(coups) + " : Tour " + convertir_texte(srcVal) + " ➔ Tour " + convertir_texte(dstVal)
appelle actualiserAffichage(-1, faux)
pause 600
fin pour
gagne vaut vrai
sinon
// ---- GESTION DU JEU MANUEL (CLICS SUR LES TOURS) ----
tourCible vaut 0
si clicX >= 80 et clicX <= 220 alors
tourCible vaut 1
sinon si clicX >= 230 et clicX <= 370 alors
tourCible vaut 2
sinon si clicX >= 380 et clicX <= 520 alors
tourCible vaut 3
fin si
si tourCible > 0 alors
si selection = -1 alors
si tourCible = 1 et longueur(tour1) > 0 alors
selection vaut 1
message vaut "Tour 1 sélectionnée. Choisissez la destination."
sinon si tourCible = 2 et longueur(tour2) > 0 alors
selection vaut 2
message vaut "Tour 2 sélectionnée. Choisissez la destination."
sinon si tourCible = 3 et longueur(tour3) > 0 alors
selection vaut 3
message vaut "Tour 3 sélectionnée. Choisissez la destination."
sinon
message vaut "Cette tour est vide !"
fin si
sinon
si selection = tourCible alors
selection vaut -1
message vaut "Sélection annulée."
sinon
disqueBouge vaut 0
si selection = 1 alors
disqueBouge vaut dernier(tour1)
sinon si selection = 2 alors
disqueBouge vaut dernier(tour2)
sinon si selection = 3 alors
disqueBouge vaut dernier(tour3)
fin si
okMouvement vaut faux
si tourCible = 1 alors
si longueur(tour1) = 0 alors
okMouvement vaut vrai
sinon
sommetDst vaut dernier(tour1)
si disqueBouge < sommetDst alors
okMouvement vaut vrai
fin si
fin si
sinon si tourCible = 2 alors
si longueur(tour2) = 0 alors
okMouvement vaut vrai
sinon
sommetDst vaut dernier(tour2)
si disqueBouge < sommetDst alors
okMouvement vaut vrai
fin si
fin si
sinon si tourCible = 3 alors
si longueur(tour3) = 0 alors
okMouvement vaut vrai
sinon
sommetDst vaut dernier(tour3)
si disqueBouge < sommetDst alors
okMouvement vaut vrai
fin si
fin si
fin si
si okMouvement alors
si selection = 1 alors
tour1 supprime longueur(tour1) - 1
sinon si selection = 2 alors
tour2 supprime longueur(tour2) - 1
sinon si selection = 3 alors
tour3 supprime longueur(tour3) - 1
fin si
si tourCible = 1 alors
tour1 ajoute disqueBouge
sinon si tourCible = 2 alors
tour2 ajoute disqueBouge
sinon si tourCible = 3 alors
tour3 ajoute disqueBouge
fin si
coups vaut coups + 1
selection vaut -1
message vaut "Coup validé."
sinon
message vaut "Interdit : Impossible de placer un grand disque sur un plus petit !"
selection vaut -1
fin si
fin si
fin si
fin si
fin si
si longueur(tour3) = nbDisques alors
gagne vaut vrai
fin si
fin tant que
si selection <> -2 alors
appelle actualiserAffichage(-1, vrai)
affiche "========================================"
affiche "GAGNE ! Résolu en " + convertir_texte(coups) + " coups."
rejouer vaut 0
choisir ["Rejouer", "Quitter"] dans rejouer
si rejouer = 2 alors
partieEnCours vaut faux
fin si
fin si
fin tant que