Console
Clique sur « Exécuter » pour lancer le programme.
Aucune exécutionCtrl+Entrée : exécuter · Échap : arrêter
Code CoddyRun
@ CONFIGURATION
graph est une toile
dimension(graph, 400, 550)
// Le parking fait 6 x 6 cases. La sortie est à droite de la ligne 2.
NBC est un nombre
NBC vaut 5
LSORTIE est un nombre
LSORTIE vaut 2
MAXV est un nombre
MAXV vaut 13
MAXETATS est un nombre
MAXETATS vaut 4000
CS est un nombre
BX est un nombre
BY est un nombre
CS vaut 54
BX vaut 38
BY vaut 124
niveau est un nombre
niveau vaut 1
coups est un nombre
coups vaut 0
minCoups est un nombre
minCoups vaut 0
selection est un nombre
selection vaut - 1
nouveauNiveau est un booléen
nouveauNiveau vaut vrai
gagne est un booléen
gagne vaut faux
message est un texte
message vaut "Clique une voiture, puis la case où l'envoyer"
@ LES VOITURES
// vLgn / vCln : coin haut-gauche, vLon : longueur, vOri : 0 couché, 1 debout
nbV est un nombre
nbV vaut 0
vLgn est un tableau
vCln est un tableau
vLon est un tableau
vOri est un tableau
dLgn est un tableau
dCln est un tableau
bLgn est un tableau
bCln est un tableau
bLon est un tableau
bOri est un tableau
posV est un tableau
multV est un tableau
pour v de 0 à MAXV
vLgn ajoute 0
vCln ajoute 0
vLon ajoute 2
vOri ajoute 0
dLgn ajoute 0
dCln ajoute 0
bLgn ajoute 0
bCln ajoute 0
bLon ajoute 2
bOri ajoute 0
posV ajoute 0
multV ajoute 1
fin pour
coulV est un tableau
coulV ajoute #E53935
coulV ajoute #1E88E5
coulV ajoute #43A047
coulV ajoute #FB8C00
coulV ajoute #8E24AA
coulV ajoute #00ACC1
coulV ajoute #FDD835
coulV ajoute #6D4C41
coulV ajoute #EC407A
coulV ajoute #26A69A
coulV ajoute #7E57C2
coulV ajoute #9E9D24
@ OCCUPATION DU PARKING
occ est un tableau
pour i de 0 à NBC
ligO est un tableau
pour j de 0 à NBC
ligO ajoute - 1
fin pour
occ ajoute ligO
fin pour
@ FILE DU PARCOURS EN LARGEUR
// Chaque situation du parking est résumée par un seul nombre :
// la position de chaque voiture écrite en base 6.
file est un tableau
distF est un tableau
pour k de 0 à MAXETATS
file ajoute 0
distF ajoute 0
fin pour
vus est un dictionnaire
vus vaut [:]
@ DESSIN D'UNE VOITURE
procédure dessinerVoiture(t, x, y, l, h, coul, choisie)
rectangle_arrondi(t, x + 2, y + 4, l, h, 12, rgba(0, 0, 0, 0.3))
rectangle_arrondi(t, x, y, l, h, 12, coul)
// Vitrage
si l > h alors
rectangle_arrondi(t, x + l / 6, y + h / 4, l * 2 / 3, h / 3, 6, rgba(255, 255, 255, 0.35))
sinon
rectangle_arrondi(t, x + l / 4, y + h / 6, l / 3, h * 2 / 3, 6, rgba(255, 255, 255, 0.35))
fin si
si choisie = vrai alors
contour(t, #FFFFFF, 3)
rectangle_arrondi(t, x - 2, y - 2, l + 4, h + 4, 14, rgba(255, 255, 255, 0.12))
contour(t, #0)
fin si
fin procédure
@ UN BOUTON
procédure dessinerBouton(t, x, y, l, h, txt, coul)
rectangle_arrondi(t, x, y + 3, l, h, 10, rgba(15, 23, 42, 0.25))
rectangle_arrondi(t, x, y, l, h, 10, coul)
label(t, x + 16, y + h / 2 + 5, txt, #FFFFFF, 13)
fin procédure
@ BOUCLE PRINCIPALE
tant que vrai
// ==========================================================
// GÉNÉRATION D'UN NIVEAU, RÉSOLU AVANT D'ÊTRE PROPOSÉ
// ==========================================================
si nouveauNiveau = vrai alors
nouveauNiveau vaut faux
gagne vaut faux
coups vaut 0
selection vaut - 1
cible est un nombre
cible vaut 9 + niveau * 3
cible vaut limiter(cible, 9, 28)
meilleurMin est un nombre
meilleurMin vaut - 1
nbBest est un nombre
nbBest vaut 0
tentative est un nombre
tentative vaut 0
tant que tentative < 12 et meilleurMin < cible
tentative ajoute 1
// ---------- 1. On dispose les voitures au hasard ----------
pour i de 0 à NBC
pour j de 0 à NBC
occ[i][j] vaut - 1
fin pour
fin pour
nbV vaut 1
vLgn[0] vaut LSORTIE
vCln[0] vaut hasard(0, 2)
vLon[0] vaut 2
vOri[0] vaut 0
occ[LSORTIE][vCln[0]] vaut 0
occ[LSORTIE][vCln[0] + 1] vaut 0
// ---------- 1b. Trois voitures debout barrent d'office la sortie ----------
// Sans elles, la voiture rouge file tout droit et le niveau est trivial.
barrages est un nombre
barrages vaut 0
essaiB est un nombre
essaiB vaut 0
tant que barrages < 3 et essaiB < 250
essaiB ajoute 1
lonB est un nombre
lonB vaut 2
si hasard(1, 100) <= 40 alors
lonB vaut 3
fin si
clB est un nombre
clB vaut hasard(vCln[0] + 2, NBC)
lgB est un nombre
lgB vaut hasard(LSORTIE - lonB + 1, LSORTIE)
si lgB < 0 alors
lgB vaut 0
fin si
si lgB + lonB - 1 <= NBC alors
okB est un booléen
okB vaut vrai
pour k de 0 à lonB - 1
si occ[lgB + k][clB] >= 0 alors
okB vaut faux
fin si
fin pour
si okB = vrai alors
vLgn[nbV] vaut lgB
vCln[nbV] vaut clB
vLon[nbV] vaut lonB
vOri[nbV] vaut 1
pour k de 0 à lonB - 1
occ[lgB + k][clB] vaut nbV
fin pour
nbV ajoute 1
barrages ajoute 1
fin si
fin si
fin tant que
combien est un nombre
combien vaut hasard(9, 12)
essais est un nombre
essais vaut 0
tant que nbV < combien et essais < 500
essais ajoute 1
ori est un nombre
lon est un nombre
ori vaut hasard(0, 1)
lon vaut 2
si hasard(1, 100) <= 30 alors
lon vaut 3
fin si
lg est un nombre
cl est un nombre
si ori = 0 alors
lg vaut hasard(0, NBC)
cl vaut hasard(0, NBC - lon + 1)
sinon
lg vaut hasard(0, NBC - lon + 1)
cl vaut hasard(0, NBC)
fin si
// Une voiture couchée sur la ligne de sortie bloquerait à jamais
placeOk est un booléen
placeOk vaut vrai
si ori = 0 et lg = LSORTIE alors
placeOk vaut faux
fin si
si placeOk = vrai alors
pour k de 0 à lon - 1
ck est un nombre
lk est un nombre
si ori = 0 alors
lk vaut lg
ck vaut cl + k
sinon
lk vaut lg + k
ck vaut cl
fin si
si occ[lk][ck] >= 0 alors
placeOk vaut faux
fin si
fin pour
fin si
si placeOk = vrai alors
vLgn[nbV] vaut lg
vCln[nbV] vaut cl
vLon[nbV] vaut lon
vOri[nbV] vaut ori
pour k de 0 à lon - 1
si ori = 0 alors
occ[lg][cl + k] vaut nbV
sinon
occ[lg + k][cl] vaut nbV
fin si
fin pour
nbV ajoute 1
fin si
fin tant que
// ---------- 2. Combien de coups au minimum ? ----------
// Puissances de 6 : la position de la voiture v pèse 6 puissance v
m est un nombre
m vaut 1
pour v de 0 à nbV - 1
multV[v] vaut m
m vaut m * 6
fin pour
codeDep est un nombre
codeDep vaut 0
pour v de 0 à nbV - 1
pv est un nombre
si vOri[v] = 0 alors
pv vaut vCln[v]
sinon
pv vaut vLgn[v]
fin si
codeDep vaut codeDep + pv * multV[v]
fin pour
vus vaut [:]
file[0] vaut codeDep
distF[0] vaut 0
vus[convertir_texte(codeDep)] vaut 1
nbEtats est un nombre
nbEtats vaut 1
tete est un nombre
tete vaut 0
resultat est un nombre
resultat vaut - 1
tant que tete < nbEtats et resultat < 0 et nbEtats < MAXETATS - nbV * 2
fcode est un nombre
fcode vaut file[tete]
dCode est un nombre
dCode vaut distF[tete]
// Décodage : on extrait chaque position en base 6
reste est un nombre
reste vaut fcode
pour v de 0 à nbV - 1
q est un nombre
q vaut arrondi_inferieur(reste / 6)
posV[v] vaut reste - q * 6
reste vaut q
fin pour
si posV[0] = NBC - 1 alors
resultat vaut dCode
sinon
// Occupation correspondant à cette situation
pour i de 0 à NBC
pour j de 0 à NBC
occ[i][j] vaut - 1
fin pour
fin pour
pour v de 0 à nbV - 1
pour k de 0 à vLon[v] - 1
si vOri[v] = 0 alors
occ[vLgn[v]][posV[v] + k] vaut v
sinon
occ[posV[v] + k][vCln[v]] vaut v
fin si
fin pour
fin pour
// Chaque voiture tente d'avancer et de reculer d'une case
pour v de 0 à nbV - 1
pour sens de 0 à 1
dep est un nombre
si sens = 0 alors
dep vaut 0 - 1
sinon
dep vaut 1
fin si
npos est un nombre
npos vaut posV[v] + dep
bon est un booléen
bon vaut faux
si npos >= 0 et npos + vLon[v] - 1 <= NBC alors
// Seule la case libérée devant la voiture doit être vide
tl est un nombre
tc est un nombre
si dep = 1 alors
si vOri[v] = 0 alors
tl vaut vLgn[v]
tc vaut posV[v] + vLon[v]
sinon
tl vaut posV[v] + vLon[v]
tc vaut vCln[v]
fin si
sinon
si vOri[v] = 0 alors
tl vaut vLgn[v]
tc vaut npos
sinon
tl vaut npos
tc vaut vCln[v]
fin si
fin si
si occ[tl][tc] < 0 alors
bon vaut vrai
fin si
fin si
si bon = vrai alors
nCode est un nombre
nCode vaut fcode + dep * multV[v]
cleE est un texte
cleE vaut convertir_texte(nCode)
si contient(vus, cleE) = faux alors
si nbEtats < MAXETATS alors
vus[cleE] vaut 1
file[nbEtats] vaut nCode
distF[nbEtats] vaut dCode + 1
nbEtats ajoute 1
fin si
fin si
fin si
fin pour
fin pour
fin si
tete ajoute 1
fin tant que
// ---------- 3. On garde la configuration la plus corsée ----------
si resultat > meilleurMin alors
meilleurMin vaut resultat
nbBest vaut nbV
pour v de 0 à nbV - 1
bLgn[v] vaut vLgn[v]
bCln[v] vaut vCln[v]
bLon[v] vaut vLon[v]
bOri[v] vaut vOri[v]
fin pour
fin si
fin tant que
// ---------- 4. Le niveau retenu devient le niveau courant ----------
nbV vaut nbBest
pour v de 0 à nbV - 1
vLgn[v] vaut bLgn[v]
vCln[v] vaut bCln[v]
vLon[v] vaut bLon[v]
vOri[v] vaut bOri[v]
dLgn[v] vaut bLgn[v]
dCln[v] vaut bCln[v]
fin pour
minCoups vaut meilleurMin
message vaut "Niveau " + niveau + " : " + minCoups + " coups suffisent"
fin si
// ==========================================================
// AFFICHAGE
// ==========================================================
effacer(graph)
contour(graph, #0)
remplir(graph, #EDF2F8)
// ---------- BANDEAU DU HAUT ----------
rectangle_arrondi(graph, 12, 8, 376, 98, 14, #FFFFFF)
label(graph, 26, 40, "EMBOUTEILLAGE", #B45309, 20)
label(graph, 26, 68, "Niveau " + niveau, #0F172A, 14)
label(graph, 130, 68, "Coups : " + coups, #2563EB, 14)
coulMin est un texte
si coups > minCoups alors
coulMin vaut #DC2626
sinon
coulMin vaut #16A34A
fin si
label(graph, 250, 68, "Minimum : " + minCoups, coulMin, 14)
nomDiff est un texte
si minCoups <= 10 alors
nomDiff vaut "Facile"
sinon si minCoups <= 16 alors
nomDiff vaut "Moyen"
sinon si minCoups <= 22 alors
nomDiff vaut "Difficile"
sinon
nomDiff vaut "Expert"
fin si
label(graph, 300, 40, nomDiff, #DC2626, 13)
label(graph, 26, 94, message, #64748B, 11)
// ---------- LE PARKING ----------
rectangle_arrondi(graph, 28, 114, 344, 344, 16, #3E4650)
pour i de 0 à NBC
pour j de 0 à NBC
rectangle_arrondi(graph, BX + j * CS + 3, BY + i * CS + 3, CS - 6, CS - 6, 8, #4A525C)
fin pour
fin pour
// La sortie, à droite de la ligne 2
rectangle(graph, 362, BY + LSORTIE * CS + 8, 10, CS - 16, #FDE68A)
pFl est un tableau
pFl ajoute 366
pFl ajoute BY + LSORTIE * CS + 16
pFl ajoute 366
pFl ajoute BY + LSORTIE * CS + 38
pFl ajoute 380
pFl ajoute BY + LSORTIE * CS + 27
polygone(graph, pFl, #FDE68A)
// Les voitures
pour v de 0 à nbV - 1
xv est un nombre
yv est un nombre
lv est un nombre
hv est un nombre
xv vaut BX + vCln[v] * CS + 4
yv vaut BY + vLgn[v] * CS + 4
si vOri[v] = 0 alors
lv vaut vLon[v] * CS - 8
hv vaut CS - 8
sinon
lv vaut CS - 8
hv vaut vLon[v] * CS - 8
fin si
choisie est un booléen
choisie vaut faux
si v = selection alors
choisie vaut vrai
fin si
appelle dessinerVoiture(graph, xv, yv, lv, hv, coulV[v], choisie)
fin pour
// ---------- BOUTONS ----------
appelle dessinerBouton(graph, 28, 476, 150, 44, "Recommencer", #64748B)
appelle dessinerBouton(graph, 200, 476, 172, 44, "Nouveau niveau", #2563EB)
// ---------- VICTOIRE ----------
si gagne = vrai alors
rectangle(graph, 0, 0, 400, 550, rgba(15, 23, 42, 0.75))
rectangle_arrondi(graph, 40, 180, 320, 200, 16, #FFFFFF)
label(graph, 76, 232, "🚗 SORTIE LIBRE !", #B45309, 24)
label(graph, 76, 274, "Résolu en " + coups + " coups", #0F172A, 16)
si coups <= minCoups alors
label(graph, 76, 302, "Solution optimale, bravo !", #16A34A, 14)
sinon
label(graph, 76, 302, "Le minimum était de " + minCoups + " coups", #64748B, 14)
fin si
label(graph, 76, 348, "Clique pour le niveau suivant", #2563EB, 14)
fin si
affiche graph
// ==========================================================
// LA SOURIS
// ==========================================================
xc est un nombre
yc est un nombre
cliquer graph dans xc, yc
si gagne = vrai alors
niveau ajoute 1
nouveauNiveau vaut vrai
sinon si xc >= 28 et xc <= 178 et yc >= 476 et yc <= 520 alors
// ---------- RECOMMENCER ----------
pour v de 0 à nbV - 1
vLgn[v] vaut dLgn[v]
vCln[v] vaut dCln[v]
fin pour
coups vaut 0
selection vaut - 1
message vaut "Niveau remis à zéro"
sinon si xc >= 200 et xc <= 372 et yc >= 476 et yc <= 520 alors
// ---------- AUTRE NIVEAU ----------
nouveauNiveau vaut vrai
sinon si xc >= BX et xc < BX + (NBC + 1) * CS et yc >= BY et yc < BY + (NBC + 1) * CS alors
cln est un nombre
lgn est un nombre
cln vaut arrondi_inferieur((xc - BX) / CS)
lgn vaut arrondi_inferieur((yc - BY) / CS)
cln vaut limiter(cln, 0, NBC)
lgn vaut limiter(lgn, 0, NBC)
// Quelle voiture occupe cette case ?
surV est un nombre
surV vaut - 1
pour v de 0 à nbV - 1
pour k de 0 à vLon[v] - 1
lk est un nombre
ck est un nombre
si vOri[v] = 0 alors
lk vaut vLgn[v]
ck vaut vCln[v] + k
sinon
lk vaut vLgn[v] + k
ck vaut vCln[v]
fin si
si lk = lgn et ck = cln alors
surV vaut v
fin si
fin pour
fin pour
si surV >= 0 alors
selection vaut surV
si surV = 0 alors
message vaut "Voiture rouge sélectionnée : elle doit sortir à droite"
sinon
message vaut "Voiture sélectionnée : clique sa destination"
fin si
sinon si selection < 0 alors
message vaut "Choisis d'abord une voiture"
sinon
// ---------- DÉPLACER LA VOITURE SÉLECTIONNÉE ----------
s est un nombre
s vaut selection
alignee est un booléen
alignee vaut faux
viser est un nombre
viser vaut 0
si vOri[s] = 0 et lgn = vLgn[s] alors
alignee vaut vrai
si cln < vCln[s] alors
viser vaut cln
sinon
viser vaut cln - vLon[s] + 1
fin si
sinon si vOri[s] = 1 et cln = vCln[s] alors
alignee vaut vrai
si lgn < vLgn[s] alors
viser vaut lgn
sinon
viser vaut lgn - vLon[s] + 1
fin si
fin si
si alignee = faux alors
message vaut "Cette voiture ne roule pas dans cette direction"
sinon
// Occupation actuelle, sans la voiture déplacée
pour i de 0 à NBC
pour j de 0 à NBC
occ[i][j] vaut - 1
fin pour
fin pour
pour v de 0 à nbV - 1
si v <> s alors
pour k de 0 à vLon[v] - 1
si vOri[v] = 0 alors
occ[vLgn[v]][vCln[v] + k] vaut v
sinon
occ[vLgn[v] + k][vCln[v]] vaut v
fin si
fin pour
fin si
fin pour
pos est un nombre
si vOri[s] = 0 alors
pos vaut vCln[s]
sinon
pos vaut vLgn[s]
fin si
dep vaut 0
si viser > pos alors
dep vaut 1
sinon si viser < pos alors
dep vaut 0 - 1
fin si
depart est un nombre
depart vaut pos
avance est un booléen
avance vaut vrai
tant que avance = vrai et pos <> viser
npos vaut pos + dep
avance vaut faux
si npos >= 0 et npos + vLon[s] - 1 <= NBC alors
tl vaut 0
tc vaut 0
si dep = 1 alors
si vOri[s] = 0 alors
tl vaut vLgn[s]
tc vaut pos + vLon[s]
sinon
tl vaut pos + vLon[s]
tc vaut vCln[s]
fin si
sinon
si vOri[s] = 0 alors
tl vaut vLgn[s]
tc vaut npos
sinon
tl vaut npos
tc vaut vCln[s]
fin si
fin si
si occ[tl][tc] < 0 alors
pos vaut npos
avance vaut vrai
fin si
fin si
fin tant que
si pos = depart alors
message vaut "La voie est bloquée de ce côté"
sinon
si vOri[s] = 0 alors
vCln[s] vaut pos
sinon
vLgn[s] vaut pos
fin si
coups ajoute 1
selection vaut - 1
message vaut "Coup " + coups + " joué"
si vCln[0] = NBC - 1 et vOri[0] = 0 alors
gagne vaut vrai
fin si
fin si
fin si
fin si
fin si
fin tant que