// template-pack-4-jeux-educatifs.jsx // PACK 4 · JEUX ÉDUCATIFS UNIVERSELS — Allo Education Books v1.2 // 12 templates ludiques harmonisés avec la charte verrouillée. // Toutes les pages passent par . Aucun header/footer recréé. // Pas d'emoji. Toutes icônes via ou iconKey. Pilotables par data. const { Fragment: J_F } = React; /* ════════════════════════════════════════════════════════════════════════ Helpers locaux — strictement décoratifs, ne touchent pas la charte. ════════════════════════════════════════════════════════════════════════ */ function GameMeta({ niveau, duree, joueurs, difficulte = 2, max = 3 }) { return (
{niveau} {duree} {joueurs && (<>{joueurs})} Difficulté
); } function Sep() { return ; } function Stars({ n = 2, max = 3 }) { return ( {Array.from({ length: max }).map((_, i) => ( ))} ); } function NumChip({ n, tone = "primary", size = "0.22in" }) { const bg = tone === "orange" ? "var(--ae-orange)" : tone === "green" ? "var(--ae-success)" : tone === "yellow" ? "var(--ae-yellow-dark)" : "var(--ae-primary)"; return ( {n} ); } function AnswerSlot({ width = "0.32in", height = "0.32in" }) { return ; } /* ════════════════════════════════════════════════════════════════════════ 1 · MOTS CROISÉS (template: "crossword-game") ════════════════════════════════════════════════════════════════════════ */ // Grid encoded as a string array, "." = case noire, " " = case ouverte. // Numbers placed on first letter of each across/down word. function CrosswordGrid({ rows, numbers = {}, cell = "0.3in" }) { const ROWS = rows.length, COLS = rows[0].length; return (
{rows.map((row, y) => Array.from(row).map((c, x) => { const isBlack = c === "."; const key = `${x}-${y}`; const num = numbers[key]; return (
{!isBlack && num != null && ( {num} )}
); }) )}
); } function CluesList({ title, items, tone = "primary" }) { const accent = tone === "orange" ? "var(--ae-orange)" : "var(--ae-primary)"; return (
{title}
    {items.map(([n, txt]) => (
  1. {n}. {txt}
  2. ))}
); } function J1Crossword({ density, qrVisible, scoreVisible, scale = 1 }) { // 11×8 grid — Moyen Âge. Black cells = "." const rows = [ "...ROI....", "..A...V...", ".CHEVALIER", "..B...S...", ".SEIGNEUR.", "..Y...A...", "FIEF..L...", "...CROISA.", // last col cut to fit ].map(r => r.padEnd(10, ".")); const numbers = { "3-0": 1, // ROI across "1-1": 2, // ABBAYE down (col 1) "6-1": 3, // VASSAL down (col 6) "1-2": 4, // CHEVALIER across "1-4": 5, // SEIGNEUR across "0-6": 6, // FIEF across "3-7": 7, // CROISA(DE) across }; const acrossClues = [ [1, "Souverain qui règne sur le royaume."], [4, "Combattant à cheval au service du seigneur."], [5, "Personnage qui possède une terre et y exerce le pouvoir."], [6, "Terre confiée par le seigneur à son vassal."], [7, "Expédition militaire vers Jérusalem (XIᵉ–XIIIᵉ s.)."], ]; const downClues = [ [2, "Lieu où vivent les moines, dirigé par un abbé."], [3, "Homme lié à un seigneur par un serment de fidélité."], ]; return (
Commence toujours par le mot dont tu es le plus sûr. Ses lettres serviront d'indices pour les mots qui se croisent.
); } /* ════════════════════════════════════════════════════════════════════════ 2 · MOTS MÊLÉS (template: "word-search-game") ════════════════════════════════════════════════════════════════════════ */ function WordSearchGrid({ grid, cell = "0.26in" }) { return (
{grid.map((row, y) => row.map((ch, x) => (
{ch}
)) )}
); } function J2WordSearch({ density, qrVisible, scoreVisible, scale = 1 }) { // 12×10 grid with planètes hidden (some real placements) const grid = [ "MERCUREZBNV".split(""), "AKLPLANETEN".split(""), "RPSATURNEPL".split(""), "SVENUSXMQTU".split(""), "TERREORBITN".split(""), "LZJUPITERAE".split(""), "URANUSEHJST".split(""), "FETOILEKMUO".split(""), "ASOLEILBRMN".split(""), "TGALAXIEZWE".split(""), ]; const words = [ "SOLEIL", "MERCURE", "VENUS", "TERRE", "MARS", "JUPITER", "SATURNE", "URANUS", "NEPTUNE", "PLANETE", "ETOILE", "ORBITE", "GALAXIE", ]; return (
{words.map(w => ( {w} ))}
Entoure chaque mot trouvé. Coche-le dans la liste ci-contre. Si tu bloques, le QR du footer dévoile la solution.
Cherche d'abord les mots les plus longs (NEPTUNE, GALAXIE) : ils éliminent rapidement plusieurs lignes de la grille.
); } /* ════════════════════════════════════════════════════════════════════════ 3 · CODE SECRET (template: "secret-code-game") ════════════════════════════════════════════════════════════════════════ */ function CodeKeyTable({ pairs, cols = 13 }) { const rows = []; for (let i = 0; i < pairs.length; i += cols) rows.push(pairs.slice(i, i + cols)); return (
{rows.map((r, ri) => (
{r.map(([letter]) => (
{letter}
))}
{r.map(([, num]) => (
0 ? "1px solid var(--ae-border)" : "none", background: ri % 2 ? "var(--ae-bg-cool)" : "white", }}>{num}
))}
))}
); } function J3SecretCode({ density, qrVisible, scoreVisible, scale = 1 }) { // A=1, B=2 ... full alphabet. We display only the active subset. const used = "BRAVOLEMOTSECRETESTGAGNE".split(""); const uniq = [...new Set(used)].sort(); const pairs = uniq.map(l => [l, l.charCodeAt(0) - 64]); // Operations: each result corresponds to a letter in "BRAVOLEMOT..." // Calculations to decipher 5 letters: B(2), R(18), A(1), V(22), O(15) const calcs = [ ["1.", "(8 × 4) − 30", "B"], ["2.", "9 × 2", "R"], ["3.", "(5 + 3) − 7", "A"], ["4.", "(11 × 2)", "V"], ["5.", "(60 ÷ 4)", "O"], ]; return (
Chaque lettre vaut son rang dans l'alphabet : A = 1, B = 2, C = 3 …
Calcul
Résultat
Lettre
{calcs.map(([n, op]) => (
{n}
{op} =
))}
Mot mystère
{Array.from("BRAVO").map((_, i) => ( ))}
Les nombres de la table vont de 1 à 26. Si ton résultat est au-dessus de 26 : tu t'es trompé quelque part — refais le calcul.
); } /* ════════════════════════════════════════════════════════════════════════ 4 · JEU DE L'INTRUS (template: "odd-one-out-game") ════════════════════════════════════════════════════════════════════════ */ function IntrusItem({ children }) { return ( {children} ); } function J4OddOneOut({ density, qrVisible, scoreVisible, scale = 1 }) { const series = [ { theme: "Capitales", items: ["Paris", "Madrid", "Berlin", "Lyon", "Rome"] }, { theme: "Mammifères", items: ["Chien", "Chat", "Dauphin", "Requin", "Baleine"] }, { theme: "Multiples de 3", items: ["9", "15", "22", "27", "33"] }, { theme: "Verbes du 1ᵉʳ groupe", items: ["chanter", "parler", "finir", "manger", "danser"] }, { theme: "Mots invariables", items: ["mais", "où", "donc", "joli", "car"] }, { theme: "Sources d'énergie renouvelables", items: ["soleil", "vent", "eau", "pétrole", "biomasse"] }, ]; return (
{series.map((s, i) => (
{s.theme}
{s.items.map(it => {it})}
J'explique pourquoi
))}
Avant d'entourer, demande-toi : quel point commun ont 4 mots de la liste ? L'intrus est celui qui ne le partage pas. ); } /* ════════════════════════════════════════════════════════════════════════ 5 · VRAI / FAUX EXPRESS (template: "true-false-game") ════════════════════════════════════════════════════════════════════════ */ function J5TrueFalse({ density, qrVisible, scoreVisible, scale = 1 }) { const items = [ "La Révolution française commence en 1789.", "Louis XVI était empereur des Français.", "La prise de la Bastille a eu lieu le 14 juillet 1789.", "La Déclaration des droits de l'homme date de 1791.", "Marie-Antoinette était reine d'Angleterre.", "La Première République est proclamée en 1792.", "Robespierre était un général de l'Empire.", "La devise « Liberté, Égalité, Fraternité » date de la Révolution.", ]; return (
{items.map((txt, i) => (
0 ? "1px dashed var(--ae-border)" : "none", }}> {txt}
V
F
))}
Confondre « roi » et « empereur ». Sous l'Ancien Régime, le dirigeant est un roi. L'empereur, c'est plus tard, avec Napoléon.
); } /* ════════════════════════════════════════════════════════════════════════ 6 · RELIER / ASSOCIER (template: "matching-game") ════════════════════════════════════════════════════════════════════════ */ function J6Matching({ density, qrVisible, scoreVisible, scale = 1 }) { // Anglais 6e — vocabulaire animaux + maison const left = [ ["1", "Bedroom"], ["2", "Kitchen"], ["3", "Living room"], ["4", "Bathroom"], ["5", "Garden"], ["6", "Garage"], ]; const right = [ ["A", "Le jardin"], ["B", "Le salon"], ["C", "La salle de bain"], ["D", "La chambre"], ["E", "Le garage"], ["F", "La cuisine"], ]; return (
{/* English column */}
English
{left.map(([n, w]) => (
{w}
))}
{/* Connector lane */}
{[60, 120, 180, 240, 300, 360].map((y, i) => ( ))}
relier
{/* French column */}
Français
{right.map(([ch, t]) => (
{ch} {t}
))}
Reporte tes paires ici
Lis chaque paire à voix haute en anglais puis en français. Le son de la traduction t'aide à mémoriser bien plus vite que la lecture silencieuse.
); } /* ════════════════════════════════════════════════════════════════════════ 7 · REMETTRE DANS L'ORDRE (template: "ordering-game") ════════════════════════════════════════════════════════════════════════ */ function OrderCard({ letter, text }) { return (
{letter} {text}
); } function J7Ordering({ density, qrVisible, scoreVisible, scale = 1 }) { const cards = [ ["A", "L'eau s'évapore au-dessus des océans, des lacs et des rivières."], ["B", "Les nuages se déplacent avec le vent et se refroidissent."], ["C", "Les gouttes d'eau retombent sous forme de pluie ou de neige."], ["D", "L'eau ruisselle, s'infiltre dans les sols et rejoint les nappes."], ["E", "Les fleuves transportent l'eau jusqu'aux mers et aux océans."], ["F", "La vapeur d'eau monte et se condense en nuages."], ]; return (
Pour la cuisson d'un œuf : casserbattrecuire servir. La logique : tu commences par l'action qui rend possible la suivante.
{cards.map(([l, t]) => (
))}
Frise · ordre des étapes
{[1, 2, 3, 4, 5, 6].map((n, i) => (
{n} ?
{i < 5 && }
))}
Cherche d'abord l'étape de départ : celle qui ne dépend d'aucune autre. C'est ton point d'ancrage pour tout reconstituer.
); } /* ════════════════════════════════════════════════════════════════════════ 8 · LABYRINTHE ÉDUCATIF (template: "maze-game") ════════════════════════════════════════════════════════════════════════ */ function MazeSVG() { // Schematic 11×7 maze. Walls drawn as line segments. Path from (0,3)→(10,3) return ( {/* outer */} {/* internal walls */} {/* question stops */} {[ { x: 60, y: 60, n: 1 }, { x: 140, y: 120, n: 2 }, { x: 220, y: 80, n: 3 }, { x: 320, y: 140, n: 4 }, { x: 380, y: 220, n: 5 }, ].map(({ x, y, n }) => ( {n} ))} {/* start / end */} DÉPART FIN ); } function J8Maze({ density, qrVisible, scoreVisible, scale = 1 }) { const questions = [ ["Combien de continents sur Terre ?", "5", "6", "7"], ["7 × 8 = ?", "54", "56", "64"], ["Capitale du Portugal ?", "Madrid", "Lisbonne", "Porto"], ["Synonyme de « rapide » ?", "Lent", "Vif", "Long"], ["Périmètre d'un carré de 4 cm ?", "8 cm", "12 cm", "16 cm"], ]; return (
{questions.map(([q, ...opts], i) => (
{q}
{opts.map((o, j) => ( {o} ))}
))}
); } /* ════════════════════════════════════════════════════════════════════════ 9 · COLORIAGE MAGIQUE (template: "magic-coloring-game") ════════════════════════════════════════════════════════════════════════ */ const COLORING_PALETTE = [ { n: 1, name: "Bleu", hex: "var(--ae-primary)", soft: "var(--ae-primary-soft)" }, { n: 2, name: "Orange", hex: "var(--ae-orange)", soft: "var(--ae-orange-soft)" }, { n: 3, name: "Jaune", hex: "var(--ae-yellow-dark)", soft: "var(--ae-yellow-soft)" }, { n: 4, name: "Vert", hex: "var(--ae-success)", soft: "var(--ae-success-soft)" }, { n: 5, name: "Rouge", hex: "var(--ae-error)", soft: "var(--ae-error-soft)" }, ]; function ButterflyZones({ outlined = true }) { // Simple butterfly with 12 numbered zones // Layout: cols 1-12 mapped to wing zones (we keep schematic shapes) const zones = [ // Body { d: "M 215 60 Q 225 90 215 200 Q 205 90 215 60 Z", n: 1 }, // Left top wing { d: "M 210 90 Q 130 60 90 110 Q 130 140 210 130 Z", n: 2 }, { d: "M 205 110 Q 150 100 130 130 Q 165 135 205 130 Z", n: 3 }, // Left bottom wing { d: "M 210 140 Q 150 150 110 200 Q 165 200 210 180 Z", n: 4 }, { d: "M 205 165 Q 165 175 150 195 Q 180 195 205 185 Z", n: 5 }, // Right top wing { d: "M 220 90 Q 300 60 340 110 Q 300 140 220 130 Z", n: 1 }, { d: "M 225 110 Q 280 100 300 130 Q 265 135 225 130 Z", n: 2 }, // Right bottom wing { d: "M 220 140 Q 280 150 320 200 Q 265 200 220 180 Z", n: 3 }, { d: "M 225 165 Q 265 175 280 195 Q 250 195 225 185 Z", n: 4 }, // Antennae { d: "M 215 60 Q 200 40 195 30", n: 5, stroke: true }, { d: "M 215 60 Q 230 40 235 30", n: 5, stroke: true }, ]; return ( {zones.filter(z => !z.stroke).map((z, i) => ( ))} {zones.filter(z => z.stroke).map((z, i) => ( ))} {/* Numbers */} {[ { x: 215, y: 130, n: 1 }, { x: 150, y: 100, n: 2 }, { x: 170, y: 125, n: 3 }, { x: 160, y: 175, n: 4 }, { x: 180, y: 190, n: 5 }, { x: 280, y: 100, n: 1 }, { x: 270, y: 125, n: 2 }, { x: 270, y: 175, n: 3 }, { x: 255, y: 190, n: 4 }, ].map((p, i) => ( {p.n} ))} ); } function J9MagicColoring({ density, qrVisible, scoreVisible, scale = 1 }) { const calcs = [ ["6 + 2", "= ___", "→ Bleu (1)"], ["12 − 6", "= ___", "→ Orange (2)"], ["3 × 3", "= ___", "→ Jaune (3)"], ["20 ÷ 5", "= ___", "→ Vert (4)"], ["7 + 8", "= ___", "→ Rouge (5)"], ]; return (
  1. 1Calcule le résultat de chaque opération.
  2. 2Reporte le numéro indiqué (1 à 5) dans le code couleur.
  3. 3Colorie chaque zone du dessin avec la couleur correspondante.
{COLORING_PALETTE.map(c => (
{c.n} {c.name}
))}
{calcs.map(([op, eq, hint], i) => (
{op} {eq} {hint}
))}
); } /* ════════════════════════════════════════════════════════════════════════ 10 · PIXEL ART PAR COORDONNÉES (template: "coordinate-pixel-art") ════════════════════════════════════════════════════════════════════════ */ function CoordinateGrid({ cols = 12, rows = 10, marked = [] }) { const CELL = 18; const ORIGIN_X = 22, ORIGIN_Y = 22; const W = ORIGIN_X + cols * CELL + 4; const H = ORIGIN_Y + rows * CELL + 4; return ( {/* Grid lines */} {Array.from({ length: cols + 1 }).map((_, i) => ( ))} {Array.from({ length: rows + 1 }).map((_, i) => ( ))} {/* Axes */} {/* X labels (1..cols) */} {Array.from({ length: cols }).map((_, i) => ( {i + 1} ))} {/* Y labels (1..rows from bottom) */} {Array.from({ length: rows }).map((_, i) => ( {i + 1} ))} {/* Marked cells (preview hint, light fill) */} {marked.map(([x, y, color], i) => ( ))} ); } function J10PixelArt({ density, qrVisible, scoreVisible, scale = 1 }) { // Preview hints — student fills in the rest. Star shape coords (1-indexed) const hints = [ [6, 9, "var(--ae-yellow-soft)"], [7, 9, "var(--ae-yellow-soft)"], [6, 8, "var(--ae-yellow-soft)"], [7, 8, "var(--ae-yellow-soft)"], ]; const coords = [ "(6 ; 10) · (7 ; 10)", "(5 ; 9) · (6 ; 9) · (7 ; 9) · (8 ; 9)", "(4 ; 8) · (5 ; 8) · (6 ; 8) · (7 ; 8) · (8 ; 8) · (9 ; 8)", "(3 ; 7) · (4 ; 7) · (10 ; 7) · (11 ; 7)", "(5 ; 6) · (6 ; 6) · (7 ; 6) · (8 ; 6)", "(6 ; 5) · (7 ; 5)", "(5 ; 4) · (8 ; 4)", "(4 ; 3) · (9 ; 3)", ]; return (
On lit les coordonnées (x ; y) dans cet ordre : x = abscisse, axe horizontal (de gauche à droite). y = ordonnée, axe vertical (de bas en haut). On part toujours de l'origine, en bas à gauche.
    {coords.map((c, i) =>
  1. {c}
  2. )}
Couleur conseillée : jaune.
Une fois l'étoile terminée, dessine ta propre image (5 cases minimum) et écris la liste de coordonnées en dessous. Ton voisin la testera. Marque toujours l'abscisse en premier. Une coordonnée inversée fait basculer le pixel de l'autre côté du plan.
); } /* ════════════════════════════════════════════════════════════════════════ 11 · MEMORY · PAIRES À RETROUVER (template: "memory-pairs-game") ════════════════════════════════════════════════════════════════════════ */ function MemoryCard({ children, accent = "primary", small = false }) { const color = accent === "orange" ? "var(--ae-orange)" : accent === "green" ? "var(--ae-success)" : "var(--ae-primary)"; return (
{children}
); } function J11Memory({ density, qrVisible, scoreVisible, scale = 1 }) { // 6 paires anglais ↔ français — verbes irréguliers const pairs = [ { en: "to go", fr: "aller" }, { en: "to be", fr: "être" }, { en: "to have", fr: "avoir" }, { en: "to do", fr: "faire" }, { en: "to see", fr: "voir" }, { en: "to take", fr: "prendre" }, ]; // Shuffle deterministic for visual interest const order = [0, 5, 2, 1, 3, 4, 5, 0, 4, 3, 1, 2]; const cards = order.map((i, idx) => idx % 2 === 0 ? { txt: pairs[i].en, t: "en" } : { txt: pairs[i].fr, t: "fr" }); return (
  1. 1Découpe les 12 cartes le long des pointillés.
  2. 2Pose-les face cachée sur la table, en désordre.
  3. 3Retourne 2 cartes par tour. Si elles forment une paire (anglais / français), garde-les.
  4. 4Le joueur avec le plus de paires gagne. Solo : essaye en moins de 12 tours.
{cards.map((c, i) => ( {c.txt} ))}
Tours utilisés : Paires trouvées : Temps :
Joueur 1paires Joueur 2paires Vainqueur
Avant de commencer le memory, lis la liste des 6 paires à voix haute une fois. Cela double tes chances de retrouver les paires rapidement. ); } /* ════════════════════════════════════════════════════════════════════════ 12 · ÉNIGMES / DEVINETTES (template: "riddle-game") ════════════════════════════════════════════════════════════════════════ */ function J12Riddles({ density, qrVisible, scoreVisible, scale = 1 }) { const riddles = [ { n: 1, diff: 1, q: "Plus on m'enlève de matière, plus je grossis. Qui suis-je ?", hint: "Pense à un objet qu'on creuse dans la terre.", }, { n: 2, diff: 2, q: "Je commence la nuit et je termine le matin. On me retrouve aussi au début et à la fin de l'année. Quelle lettre suis-je ?", hint: "Regarde la première et la dernière lettre des mots cités.", }, { n: 3, diff: 2, q: "J'ai des villes, mais pas de maisons ; des forêts, mais pas d'arbres ; des rivières, mais pas d'eau. Qui suis-je ?", hint: "On me déplie sur une table.", }, { n: 4, diff: 3, q: "Si tu me dis, je n'existe plus. Qui suis-je ?", hint: "Garde-le pour toi.", }, { n: 5, diff: 3, q: "Mon père a 5 fils. Quatre s'appellent Lou, La, Li, Le. Comment s'appelle le cinquième ?", hint: "Lis bien la première phrase…", }, ]; return (
{riddles.map(r => (
{r.n} Énigme {r.n}
« {r.q} »
Ma réponse
Indice : {r.hint}
))} {/* Last cell — Ketty bubble fills the grid */}
Une bonne énigme se résout rarement avec la première idée qui vient. Lis 2 fois, repère le mot piège, et essaye plusieurs interprétations avant de répondre. Le QR du footer dévoile les réponses détaillées.
); } /* ──────────────────────────────────────────────────────────────────────── Export ──────────────────────────────────────────────────────────────────────── */ Object.assign(window, { J1Crossword, J2WordSearch, J3SecretCode, J4OddOneOut, J5TrueFalse, J6Matching, J7Ordering, J8Maze, J9MagicColoring, J10PixelArt, J11Memory, J12Riddles, });