CoddyRun
Guide complet

De CoddyRun à JavaScript

Votre programme fonctionne dans CoddyRun ; voici comment en faire une vraie page web, en HTML, CSS et JavaScript écrit comme sur n'importe quel site. La syntaxe se traduit presque mot pour mot. Ce qui change vraiment, c'est la logique : un programme CoddyRun attend l'utilisateur, une page web réagit à ce qu'il fait. Ce guide montre comment passer de l'un à l'autre, instruction par instruction.

Le changement de logique
D'un programme qui attend à une page qui réagit
Un programme CoddyRun se lit de haut en bas et s'arrête pour attendre : demande jusqu'à la saisie, cliquer jusqu'au clic, pause pendant un délai. Une page web ne s'arrête jamais : elle s'affiche, puis réagit à ce que fait l'utilisateur. Convertir un programme, ce n'est donc pas traduire les lignes une à une ; c'est redistribuer son contenu en trois parties.
1. L'état
Les variables qui décrivent la situation à un instant donné : le score, la position de la balle, l'étape du questionnaire. En CoddyRun, ce sont vos déclarations.
2. L'affichage
Une fonction qui montre l'état à l'écran. On l'appelle chaque fois que l'état change. En CoddyRun, ce sont vos affiche et vos dessins.
3. Les réactions
Des fonctions déclenchées par un clic, une touche, une saisie validée ou un minuteur. Chacune modifie l'état, puis rappelle l'affichage. En CoddyRun, c'est ce qui suit chaque demande, cliquer ou pause.
Ce qui ne change pas. Les calculs, les conditions, les boucles sans attente, les tableaux et les fonctions se traduisent presque mot pour mot : les correspondances sont données plus bas, de Types, variables et constantes à Conditions et boucles. Seules les instructions qui attendent obligent à réorganiser le programme, et ce sont elles que traitent Afficher dans la page, Les entrées deviennent des événements et Le temps, l'animation et la toile.
La structure d'une page
Trois fichiers : le contenu, la présentation, le comportement

La console de CoddyRun disparaît : à sa place, on écrit directement en HTML les éléments dont le programme a besoin — un titre, un champ de saisie, une zone de résultat, une toile de dessin. Le JavaScript se contente ensuite de les remplir et de réagir.

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Mon programme</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Mon programme</h1>

    <form id="formulaire">
        <label for="saisie">Ton nom</label>
        <input id="saisie" required>
        <button>Valider</button>
    </form>

    <p id="resultat"></p>
    <canvas id="toile" width="300" height="200"></canvas>

    <script src="programme.js"></script>
</body>
</html>
// programme.js

// 1. Les éléments de la page
const formulaire = document.getElementById('formulaire');
const resultat = document.getElementById('resultat');

// 2. L'état
let score = 0;

// 3. L'affichage
function afficher() {
    resultat.textContent = 'Score : ' + score;
}

// 4. Les réactions
formulaire.addEventListener('submit', evenement => {
    evenement.preventDefault();       // empêche le rechargement de la page
    score += 1;
    afficher();
});

// 5. Le démarrage
afficher();
Dans les sections consacrées à la syntaxe, de Types, variables à Conditions et boucles, console.log() tient lieu d'affiche : le résultat s'affiche dans la console du navigateur, ouverte avec F12. Afficher dans la page montre comment écrire dans la page.
Types, variables et constantes
La déclaration typée devient une initialisation
CoddyRun
@ Déclarations
age est un nombre
nom est un texte
actif est un booléen
scores est un tableau
x, y, z est un nombre
xPI est une constante vaut 3.14159

age vaut 25
nom vaut "Alice"
JavaScript
// Déclarations : valeur par défaut du type
let age = 0;
let nom = '';
let actif = false;
let scores = [];
let x = 0, y = 0, z = 0;
const xPI = 3.14159;

age = 25;
nom = 'Alice';

Reproduisez explicitement la valeur par défaut de chaque type (0, '', false, []). Sans elle, une variable vaut undefined et le moindre calcul produit NaN.

CoddyRunJavaScriptRemarque
nombrelet n = 0;Un seul type numérique dans les deux langages.
textelet t = '';
booléenlet b = false;vrai / faux deviennent true / false.
tableaulet t = [];Index à partir de 0 dans les deux langages.
enregistrementlet p = {};Un objet.
dictionnairelet d = new Map();Voir Tableaux, dictionnaires.
date / heurelet d = new Date();Voir Données et dates.
toileconst ctx = canvas.getContext('2d');Un élément <canvas> de la page. Voir La toile.
est une constante vautconst
La casse. CoddyRun ne distingue pas les majuscules : Score et score sont la même variable. JavaScript les distingue. Uniformisez l'écriture de chaque nom avant de convertir, et vérifiez qu'aucun n'est un mot réservé de JavaScript : class, new, delete, function, default…
Opérateurs et texte
Les symboles qui changent, et l'index des textes
CoddyRunJavaScriptRemarque
====Comparaison stricte. Un seul = affecte la variable au lieu de la comparer.
<>!==
et ou non&& || !
a mod ba % bEn JavaScript, le signe du résultat suit a : vérifiez avec des nombres négatifs.
a ^ ba ** bLe ^ de JavaScript est un « ou exclusif » binaire : 2 ^ 3 vaut 1.
"Bon" + "jour"'Bon' + 'jour'Identique.
#65String.fromCharCode(65)Caractère par son code.
n ajoute 1n += 1Sur un nombre ou un texte.
n soustrait 1n -= 1
CoddyRun
mot est un texte
mot vaut "Bonjour"
affiche copier(mot, 2, 3)      // "onj"
affiche position("j", mot)     // 4, et 0 si absent
JavaScript
let mot = 'Bonjour';
console.log(mot.slice(1, 1 + 3));     // début - 1, puis longueur
console.log(mot.indexOf('j') + 1);    // -1 + 1 = 0 si absent

Le décalage d'index est la première source d'erreurs. Les tableaux commencent à 0 dans les deux langages, mais les textes commencent à 1 en CoddyRun et à 0 en JavaScript : soustrayez 1 à chaque position de caractère. Pour position(), ajouter 1 à indexOf donne exactement le comportement de CoddyRun, y compris le 0 quand le motif est absent.

Tableaux, enregistrements, dictionnaires, classes
Des correspondances directes
CoddyRun
scores est un tableau
scores ajoute 10
scores ajoute 20
scores[1] vaut 99
scores supprime 0
vide scores

personne est un enregistrement
personne.nom vaut "Alice"
personne.age ajoute 1
JavaScript
let scores = [];
scores.push(10);
scores.push(20);
scores[1] = 99;
scores.splice(0, 1);       // supprime l'index 0
scores.length = 0;         // vide le tableau

let personne = {};
personne.nom = 'Alice';
personne.age = (personne.age ?? 0) + 1;
CoddyRun
contacts est un dictionnaire
contacts vaut ['nom': 'Jean', 'age': 25]
contacts['ville'] vaut 'Paris'
contacts supprime 'nom'
si contient(contacts, 'age') alors
    affiche contacts['age']
fin si
liste est un tableau
liste vaut cles(contacts)
JavaScript
let contacts = new Map([['nom', 'Jean'], ['age', 25]]);
contacts.set('ville', 'Paris');
contacts.delete('nom');
if (contacts.has('age')) {
    console.log(contacts.get('age'));
}

let liste = [];
liste = [...contacts.keys()];

Préférez Map à un objet simple pour un dictionnaire : elle conserve l'ordre d'insertion comme CoddyRun, et accepte n'importe quelle clé sans collision avec les propriétés internes des objets.

CoddyRun
classe Personne :
    nom, prenom est un texte
    age est un nombre
    actif est un booléen
fin classe
JavaScript
class Personne {
    constructor() {
        this.nom = '';
        this.prenom = '';
        this.age = 0;
        this.actif = false;
    }
}
const p = new Personne();
Conditions et boucles
Tant qu'elles n'attendent rien, elles se traduisent directement
CoddyRun
si age >= 18 alors
    affiche "Majeur"
sinon si age >= 13 alors
    affiche "Adolescent"
sinon
    affiche "Enfant"
fin si

selon jour
    cas 1 : affiche "Lundi"
    cas 2 : affiche "Mardi"
    sinon selon : affiche "Autre"
fin selon
JavaScript
if (age >= 18) {
    console.log('Majeur');
} else if (age >= 13) {
    console.log('Adolescent');
} else {
    console.log('Enfant');
}

switch (jour) {
    case 1: console.log('Lundi'); break;
    case 2: console.log('Mardi'); break;
    default: console.log('Autre');
}

Terminez chaque case par break : sans lui, JavaScript enchaîne sur le cas suivant, ce que CoddyRun ne fait jamais.

CoddyRun
tant que x < 10
    x vaut x + 1
fin tant que

répète 5 fois
    affiche "Salut"
fin répète

pour i de 1 à 10
    affiche i
fin pour

pour i de 10 à 1 pas -1
    affiche i
fin pour
JavaScript
while (x < 10) {
    x = x + 1;
}

for (let k = 0; k < 5; k++) {
    console.log('Salut');
}

for (let i = 1; i <= 10; i++) {    // borne incluse : <=
    console.log(i);
}

for (let i = 10; i >= 1; i -= 1) { // pas négatif : >=
    console.log(i);
}

La borne de pour est incluse : de 1 à 10 fait dix tours, d'où <=. Avec un pas négatif, la comparaison s'inverse. arrête et continue deviennent break et continue.

Une boucle qui contient une attente ne se traduit pas en boucle. Un tant que qui fait demande à chaque tour, ou un pour qui attend un clic, deviennent un compteur dans l'état et une réaction qui le fait avancer. Les entrées deviennent des événements montre comment. Une boucle sans fin en JavaScript fige l'onglet : il n'y a pas de limite de sécurité comme dans CoddyRun.
Fonctions, procédures et erreurs
Presque identiques
CoddyRun
fonction carre(x)
    retourne x * x
fin fonction

procédure saluer(nom)
    affiche "Bonjour " + nom
fin procédure

resultat vaut carre(5)
appelle saluer("Alice")
JavaScript
function carre(x) {
    return x * x;
}

function saluer(nom) {
    console.log('Bonjour ' + nom);
}

resultat = carre(5);
saluer('Alice');                  // « appelle » disparaît
CoddyRun
essayer
    n vaut convertir_nombre(saisie)
attraper
    affiche "Ce n'est pas un nombre"
fin essayer
JavaScript
n = Number(saisie);
if (Number.isNaN(n)) {
    console.log("Ce n'est pas un nombre");
}

Beaucoup d'opérations qui déclenchent une erreur en CoddyRun ne le font pas en JavaScript : Number('abc') renvoie NaN sans rien signaler. Testez explicitement le résultat. try / catch reste utile pour les vraies exceptions, comme une lecture de données qui échoue.

CoddyRun
si rayon <= 0 alors
    affiche "Le rayon doit être positif."
    terminer
fin si
JavaScript
if (rayon <= 0) {
    resultat.textContent = 'Le rayon doit être positif.';
    return;                       // quitte la réaction en cours
}

terminer n'a pas d'équivalent direct : une page ne s'arrête pas. Dans une réaction, return interrompt le traitement ; pour mettre fin à un jeu, on désactive les contrôles (bouton.disabled = true) ou on retire l'écouteur d'événement.

Afficher dans la page
Écrire dans des éléments plutôt que dans une console
CoddyRun
affiche "Bonjour " + nom
couleur(#F4212E, "Attention !")
html("<h2>Résultats</h2>")
déboguer scores
JavaScript
// Remplacer le contenu d'un élément
resultat.textContent = 'Bonjour ' + nom;

// Ajouter une ligne à un journal
const ligne = document.createElement('p');
ligne.textContent = 'Attention !';
ligne.className = 'alerte';       // couleur définie en CSS
journal.append(ligne);

// Du HTML que vous écrivez vous-même
titre.innerHTML = '<h2>Résultats</h2>';

console.log(scores);

Utilisez textContent pour tout ce qui vient de l'utilisateur ou d'un calcul : le texte est affiché tel quel. innerHTML interprète les balises ; ne l'employez que pour du contenu que vous avez écrit vous-même, sans quoi une saisie contenant du code serait exécutée.

/* style.css */
.alerte {
    color: #F4212E;
}
Le réflexe idiomatique. Plutôt que d'accumuler des lignes comme dans une console, prévoyez dans le HTML un élément par information — le score, le message, la question en cours — et mettez à jour son contenu. La page reste lisible, et une fonction afficher() unique, appelée après chaque changement, garde tout cohérent.
Les entrées deviennent des événements
Ce qui suivait l'attente devient le contenu d'une réaction
CoddyRun
nom est un texte
demande "Ton nom ? " dans nom
affiche "Bonjour " + nom
JavaScript
// HTML : <form id="f"><input id="nom" required><button>OK</button></form>
//        <p id="resultat"></p>
const f = document.getElementById('f');
const resultat = document.getElementById('resultat');
f.addEventListener('submit', e => {
    e.preventDefault();
    const nom = document.getElementById('nom').value;
    resultat.textContent = 'Bonjour ' + nom;
});

Tout ce qui suivait la demande passe dans la réaction à submit. Un formulaire, plutôt qu'un simple bouton, permet de valider avec la touche Entrée et apporte la vérification required gratuitement.

CoddyRun
age est un nombre
demande "Ton âge ? " dans age
JavaScript
// HTML : <input id="age" type="number" min="0" required>
const age = Number(document.getElementById('age').value);

Une saisie est toujours un texte en JavaScript : '3' + 1 donne '31'. Convertissez avec Number(), et utilisez type="number" pour que le navigateur n'accepte que des chiffres.

CoddyRun
choix est un nombre
choisir ["Rouge", "Vert", "Bleu"] dans choix
affiche choix
JavaScript
// HTML : <div id="choix">
//          <button data-n="1">Rouge</button>
//          <button data-n="2">Vert</button>
//          <button data-n="3">Bleu</button>
//        </div>
document.getElementById('choix').addEventListener('click', e => {
    const bouton = e.target.closest('button');
    if (!bouton) return;
    const choix = Number(bouton.dataset.n);
    console.log(choix);
});

Un seul écouteur sur le conteneur suffit pour tous les boutons : closest retrouve celui qui a été cliqué. L'attribut data-n conserve l'index de 1 à n de CoddyRun.

CoddyRun
action est un nombre
appuyer ['z', 's', 'd', 'q'] dans action
JavaScript
const touches = ['z', 's', 'd', 'q'];
document.addEventListener('keydown', e => {
    const action = touches.indexOf(e.key.toLowerCase()) + 1;
    if (action === 0) return;          // autre touche : on ignore
    e.preventDefault();
    deplacer(action);
});

Pour les flèches du clavier, comparez e.key à 'ArrowUp', 'ArrowDown', 'ArrowLeft' et 'ArrowRight'.

CoddyRun
x, y est un nombre
cliquer maToile dans x, y
JavaScript
canvas.addEventListener('click', e => {
    const r = canvas.getBoundingClientRect();
    const x = (e.clientX - r.left) * canvas.width / r.width;
    const y = (e.clientY - r.top) * canvas.height / r.height;
    traiterClic(x, y);
});

La mise à l'échelle compte : si la toile est affichée plus petite ou plus grande que sa taille réelle, sur un téléphone par exemple, les coordonnées brutes seraient fausses. interagir se traduit simplement par les deux écouteurs à la fois, clavier et clic, appelant les mêmes fonctions.

Une boucle qui attend

C'est la conversion la plus délicate, et la plus formatrice. La boucle disparaît : son compteur rejoint l'état, et la réaction le fait avancer à chaque événement.

CoddyRun
somme est un nombre
n est un nombre
pour i de 1 à 3
    demande "Nombre " + i + " : " dans n
    somme ajoute n
fin pour
affiche "Somme : " + somme
JavaScript
// HTML : <form id="f"><label id="question"></label>
//          <input id="n" type="number" required><button>OK</button></form>
//        <p id="resultat"></p>
const f = document.getElementById('f');
const question = document.getElementById('question');
const resultat = document.getElementById('resultat');

let i = 1;
let somme = 0;

function afficher() {
    question.textContent = 'Nombre ' + i + ' : ';
}

f.addEventListener('submit', e => {
    e.preventDefault();
    somme += Number(document.getElementById('n').value);
    i += 1;
    f.reset();
    if (i > 3) {                      // condition de fin de la boucle
        f.hidden = true;
        resultat.textContent = 'Somme : ' + somme;
    } else {
        afficher();
    }
});

afficher();

Le compteur i et l'accumulateur somme sont devenus l'état ; le corps de la boucle est devenu la réaction ; la condition de sortie est testée à la fin de chaque réaction. Ce schéma s'applique à toutes les boucles qui attendent.

Le temps, l'animation et la toile
Les minuteurs remplacent pause et processus ; le canvas remplace la toile
CoddyRun
affiche "Trois..."
pause 1000
affiche "Deux..."
pause 1000
affiche "Partez !"
JavaScript
resultat.textContent = 'Trois...';
setTimeout(() => {
    resultat.textContent = 'Deux...';
    setTimeout(() => {
        resultat.textContent = 'Partez !';
    }, 1000);
}, 1000);

setTimeout programme une action plus tard, sans bloquer la page. Pour plusieurs étapes successives, ce schéma suffit ; au-delà de trois ou quatre, préférez un compteur d'étapes dans l'état, comme pour les boucles qui attendent.

CoddyRun
processus Balle()
    tant que vrai
        x ajoute 5
        si x > 300 alors
            x vaut 0
        fin si
        effacer(t)
        cercle(t, x, 100, 10, #FFD43B)
        affiche t
        pause 30
    fin tant que
fin processus

Balle()
JavaScript
let x = 0;
let enPause = false;

function image() {
    if (!enPause) {
        x += 5;
        if (x > 300) x = 0;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#FFD43B';
        ctx.beginPath();
        ctx.arc(x, 100, 10, 0, Math.PI * 2);
        ctx.fill();
    }
    requestAnimationFrame(image);       // image suivante
}

requestAnimationFrame(image);           // démarre l'animation

requestAnimationFrame appelle la fonction à chaque rafraîchissement de l'écran, environ 60 fois par seconde, et se met en veille quand l'onglet est caché. C'est la façon idiomatique d'animer. suspendre et reprendre deviennent un simple booléen, enPause, que l'on bascule depuis une réaction. Pour un rythme lent et régulier, setInterval(image, 100) convient aussi.

CoddyRun
t est une toile
dimension(t, 300, 200)
remplir(t, #1E2430)
rectangle(t, 20, 20, 60, 30, #1D9BF0)
cercle(t, 150, 100, 40, #FFD43B)
ligne(t, 0, 190, 300, 190, #FFFFFF, 2)
label(t, 10, 10, "Score", #FFFFFF, 14)
affiche t
JavaScript
// HTML : <canvas id="toile" width="300" height="200"></canvas>
const canvas = document.getElementById('toile');
const ctx = canvas.getContext('2d');

ctx.fillStyle = '#1E2430';
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = '#1D9BF0';
ctx.fillRect(20, 20, 60, 30);

ctx.fillStyle = '#FFD43B';
ctx.beginPath();
ctx.arc(150, 100, 40, 0, Math.PI * 2);
ctx.fill();

ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(0, 190);
ctx.lineTo(300, 190);
ctx.stroke();

ctx.fillStyle = '#FFFFFF';
ctx.font = '14px sans-serif';
ctx.textBaseline = 'top';
ctx.fillText('Score', 10, 10);

Le canvas dessine immédiatement : il n'y a pas d'équivalent à affiche t. La couleur se règle avant la forme, avec fillStyle pour le remplissage et strokeStyle pour le trait. textBaseline = 'top' place le texte par son coin supérieur, comme label.

CoddyRunJavaScriptRemarque
dimension(t, l, h)<canvas width="l" height="h">Ou canvas.width = l en JavaScript.
remplir(t, c)ctx.fillStyle = c; ctx.fillRect(0, 0, l, h)
effacer(t)ctx.clearRect(0, 0, l, h)
rectangle(t, x, y, l, h, c)ctx.fillRect(x, y, l, h)Après ctx.fillStyle = c.
rectangle_arrondi(...)ctx.roundRect(x, y, l, h, r); ctx.fill()Précédé de ctx.beginPath().
cercle(t, cx, cy, r, c)ctx.arc(cx, cy, r, 0, 2 * Math.PI)Entre beginPath() et fill().
ellipse(t, cx, cy, rx, ry, c)ctx.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI)Idem.
arc(t, cx, cy, r, a1, a2, c)ctx.arc(cx, cy, r, a1, a2)Angles en radians.
ligne(t, x1, y1, x2, y2, c, e)moveTo, lineTo, strokelineWidth pour l'épaisseur.
polygone / trianglemoveTo, puis lineTo par sommet, closePath, fill
contour(t, c, e)ctx.strokeStyle = c; ctx.lineWidth = ePuis ctx.stroke() après chaque fill().
label(t, x, y, texte, c, taille)ctx.font = taille + 'px sans-serif'; ctx.fillText(texte, x, y)
dégradé(t, [c1, c2])ctx.createLinearGradient(0, 0, l, 0)Puis addColorStop pour chaque couleur.
svg(t, x, y, image, l, h)ctx.drawImage(img, x, y, l, h)Avec un new Image() chargé au préalable.
enregistrer(t, chemin)canvas.toDataURL('image/png')Une image PNG, à proposer au téléchargement.
CoddyRun
si clique(x, y, cx, cy, 18) alors
    score ajoute 1
fin si
JavaScript
function dansCercle(x, y, cx, cy, r) {
    return (x - cx) ** 2 + (y - cy) ** 2 <= r * r;
}

function dansRectangle(x, y, rx, ry, l, h) {
    return x >= rx && x <= rx + l && y >= ry && y <= ry + h;
}

if (dansCercle(x, y, cx, cy, 18)) {
    score += 1;
}

Le test de zone de clique() s'écrit en deux petites fonctions, à placer en tête du programme.

Canvas ou SVG ? Le canvas est le plus proche de la toile CoddyRun : on dessine, puis on efface et on redessine pour animer. Le SVG, lui, garde chaque forme comme un élément de la page, que l'on peut modifier, styler en CSS et cliquer individuellement. Pour un jeu ou une animation, choisissez le canvas ; pour un schéma interactif dont on change quelques formes, le SVG.
Données, fichiers et dates
Le disque devient le navigateur
CoddyRunJavaScriptRemarque
paramètre('jeu', 'score', 52)localStorage.setItem('jeu.score', JSON.stringify(52))Conservé dans le navigateur, d'une visite à l'autre.
paramètre('jeu', 'score')JSON.parse(localStorage.getItem('jeu.score'))Renvoie null si absent, au lieu d'une erreur.
importer("https://…")fetch(url).then(r => r.text())Un fichier du disque n'est pas lisible par une page web, sauf choisi par l'utilisateur avec <input type="file">.
sauvegarder(chemin, texte)un lien de téléchargement vers un BlobLe navigateur propose le fichier ; il ne l'écrit pas en silence.
maintenant()new Date()
annee_de(d) mois_de(d) jour_de(d)d.getFullYear() d.getMonth() + 1 d.getDate()Les mois commencent à 0 en JavaScript.
heure_de(h) minute_de(h)d.getHours() d.getMinutes()
format_date(d, motif)d.toLocaleDateString('fr-FR')Format français automatique.
chrono()performance.now()Millisecondes haute résolution.
// Équivalent de sauvegarder('scores.txt', texte)
function telecharger(nomFichier, texte) {
    const blob = new Blob([texte], { type: 'text/plain' });
    const lien = document.createElement('a');
    lien.href = URL.createObjectURL(blob);
    lien.download = nomFichier;
    lien.click();
    URL.revokeObjectURL(lien.href);
}
Fonctions natives courantes
Les équivalents directs
CoddyRunJavaScriptRemarque
racine(x) absolue(x)Math.sqrt(x) Math.abs(x)
arrondi(x)Math.round(x)Diffère sur -2.5 : JavaScript donne -2. Vérifiez si vos données sont négatives.
arrondi_superieur / inferieurMath.ceil / Math.floor
decimal(x, n)Number(x.toFixed(n))
hasard(n)Math.floor(Math.random() * (n + 1))De 0 à n inclus.
hasard(a, b)a + Math.floor(Math.random() * (b - a + 1))De a à b inclus.
minimum(a, b) maximum(a, b)Math.min(a, b) Math.max(a, b)
limiter(x, a, b)Math.min(Math.max(x, a), b)
sinus(x) pi()Math.sin(x) Math.PIRadians dans les deux langages.
longueur(x)x.lengthPour un dictionnaire : d.size.
majuscules(t) minuscules(t)t.toUpperCase() t.toLowerCase()
supprime_espace(t)t.trim()
contient(t, m)t.includes(m)Pour un dictionnaire : d.has(m).
remplacer(t, a, b)t.replaceAll(a, b)
decouper(t, s) joindre(tab, s)t.split(s) tab.join(s)
somme(tab)tab.reduce((a, b) => a + b, 0)
trier(tab)tab.sort((a, b) => a - b)Sans fonction de comparaison, JavaScript trie les nombres comme du texte : 10 avant 9.
melanger(tab)tab.sort(() => Math.random() - 0.5)Suffisant pour un jeu ; non uniforme statistiquement.
index_de(tab, v)tab.indexOf(v)-1 si absent, comme CoddyRun.
convertir_texte(x)String(x)Écrit true / false pour un booléen.
convertir_nombre(x)Number(x)Renvoie NaN au lieu d'une erreur.
sialors(c, a, b)c ? a : b
pair(n) impair(n)n % 2 === 0 n % 2 !== 0
Exemples convertis
Huit programmes, chacun centré sur une instruction CoddyRun

Chaque exemple montre le programme CoddyRun et sa version web complète, prête à copier dans un fichier .html. Ils vont du plus simple au plus délicat : Aire d'un cercle · Somme de trois nombres · Le juste prix · Un quiz à choix · Un compte à rebours · Déplacer un carré au clavier · Attraper la cible · Une balle qui rebondit.

Aire d'un cercle

demande

Une saisie, un calcul, une sortie anticipée avec terminer.

CoddyRun
xPI est une constante vaut 3.14159

fonction airecercle(rayon)
    retourne xPI * rayon ^ 2
fin fonction

rayon est un nombre
demande "Entre un rayon : " dans rayon

si rayon <= 0 alors
    affiche "Le rayon doit être positif."
    terminer
fin si

affiche "Aire : " + convertir_texte(arrondi(airecercle(rayon)))
HTML et JavaScript
<form id="formulaire">
    <label for="rayon">Entre un rayon :</label>
    <input id="rayon" type="number" step="any" required>
    <button>Calculer</button>
</form>
<p id="resultat"></p>

<script>
    const PI = 3.14159;
    const formulaire = document.getElementById('formulaire');
    const resultat = document.getElementById('resultat');

    function aireCercle(rayon) {
        return PI * rayon ** 2;
    }

    formulaire.addEventListener('submit', e => {
        e.preventDefault();
        const rayon = Number(document.getElementById('rayon').value);

        if (rayon <= 0) {
            resultat.textContent = 'Le rayon doit être positif.';
            return;
        }

        resultat.textContent = 'Aire : ' + Math.round(aireCercle(rayon));
    });
</script>

La demande devient un formulaire ; ce qui la suivait passe dans la réaction à submit, et terminer devient return.

Somme de trois nombres

boucle qui attend

La conversion la plus formatrice : une boucle pour qui demande une saisie à chaque tour.

CoddyRun
somme est un nombre
n est un nombre

pour i de 1 à 3
    demande "Nombre " + convertir_texte(i) + " : " dans n
    somme ajoute n
fin pour

affiche "Somme : " + convertir_texte(somme)
HTML et JavaScript
<form id="formulaire">
    <label for="n" id="question"></label>
    <input id="n" type="number" step="any" required>
    <button>Valider</button>
</form>
<p id="resultat"></p>

<script>
    const formulaire = document.getElementById('formulaire');
    const question = document.getElementById('question');
    const resultat = document.getElementById('resultat');

    let i = 1;
    let somme = 0;

    function afficher() {
        question.textContent = 'Nombre ' + i + ' : ';
    }

    formulaire.addEventListener('submit', e => {
        e.preventDefault();
        somme += Number(document.getElementById('n').value);
        i += 1;
        formulaire.reset();

        if (i > 3) {
            formulaire.hidden = true;
            resultat.textContent = 'Somme : ' + somme;
        } else {
            afficher();
        }
    });

    afficher();
</script>

La boucle a disparu : son compteur i et l'accumulateur somme sont devenus l'état, et la condition de fin est testée à la fin de chaque réaction.

Le juste prix

tant que + demande

Un tant que dont on ne connaît pas le nombre de tours à l'avance.

CoddyRun
secret est un nombre
essai est un nombre
coups est un nombre

secret vaut hasard(1, 100)
essai vaut 0

tant que essai <> secret
    demande "Ton essai : " dans essai
    coups ajoute 1
    si essai < secret alors
        affiche "C'est plus !"
    sinon si essai > secret alors
        affiche "C'est moins !"
    fin si
fin tant que

affiche "Gagné en " + convertir_texte(coups) + " coups !"
HTML et JavaScript
<p>J'ai choisi un nombre entre 1 et 100.</p>
<form id="formulaire">
    <label for="essai">Ton essai :</label>
    <input id="essai" type="number" min="1" max="100" required>
    <button>Proposer</button>
</form>
<p id="indice"></p>

<script>
    const formulaire = document.getElementById('formulaire');
    const indice = document.getElementById('indice');

    const secret = 1 + Math.floor(Math.random() * 100);
    let coups = 0;

    formulaire.addEventListener('submit', e => {
        e.preventDefault();
        const essai = Number(document.getElementById('essai').value);
        coups += 1;
        formulaire.reset();

        if (essai < secret) {
            indice.textContent = "C'est plus !";
        } else if (essai > secret) {
            indice.textContent = "C'est moins !";
        } else {
            indice.textContent = 'Gagné en ' + coups + ' coups !';
            formulaire.hidden = true;
        }
    });
</script>

La condition du tant que est devenue la dernière branche du if : quand l'essai est bon, la « boucle » s'arrête en masquant le formulaire.

Un quiz à choix

choisir

Plusieurs questions à choix, rangées dans un tableau plutôt que recopiées.

CoddyRun
score est un nombre
choix est un nombre

affiche "Quelle est la capitale de la France ?"
choisir ["Lyon", "Paris", "Marseille"] dans choix
si choix = 2 alors
    score ajoute 1
fin si

affiche "Combien font 7 × 8 ?"
choisir ["54", "56", "64"] dans choix
si choix = 2 alors
    score ajoute 1
fin si

affiche "Score : " + convertir_texte(score) + " / 2"
HTML et JavaScript
<p id="question"></p>
<div id="choix"></div>
<p id="resultat"></p>

<script>
    const questions = [
        { texte: 'Quelle est la capitale de la France ?', options: ['Lyon', 'Paris', 'Marseille'], bonne: 2 },
        { texte: 'Combien font 7 × 8 ?', options: ['54', '56', '64'], bonne: 2 },
    ];
    const zoneQuestion = document.getElementById('question');
    const zoneChoix = document.getElementById('choix');
    const resultat = document.getElementById('resultat');

    let numero = 0;
    let score = 0;

    function afficher() {
        if (numero === questions.length) {
            zoneQuestion.textContent = '';
            zoneChoix.replaceChildren();
            resultat.textContent = 'Score : ' + score + ' / ' + questions.length;
            return;
        }
        const q = questions[numero];
        zoneQuestion.textContent = q.texte;
        zoneChoix.replaceChildren(...q.options.map((option, i) => {
            const bouton = document.createElement('button');
            bouton.textContent = option;
            bouton.dataset.n = i + 1;
            return bouton;
        }));
    }

    zoneChoix.addEventListener('click', e => {
        const bouton = e.target.closest('button');
        if (!bouton) return;
        if (Number(bouton.dataset.n) === questions[numero].bonne) score += 1;
        numero += 1;
        afficher();
    });

    afficher();
</script>

Les deux blocs presque identiques du programme CoddyRun sont devenus des données. Ajouter une troisième question ne demande plus qu'une ligne dans le tableau questions.

Un compte à rebours

pause

Une boucle rythmée par pause, convertie en minuteur.

CoddyRun
pour i de 5 à 1 pas -1
    affiche i
    pause 1000
fin pour

affiche "Décollage !"
HTML et JavaScript
<button id="lancer">Lancer</button>
<p id="ecran" style="font-size:2rem;font-weight:700"></p>

<script>
    const bouton = document.getElementById('lancer');
    const ecran = document.getElementById('ecran');

    let n = 0;
    let minuteur = null;

    function tic() {
        if (n > 0) {
            ecran.textContent = n;
            n -= 1;
        } else {
            ecran.textContent = 'Décollage !';
            clearInterval(minuteur);
            minuteur = null;
            bouton.disabled = false;
        }
    }

    bouton.addEventListener('click', () => {
        n = 5;
        bouton.disabled = true;
        tic();
        minuteur = setInterval(tic, 1000);
    });
</script>

setInterval appelle tic chaque seconde ; le compteur n remplace la variable de boucle, et clearInterval arrête le minuteur quand la boucle aurait pris fin.

Déplacer un carré au clavier

appuyer + toile

Une boucle infinie qui attend une touche, puis redessine.

CoddyRun
t est une toile
x, y est un nombre
action est un nombre

dimension(t, 300, 200)
x vaut 140
y vaut 90

tant que vrai
    effacer(t)
    remplir(t, #1E2430)
    rectangle(t, x, y, 20, 20, #1D9BF0)
    affiche t
    appuyer ['z', 's', 'q', 'd'] dans action
    si action = 1 alors
        y soustrait 10
    sinon si action = 2 alors
        y ajoute 10
    sinon si action = 3 alors
        x soustrait 10
    sinon
        x ajoute 10
    fin si
    x vaut limiter(x, 0, 280)
    y vaut limiter(y, 0, 180)
fin tant que
HTML et JavaScript
<p>Cliquez dans le cadre, puis utilisez Z, Q, S, D ou les flèches.</p>
<canvas id="toile" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('toile');
    const ctx = canvas.getContext('2d');

    let x = 140;
    let y = 90;

    const deplacements = {
        z: [0, -10], s: [0, 10], q: [-10, 0], d: [10, 0],
        arrowup: [0, -10], arrowdown: [0, 10], arrowleft: [-10, 0], arrowright: [10, 0],
    };

    function dessiner() {
        ctx.fillStyle = '#1E2430';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#1D9BF0';
        ctx.fillRect(x, y, 20, 20);
    }

    document.addEventListener('keydown', e => {
        const d = deplacements[e.key.toLowerCase()];
        if (!d) return;
        e.preventDefault();
        x = Math.min(Math.max(x + d[0], 0), 280);
        y = Math.min(Math.max(y + d[1], 0), 180);
        dessiner();
    });

    dessiner();
</script>

Le tant que vrai a disparu : la page attend déjà les touches en permanence. La cascade de si est devenue une table de correspondance, qui accepte aussi les flèches sans une ligne de plus.

Attraper la cible

cliquer + toile

Une boucle pour qui attend un clic à chaque tour.

CoddyRun
t est une toile
score est un nombre
cx, cy est un nombre
x, y est un nombre

dimension(t, 300, 200)
pour i de 1 à 5
    cx vaut hasard(20, 280)
    cy vaut hasard(20, 180)
    effacer(t)
    remplir(t, #1E2430)
    cercle(t, cx, cy, 18, #FFD43B)
    label(t, 8, 6, "Score : " + convertir_texte(score), #FFFFFF, 14)
    affiche t
    cliquer t dans x, y
    si clique(x, y, cx, cy, 18) alors
        score ajoute 1
        affiche "Touché !"
    sinon
        affiche "Raté..."
    fin si
fin pour
affiche "Score final : " + convertir_texte(score) + " / 5"
HTML et JavaScript
<canvas id="toile" width="300" height="200"></canvas>
<p id="message">Clique sur la cible ! 5 essais.</p>

<script>
    const canvas = document.getElementById('toile');
    const ctx = canvas.getContext('2d');
    const message = document.getElementById('message');

    const etat = { essai: 1, score: 0, cx: 0, cy: 0 };

    function hasard(a, b) {
        return a + Math.floor(Math.random() * (b - a + 1));
    }

    function dessiner() {
        ctx.fillStyle = '#1E2430';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#FFD43B';
        ctx.beginPath();
        ctx.arc(etat.cx, etat.cy, 18, 0, Math.PI * 2);
        ctx.fill();
        ctx.fillStyle = '#FFFFFF';
        ctx.font = '14px sans-serif';
        ctx.textBaseline = 'top';
        ctx.fillText('Score : ' + etat.score, 8, 6);
    }

    function nouvelleCible() {
        etat.cx = hasard(20, 280);
        etat.cy = hasard(20, 180);
        dessiner();
    }

    canvas.addEventListener('click', e => {
        if (etat.essai > 5) return;
        const r = canvas.getBoundingClientRect();
        const x = (e.clientX - r.left) * canvas.width / r.width;
        const y = (e.clientY - r.top) * canvas.height / r.height;

        const touche = (x - etat.cx) ** 2 + (y - etat.cy) ** 2 <= 18 * 18;
        if (touche) etat.score += 1;
        etat.essai += 1;

        if (etat.essai > 5) {
            dessiner();
            message.textContent = 'Score final : ' + etat.score + ' / 5';
        } else {
            message.textContent = touche ? 'Touché !' : 'Raté...';
            nouvelleCible();
        }
    });

    nouvelleCible();
</script>

Ce qui précédait cliquer est devenu la fonction de dessin, ce qui le suivait est devenu la réaction au clic. Le test de clique() sur un cercle tient en une ligne.

Une balle qui rebondit

processus + suspendre

Une animation en tâche de fond, que l'on met en pause et que l'on relance.

CoddyRun
t est une toile
x, y, vx, vy est un nombre
action est un nombre

dimension(t, 300, 200)
x vaut 50
y vaut 50
vx vaut 4
vy vaut 3

processus Balle()
    tant que vrai
        x ajoute vx
        y ajoute vy
        si x < 10 ou x > 290 alors
            vx vaut -vx
        fin si
        si y < 10 ou y > 190 alors
            vy vaut -vy
        fin si
        effacer(t)
        remplir(t, #1E2430)
        cercle(t, x, y, 10, #FFD43B)
        affiche t
        pause 60
    fin tant que
fin processus

Balle()
tant que vrai
    appuyer ['p', 'r'] dans action
    si action = 1 alors
        suspendre
    sinon
        reprendre
    fin si
fin tant que
HTML et JavaScript
<canvas id="toile" width="300" height="200"></canvas>
<p><button id="pause">Pause</button></p>

<script>
    const canvas = document.getElementById('toile');
    const ctx = canvas.getContext('2d');
    const bouton = document.getElementById('pause');

    let x = 50, y = 50, vx = 4, vy = 3;
    let enPause = false;

    function image() {
        if (!enPause) {
            x += vx;
            y += vy;
            if (x < 10 || x > 290) vx = -vx;
            if (y < 10 || y > 190) vy = -vy;

            ctx.fillStyle = '#1E2430';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#FFD43B';
            ctx.beginPath();
            ctx.arc(x, y, 10, 0, Math.PI * 2);
            ctx.fill();
        }
        requestAnimationFrame(image);
    }

    bouton.addEventListener('click', () => {
        enPause = !enPause;
        bouton.textContent = enPause ? 'Reprendre' : 'Pause';
    });

    requestAnimationFrame(image);
</script>

Le processus est devenu une fonction image rappelée à chaque rafraîchissement d'écran. suspendre et reprendre se réduisent à un booléen, piloté ici par un bouton plutôt que par des touches : sur une page web, un bouton visible est plus clair qu'un raccourci qu'il faut deviner.

La méthode, pas à pas
À suivre dans l'ordre pour chaque programme
01
Uniformiser les noms
CoddyRun ignore la casse, JavaScript non : écrivez chaque variable de la même façon partout, et écartez les mots réservés de JavaScript.
02
Repérer les attentes
Surlignez chaque demande, choisir, appuyer, cliquer, interagir et pause. Ce sont elles qui découpent le programme en morceaux.
03
Dessiner la page
Pour chaque attente, prévoyez l'élément HTML correspondant : un formulaire, des boutons, un canvas. Pour chaque affiche, l'élément où le texte apparaîtra.
04
Extraire l'état
Toutes les variables qui doivent survivre entre deux événements, y compris les compteurs des boucles qui attendent, deviennent l'état, déclaré en tête.
05
Écrire l'affichage
Une fonction qui met la page en accord avec l'état : textes, dessin, éléments masqués ou visibles.
06
Écrire les réactions
Pour chaque attente, un écouteur d'événement qui contient ce qui suivait l'attente : il lit la saisie, modifie l'état, teste la fin, puis appelle l'affichage.
07
Traduire le reste
Calculs, conditions, fonctions et boucles sans attente se convertissent avec les tableaux de correspondance, de Types, variables à Fonctions. Attention aux index de texte et aux bornes de pour.
08
Tester avec les mêmes données
Exécutez les deux programmes avec les mêmes saisies et comparez les résultats. Gardez la console du navigateur ouverte (F12) : c'est là qu'apparaissent les erreurs.
Les huit pièges les plus fréquents
= au lieu de ===
Dans une condition, un seul = affecte la variable : la condition est presque toujours vraie.
^ pour une puissance
2 ^ 3 vaut 1 en JavaScript. Utilisez **.
Une saisie restée en texte
'3' + 1 vaut '31'. Convertissez avec Number().
Un formulaire qui recharge la page
Sans e.preventDefault() au début de la réaction à submit, la page se recharge et l'état est perdu.
Une boucle qui attend traduite en boucle
Un while qui attend un clic fige l'onglet : la boucle doit devenir un compteur dans l'état.
Un break manquant
Dans un switch, l'exécution continue sur le cas suivant.
Un tri numérique faux
[10, 9, 1].sort() donne [1, 10, 9]. Passez une fonction de comparaison.
Des coordonnées de clic non mises à l'échelle
Sur un écran où la toile est réduite, les clics tombent à côté. Utilisez getBoundingClientRect() comme dans Les entrées deviennent des événements.
Convertir un programme que l'on a écrit soi-même est l'un des meilleurs exercices pour passer à un langage professionnel : on connaît déjà la logique, il ne reste qu'à apprendre la syntaxe et la façon de penser du web. C'est exactement le pont que CoddyRun veut être. Une instruction qui résiste ? Posez la question sur le forum.