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.
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.
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();
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.
| CoddyRun | JavaScript | Remarque |
|---|
nombre | let n = 0; | Un seul type numérique dans les deux langages. |
texte | let t = ''; | |
booléen | let b = false; | vrai / faux deviennent true / false. |
tableau | let t = []; | Index à partir de 0 dans les deux langages. |
enregistrement | let p = {}; | Un objet. |
dictionnaire | let d = new Map(); | Voir Tableaux, dictionnaires. |
date / heure | let d = new Date(); | Voir Données et dates. |
toile | const ctx = canvas.getContext('2d'); | Un élément <canvas> de la page. Voir La toile. |
est une constante vaut | const | |
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…
| CoddyRun | JavaScript | Remarque |
|---|
= | === | Comparaison stricte. Un seul = affecte la variable au lieu de la comparer. |
<> | !== | |
et ou non | && || ! | |
a mod b | a % b | En JavaScript, le signe du résultat suit a : vérifiez avec des nombres négatifs. |
a ^ b | a ** b | Le ^ de JavaScript est un « ou exclusif » binaire : 2 ^ 3 vaut 1. |
"Bon" + "jour" | 'Bon' + 'jour' | Identique. |
#65 | String.fromCharCode(65) | Caractère par son code. |
n ajoute 1 | n += 1 | Sur un nombre ou un texte. |
n soustrait 1 | n -= 1 | |
CoddyRunmot est un texte
mot vaut "Bonjour"
affiche copier(mot, 2, 3) // "onj"
affiche position("j", mot) // 4, et 0 si absent
JavaScriptlet 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.
CoddyRunscores 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
JavaScriptlet 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;
CoddyRuncontacts 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)
JavaScriptlet 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.
CoddyRunclasse Personne :
nom, prenom est un texte
age est un nombre
actif est un booléen
fin classe
JavaScriptclass Personne {
constructor() {
this.nom = '';
this.prenom = '';
this.age = 0;
this.actif = false;
}
}
const p = new Personne();
CoddyRunsi 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
JavaScriptif (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.
CoddyRuntant 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
JavaScriptwhile (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.
CoddyRunfonction carre(x)
retourne x * x
fin fonction
procédure saluer(nom)
affiche "Bonjour " + nom
fin procédure
resultat vaut carre(5)
appelle saluer("Alice")
JavaScriptfunction carre(x) {
return x * x;
}
function saluer(nom) {
console.log('Bonjour ' + nom);
}
resultat = carre(5);
saluer('Alice'); // « appelle » disparaît
CoddyRunessayer
n vaut convertir_nombre(saisie)
attraper
affiche "Ce n'est pas un nombre"
fin essayer
JavaScriptn = 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.
CoddyRunsi rayon <= 0 alors
affiche "Le rayon doit être positif."
terminer
fin si
JavaScriptif (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.
CoddyRunaffiche "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.
CoddyRunnom 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.
CoddyRunage 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.
CoddyRunchoix 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.
CoddyRunaction est un nombre
appuyer ['z', 's', 'd', 'q'] dans action
JavaScriptconst 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'.
CoddyRunx, y est un nombre
cliquer maToile dans x, y
JavaScriptcanvas.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.
CoddyRunsomme 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.
CoddyRunaffiche "Trois..."
pause 1000
affiche "Deux..."
pause 1000
affiche "Partez !"
JavaScriptresultat.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.
CoddyRunprocessus 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()
JavaScriptlet 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.
CoddyRunt 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.
| CoddyRun | JavaScript | Remarque |
|---|
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, stroke | lineWidth pour l'épaisseur. |
polygone / triangle | moveTo, puis lineTo par sommet, closePath, fill | |
contour(t, c, e) | ctx.strokeStyle = c; ctx.lineWidth = e | Puis 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. |
CoddyRunsi clique(x, y, cx, cy, 18) alors
score ajoute 1
fin si
JavaScriptfunction 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.
| CoddyRun | JavaScript | Remarque |
|---|
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 Blob | Le 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);
}
| CoddyRun | JavaScript | Remarque |
|---|
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 / inferieur | Math.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.PI | Radians dans les deux langages. |
longueur(x) | x.length | Pour 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 | |
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.
CoddyRunxPI 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.
CoddyRunsomme 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.
CoddyRunsecret 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.
CoddyRunscore 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.
CoddyRunpour 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.
CoddyRunt 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.
CoddyRunt 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.
CoddyRunt 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.
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.
= 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
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.