Console
Clique sur « Exécuter » pour lancer le programme.
Aucune exécutionCtrl+Entrée : exécuter · Échap : arrêter
Code CoddyRun
@ Constantes
N_GRILLE est un nombre
N_GRILLE vaut 10
CASE_B est un nombre
CASE_B vaut 24
GX_JOUEUR est un nombre
GX_JOUEUR vaut 46
GX_ENNEMI est un nombre
GX_ENNEMI vaut 352
GY est un nombre
GY vaut 140
@ Etat du jeu
ecran est une toile
dimension(ecran, 640, 480)
// navJ / navO : 0 pour une case vide, 1 a 5 pour le numero du navire
// tirJ / tirO : 0 pas encore tire, 1 a l'eau, 2 touche
navJ est un tableau
navO est un tableau
tirJ est un tableau
tirO est un tableau
navTmp est un tableau
// nombre de coups au but par navire, et taille de chaque navire
touchesJ est un tableau
touchesO est un tableau
grandeurNav est un tableau
nomNav est un tableau
// pile des cases a explorer par l'ordinateur apres un touche
fileCase est un tableau
nbFile, couleJ, couleO est un nombre
coupsJ, coupsO, tour est un nombre
finie, enJeu est un booleen
message est un texte
i, k, li, co, idx, nav, essai, ok est un nombre
l2, c2, l4, c4, fini, hori, tir est un nombre
ax, ay, sx, sy est un nombre
teinte est un texte
action, ptX, ptY est un nombre
nbFile vaut 0
couleJ vaut 0
couleO vaut 0
coupsJ vaut 0
coupsO vaut 0
tour vaut 1
finie vaut faux
enJeu vaut vrai
message vaut ""
pour i de 0 à N_GRILLE * N_GRILLE - 1
navJ ajoute 0
navO ajoute 0
tirJ ajoute 0
tirO ajoute 0
navTmp ajoute 0
fileCase ajoute 0
fin pour
pour i de 0 à 5
touchesJ ajoute 0
touchesO ajoute 0
fin pour
grandeurNav ajoute 0
grandeurNav ajoute 5
grandeurNav ajoute 4
grandeurNav ajoute 3
grandeurNav ajoute 3
grandeurNav ajoute 2
nomNav ajoute ""
nomNav ajoute "Porte-avions"
nomNav ajoute "Croiseur"
nomNav ajoute "Destroyer"
nomNav ajoute "Sous-marin"
nomNav ajoute "Torpilleur"
@ Placement de la flotte
// Remplit navTmp avec les cinq navires places au hasard, sans
// chevauchement. On tire une position au hasard et on recommence si
// elle ne convient pas : c'est plus court a ecrire qu'un placement
// savant, et sur une grille de 100 cases pour 17 occupees, cela
// aboutit en quelques essais.
procédure placerFlotte()
pour i de 0 à N_GRILLE * N_GRILLE - 1
navTmp[i] vaut 0
fin pour
pour nav de 1 à 5
ok vaut 0
essai vaut 0
tant que ok = 0 et essai < 500
essai vaut essai + 1
hori vaut hasard(1)
si hori = 1 alors
li vaut hasard(N_GRILLE - 1)
co vaut hasard(N_GRILLE - grandeurNav[nav])
sinon
li vaut hasard(N_GRILLE - grandeurNav[nav])
co vaut hasard(N_GRILLE - 1)
fin si
// on verifie d'abord que toutes les cases sont libres
ok vaut 1
pour k de 0 à grandeurNav[nav] - 1
si hori = 1 alors
idx vaut li * N_GRILLE + co + k
sinon
idx vaut (li + k) * N_GRILLE + co
fin si
si navTmp[idx] <> 0 alors
ok vaut 0
fin si
fin pour
// et seulement ensuite on pose le navire
si ok = 1 alors
pour k de 0 à grandeurNav[nav] - 1
si hori = 1 alors
navTmp[li * N_GRILLE + co + k] vaut nav
sinon
navTmp[(li + k) * N_GRILLE + co] vaut nav
fin si
fin pour
fin si
fin tant que
fin pour
fin procédure
procédure nouvellePartie()
appelle placerFlotte()
pour i de 0 à N_GRILLE * N_GRILLE - 1
navJ[i] vaut navTmp[i]
fin pour
appelle placerFlotte()
pour i de 0 à N_GRILLE * N_GRILLE - 1
navO[i] vaut navTmp[i]
tirJ[i] vaut 0
tirO[i] vaut 0
fin pour
pour i de 0 à 5
touchesJ[i] vaut 0
touchesO[i] vaut 0
fin pour
nbFile vaut 0
couleJ vaut 0
couleO vaut 0
coupsJ vaut 0
coupsO vaut 0
finie vaut faux
message vaut "A vous de jouer : cliquez sur la grille de droite."
fin procédure
@ Tir du joueur
procédure tirerJoueur(idx2)
si tirJ[idx2] = 0 alors
coupsJ vaut coupsJ + 1
si navO[idx2] = 0 alors
tirJ[idx2] vaut 1
message vaut "A l'eau."
sinon
tirJ[idx2] vaut 2
nav vaut navO[idx2]
touchesO[nav] vaut touchesO[nav] + 1
si touchesO[nav] = grandeurNav[nav] alors
couleO vaut couleO + 1
message vaut "Coule : " + nomNav[nav] + " !"
sinon
message vaut "Touche !"
fin si
fin si
fin si
fin procédure
@ Tir de l'ordinateur
// Depuis la case touchee, on avance dans une direction tant que l'on
// traverse des cases deja touchees, puis on empile la premiere case
// non tiree. C'est ce qui permet de prolonger un navire au lieu de
// retomber sur ses propres impacts.
procédure pousserBout(li3, co3, dli, dco)
l4 vaut li3
c4 vaut co3
fini vaut 0
tant que fini = 0
l4 vaut l4 + dli
c4 vaut c4 + dco
si l4 < 0 ou l4 >= N_GRILLE ou c4 < 0 ou c4 >= N_GRILLE alors
fini vaut 1
sinon si tirO[l4 * N_GRILLE + c4] = 0 alors
fileCase[nbFile] vaut l4 * N_GRILLE + c4
nbFile vaut nbFile + 1
fini vaut 1
sinon si tirO[l4 * N_GRILLE + c4] = 1 alors
fini vaut 1
fin si
fin tant que
fin procédure
procédure tirerOrdinateur()
idx vaut -1
// 1. une piste en attente ? on la suit
tant que idx < 0 et nbFile > 0
nbFile vaut nbFile - 1
si tirO[fileCase[nbFile]] = 0 alors
idx vaut fileCase[nbFile]
fin si
fin tant que
// 2. sinon, une case du damier tiree au hasard
si idx < 0 alors
essai vaut 0
tant que idx < 0 et essai < 600
essai vaut essai + 1
k vaut hasard(N_GRILLE * N_GRILLE - 1)
li vaut arrondi_inferieur(k / N_GRILLE)
co vaut k - li * N_GRILLE
si tirO[k] = 0 et (li + co) mod 2 = 0 alors
idx vaut k
fin si
fin tant que
fin si
// 3. en fin de partie il ne reste parfois que des cases impaires
si idx < 0 alors
pour k de 0 à N_GRILLE * N_GRILLE - 1
si tirO[k] = 0 et idx < 0 alors
idx vaut k
fin si
fin pour
fin si
si idx >= 0 alors
coupsO vaut coupsO + 1
li vaut arrondi_inferieur(idx / N_GRILLE)
co vaut idx - li * N_GRILLE
si navJ[idx] = 0 alors
tirO[idx] vaut 1
sinon
tirO[idx] vaut 2
nav vaut navJ[idx]
touchesJ[nav] vaut touchesJ[nav] + 1
si touchesJ[nav] = grandeurNav[nav] alors
couleJ vaut couleJ + 1
// navire coule : les pistes en cours ne servent plus a rien
nbFile vaut 0
sinon
// Le navire n'est pas coule. Est-il deja touche a cote ?
// Si oui, on connait son axe et on ne prolonge QUE cet axe.
hori vaut 0
si co > 0 alors
si tirO[li * N_GRILLE + co - 1] = 2 et navJ[li * N_GRILLE + co - 1] = nav alors
hori vaut 1
fin si
fin si
si co < N_GRILLE - 1 alors
si tirO[li * N_GRILLE + co + 1] = 2 et navJ[li * N_GRILLE + co + 1] = nav alors
hori vaut 1
fin si
fin si
si li > 0 alors
si tirO[(li - 1) * N_GRILLE + co] = 2 et navJ[(li - 1) * N_GRILLE + co] = nav alors
hori vaut 2
fin si
fin si
si li < N_GRILLE - 1 alors
si tirO[(li + 1) * N_GRILLE + co] = 2 et navJ[(li + 1) * N_GRILLE + co] = nav alors
hori vaut 2
fin si
fin si
si hori = 1 alors
nbFile vaut 0
appelle pousserBout(li, co, 0, 1)
appelle pousserBout(li, co, 0, -1)
sinon si hori = 2 alors
nbFile vaut 0
appelle pousserBout(li, co, 1, 0)
appelle pousserBout(li, co, -1, 0)
sinon
// premier impact : on empile les quatre voisins
appelle pousserBout(li, co, 0, 1)
appelle pousserBout(li, co, 0, -1)
appelle pousserBout(li, co, 1, 0)
appelle pousserBout(li, co, -1, 0)
fin si
fin si
fin si
fin si
fin procédure
@ Dessin
procédure dessinerGrille(g, ox, camp)
// camp = 1 : ma flotte, navires visibles
// camp = 2 : flotte ennemie, seuls mes tirs sont visibles
pour li de 0 à N_GRILLE - 1
pour co de 0 à N_GRILLE - 1
idx vaut li * N_GRILLE + co
ax vaut ox + co * CASE_B
ay vaut GY + li * CASE_B
teinte vaut rgb(30, 58, 95)
si camp = 1 alors
si navJ[idx] <> 0 alors
teinte vaut rgb(90, 104, 122)
fin si
fin si
rectangle(g, ax, ay, CASE_B - 2, CASE_B - 2, teinte)
si camp = 1 alors
tir vaut tirO[idx]
sinon
tir vaut tirJ[idx]
fin si
si tir = 1 alors
cercle(g, ax + CASE_B / 2 - 1, ay + CASE_B / 2 - 1, 4, #8AA4BE)
sinon si tir = 2 alors
rectangle(g, ax, ay, CASE_B - 2, CASE_B - 2, #C0392B)
ligne(g, ax + 5, ay + 5, ax + CASE_B - 7, ay + CASE_B - 7, #FFD9D2, 3)
ligne(g, ax + CASE_B - 7, ay + 5, ax + 5, ay + CASE_B - 7, #FFD9D2, 3)
fin si
fin pour
fin pour
// reperes : lettres au-dessus, chiffres a gauche
pour co de 0 à N_GRILLE - 1
// Pas de conversion ASCII dans CoddyRun : on decoupe simplement
// une chaine de lettres. copier(texte, debut, longueur) indexe a 1.
label(g, ox + co * CASE_B + 7, GY - 6, copier("ABCDEFGHIJ", co + 1, 1), #7F93AC, 12)
fin pour
pour li de 0 à N_GRILLE - 1
label(g, ox - 18, GY + li * CASE_B + 16, convertir_texte(li + 1), #7F93AC, 12)
fin pour
fin procédure
procédure dessinerFlotte(g, ox, camp)
pour nav de 1 à 5
sy vaut 392 + (nav - 1) * 14
si camp = 1 alors
k vaut touchesJ[nav]
sinon
k vaut touchesO[nav]
fin si
si k = grandeurNav[nav] alors
teinte vaut rgb(192, 57, 43)
sinon
teinte vaut rgb(127, 147, 172)
fin si
label(g, ox, sy, nomNav[nav] + " (" + convertir_texte(grandeurNav[nav]) + ")", teinte, 12)
si k = grandeurNav[nav] alors
ligne(g, ox, sy - 4, ox + 108, sy - 4, rgb(192, 57, 43), 2)
fin si
fin pour
fin procédure
procédure dessinerTout()
effacer(ecran)
rectangle(ecran, 0, 0, 640, 480, #0E1A2B)
label(ecran, 190, 40, "BATAILLE NAVALE", #4CA6E0, 26)
label(ecran, 46, 72, message, #E8EEF5, 15)
label(ecran, 46, 98, "MA FLOTTE", #7F93AC, 14)
label(ecran, 196, 98, convertir_texte(coupsO) + " tirs subis", #C0392B, 13)
label(ecran, 352, 98, "FLOTTE ENNEMIE", #7F93AC, 14)
label(ecran, 534, 98, convertir_texte(coupsJ) + " tirs", #4CA6E0, 13)
appelle dessinerGrille(ecran, GX_JOUEUR, 1)
appelle dessinerGrille(ecran, GX_ENNEMI, 2)
appelle dessinerFlotte(ecran, GX_JOUEUR, 1)
appelle dessinerFlotte(ecran, GX_ENNEMI, 2)
si finie alors
rectangle_arrondi(ecran, 150, 190, 340, 100, 12, #0A1220)
si couleO = 5 alors
label(ecran, 208, 232, "VICTOIRE", #4ADE80, 30)
label(ecran, 186, 264, "flotte ennemie coulee en " + convertir_texte(coupsJ) + " tirs", #A7F3D0, 14)
sinon
label(ecran, 224, 232, "DEFAITE", #F87171, 30)
label(ecran, 190, 264, "votre flotte a coule en " + convertir_texte(coupsO) + " tirs", #FCA5A5, 14)
fin si
label(ecran, 232, 470, "n = nouvelle partie", #5A6C82, 13)
sinon
label(ecran, 46, 470, "clic = tirer n = nouvelle partie p = quitter", #3E4E63, 12)
fin si
affiche ecran
fin procédure
@ Programme principal
appelle nouvellePartie()
appelle dessinerTout()
tant que enJeu
interagir ecran, ["n", "p"] dans action, ptX, ptY
si action = 0 alors
co vaut arrondi_inferieur((ptX - GX_ENNEMI) / CASE_B)
li vaut arrondi_inferieur((ptY - GY) / CASE_B)
si non finie et ptX >= GX_ENNEMI et ptY >= GY alors
si co >= 0 et co < N_GRILLE et li >= 0 et li < N_GRILLE alors
idx vaut li * N_GRILLE + co
si tirJ[idx] = 0 alors
appelle tirerJoueur(idx)
si couleO = 5 alors
finie vaut vrai
sinon
// l'ordinateur replique aussitot : un tir chacun
appelle tirerOrdinateur()
si couleJ = 5 alors
finie vaut vrai
fin si
fin si
fin si
fin si
fin si
sinon si action = 1 alors
appelle nouvellePartie()
sinon
enJeu vaut faux
arrête
fin si
appelle dessinerTout()
fin tant que
affiche "Partie terminee - " + convertir_texte(coupsJ) + " tirs joues"