{"id":9915,"date":"2025-11-11T22:29:00","date_gmt":"2025-11-11T22:29:00","guid":{"rendered":"https:\/\/www.animcloud.fr\/?page_id=9915"},"modified":"2025-11-11T22:53:44","modified_gmt":"2025-11-11T22:53:44","slug":"mastermind","status":"publish","type":"page","link":"https:\/\/www.animcloud.fr\/en\/mastermind\/","title":{"rendered":"Mastermind"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"utf-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\" \/>\n  <title>Mastermind \u2013 Widget Autonome<\/title>\n  <style>\n    \/*\n      VERSION WIDGET ENCAPSUL\u00c9E\n      - Tout est pr\u00e9fix\u00e9 par #mastermind-root pour \u00e9viter les collisions CSS\/JS\n      - A int\u00e9grer dans n'importe quelle page sans casser le site\n    *\/\n\n    #mastermind-root { --mm-bg:#0a0b16; --mm-panel:#141731; --mm-panel2:#1b2044; --mm-ink:#f6f3e7; --mm-muted:#c9c3af; --mm-gold:#d4af37; --mm-gold2:#9f7e16; --mm-hole:#272c55; --mm-radius:16px; --mm-shadow:0 10px 26px rgba(0,0,0,.35); font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\"; color:var(--mm-ink);}\n    #mastermind-root * { box-sizing: border-box; }\n\n    \/* Conteneur principal *\/\n    #mastermind-root .mm-app { background: radial-gradient(900px 600px at 20% 10%, rgba(212,175,55,.08), transparent 60%), var(--mm-bg); padding:12px; border-radius:12px; border:1px solid rgba(212,175,55,.15); }\n\n    \/* Ent\u00eate *\/\n    #mastermind-root .mm-header { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 6px 14px; border-bottom:1px solid rgba(212,175,55,.25); }\n    #mastermind-root .mm-title { margin:0; font-weight:800; letter-spacing:.4px; font-size:clamp(18px,4vw,28px); color:#f7e8bf; text-shadow:0 1px 0 rgba(0,0,0,.4); }\n    #mastermind-root .mm-actions { display:flex; gap:8px; flex-wrap:wrap; }\n    #mastermind-root .mm-btn { cursor:pointer; border-radius:12px; padding:9px 14px; border:1px solid var(--mm-gold2); background:linear-gradient(180deg,#f7e9a1,#caa437); color:#2b2106; font-weight:800; box-shadow:var(--mm-shadow); }\n    #mastermind-root .mm-btn.secondary { background:linear-gradient(180deg,#37406e,#252c55); color:#e9ecff; border-color:#1c2348 }\n\n    \/* Layout jeu *\/\n    #mastermind-root .mm-game { display:grid; gap:12px; grid-template-columns: 1.2fr .8fr; }\n    @media (max-width:900px){ #mastermind-root .mm-game { grid-template-columns:1fr; } }\n\n    #mastermind-root .mm-panel { background: linear-gradient(180deg, rgba(255,255,255,.03), rgba(0,0,0,.18)), var(--mm-panel); border:1px solid rgba(212,175,55,.28); border-radius:var(--mm-radius); padding:12px; box-shadow:var(--mm-shadow); }\n\n    \/* Plateau *\/\n    #mastermind-root .mm-board { display:flex; flex-direction:column; gap:10px; max-height:65dvh; overflow:auto; padding-right:6px; }\n    #mastermind-root .mm-row { display:grid; gap:10px; align-items:center; padding:10px; border-radius:14px; background:linear-gradient(180deg, rgba(255,255,255,.02), rgba(0,0,0,.25)); border:1px solid rgba(212,175,55,.2); grid-template-columns:1fr minmax(160px, 1fr) auto; }\n    #mastermind-root .mm-row.mm-active { box-shadow:0 0 0 2px rgba(212,175,55,.35) inset }\n\n    #mastermind-root .mm-holes { display:grid; grid-auto-flow:column; gap:10px }\n    #mastermind-root .mm-hole { width:clamp(42px,8vw,58px); height:clamp(42px,8vw,58px); border-radius:50%; background:var(--mm-hole); border:2px dashed rgba(212,175,55,.35); display:grid; place-items:center; cursor:pointer }\n    #mastermind-root .mm-hole.mm-filled { border-style:solid; border-color:rgba(212,175,55,.55) }\n    #mastermind-root .mm-peg { width:72%; height:72%; border-radius:50%; box-shadow: inset 0 6px 12px rgba(0,0,0,.45), 0 3px 8px rgba(0,0,0,.45) }\n\n    #mastermind-root .mm-feedback { display:flex; align-items:center; gap:6px; min-height:28px; font-size:14px; color:var(--mm-muted) }\n    #mastermind-root .mm-dot { width:12px; height:12px; border-radius:50% }\n    #mastermind-root .mm-dot.good { background:#2ecc71 }\n    #mastermind-root .mm-dot.mis { background:#f1c40f }\n    #mastermind-root .mm-dot.none { background:#4c5480 }\n\n    #mastermind-root .mm-actionsRow { display:flex; gap:8px; justify-self:end }\n\n    \/* Palette *\/\n    #mastermind-root .mm-palette { display:grid; grid-template-columns:repeat(6,1fr); gap:10px }\n    @media (max-width:900px){ #mastermind-root .mm-palette{ grid-template-columns:repeat(3,1fr);} }\n    @media (max-width:640px){ #mastermind-root .mm-palette{ grid-template-columns:repeat(2,1fr);} }\n    #mastermind-root .mm-swatch { height:52px; border-radius:12px; border:1px solid rgba(212,175,55,.35); background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(0,0,0,.22)); position:relative; cursor:pointer; box-shadow:var(--mm-shadow) }\n    #mastermind-root .mm-swatch::after{ content:\"\"; position:absolute; inset:8px; border:1px solid rgba(255,255,255,.08); border-radius:10px }\n    #mastermind-root .mm-swatch > i{ position:absolute; inset:10px; border-radius:8px }\n    #mastermind-root .mm-swatch.mm-selected{ outline:3px solid var(--mm-gold); outline-offset:3px }\n\n    #mastermind-root .mm-legend{ display:flex; align-items:center; flex-wrap:wrap; gap:14px; color:var(--mm-muted); font-size:14px; margin-top:8px }\n\n    #mastermind-root .mm-status{ display:flex; justify-content:space-between; align-items:center; color:var(--mm-muted); margin-top:8px; font-size:14px }\n\n    \/* Plein \u00e9cran cibl\u00e9 -> SEULEMENT le conteneur du jeu *\/\n    #mastermind-root .mm-game:fullscreen, #mastermind-root .mm-game:-webkit-full-screen { background:linear-gradient(180deg, rgba(255,255,255,.02), rgba(0,0,0,.18)); padding:10px; }\n    #mastermind-root .mm-game:fullscreen .mm-board, #mastermind-root .mm-game:-webkit-full-screen .mm-board { max-height:calc(100dvh - 200px) }\n\n    \/* Modale *\/\n    #mastermind-root .mm-modalBack { position:fixed; inset:0; background:rgba(0,0,0,.6); display:none; align-items:center; justify-content:center; padding:16px }\n    #mastermind-root .mm-modal { background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(0,0,0,.24)), var(--mm-panel); border:1px solid rgba(212,175,55,.35); border-radius:18px; width:min(520px, 96vw); padding:16px; text-align:center; box-shadow:var(--mm-shadow) }\n    #mastermind-root .mm-modal h3{ margin:.2em 0; font-size:22px }\n    #mastermind-root .mm-secret{ display:flex; gap:10px; justify-content:center; margin:10px 0 }\n\n    \/* Mobile sp\u00e9cifiques *\/\n    @media (max-width:700px){\n      #mastermind-root .mm-row{ grid-template-columns:1fr; }\n      #mastermind-root .mm-actionsRow{ justify-self:stretch }\n      #mastermind-root .mm-actionsRow .mm-btn{ flex:1; min-height:44px }\n      #mastermind-root .mm-hole{ width:clamp(46px,14vw,64px); height:clamp(46px,14vw,64px) }\n    }\n  <\/style>\n<\/head>\n<body>\n  <!-- WIDGET SCOP\u00c9 -->\n  <div id=\"mastermind-root\">\n    <div class=\"mm-app\">\n      <div class=\"mm-header\">\n        <h2 class=\"mm-title\">MASTERmind \u2014 \u00c9dition Baroque<\/h2>\n        <div class=\"mm-actions\">\n          <button class=\"mm-btn\" id=\"mm-full\">\u2922 Plein \u00e9cran<\/button>\n          <button class=\"mm-btn secondary\" id=\"mm-restart\">\u21bb Recommencer<\/button>\n        <\/div>\n      <\/div>\n\n      <div class=\"mm-game\" id=\"mm-game\">\n        <!-- Plateau -->\n        <section class=\"mm-panel\">\n          <div class=\"mm-board\" id=\"mm-board\" aria-live=\"polite\"><\/div>\n          <div class=\"mm-status\">\n            <span>Manche <b id=\"mm-turn\">1<\/b>\/<span id=\"mm-max\">10<\/span><\/span>\n            <span>Couleur s\u00e9lectionn\u00e9e : <b id=\"mm-selected\" style=\"color:var(--mm-muted)\">aucune<\/b><\/span>\n          <\/div>\n        <\/section>\n\n        <!-- Palette -->\n        <aside class=\"mm-panel\">\n          <h3 style=\"margin:0 0 8px 0; color:#f7e8bf\">PALETTE ROYALE<\/h3>\n          <div class=\"mm-palette\" id=\"mm-palette\"><\/div>\n          <div class=\"mm-legend\">\n            <span class=\"mm-dot good\"><\/span> bien plac\u00e9e\n            <span class=\"mm-dot mis\"><\/span> bonne couleur, mauvaise place\n            <span class=\"mm-dot none\"><\/span> pas dans le code\n          <\/div>\n          <p style=\"color:var(--mm-muted);margin-top:8px\">Astuce\u00a0: choisissez une couleur puis cliquez les emplacements de la ligne active. Validez quand les 4 sont remplis. <em>(Plein \u00e9cran\u00a0: bouton ou touche F)<\/em><\/p>\n        <\/aside>\n      <\/div>\n    <\/div>\n\n    <!-- Modale -->\n    <div class=\"mm-modalBack\" id=\"mm-modal\">\n      <div class=\"mm-modal\">\n        <div style=\"font-size:30px\">\ud83c\udf96\ufe0f<\/div>\n        <h3 id=\"mm-modal-title\"><\/h3>\n        <p id=\"mm-modal-text\" style=\"color:var(--mm-muted)\"><\/p>\n        <div class=\"mm-secret\" id=\"mm-modal-secret\"><\/div>\n        <button class=\"mm-btn\" id=\"mm-modal-close\">Continuer<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <script>\n  (function(){\n    \/\/ --- S\u00e9lecteurs encapsul\u00e9s ---\n    const elRoot = document.getElementById('mastermind-root');\n    const elBoard = elRoot.querySelector('#mm-board');\n    const elPalette = elRoot.querySelector('#mm-palette');\n    const elTurn = elRoot.querySelector('#mm-turn');\n    const elMax = elRoot.querySelector('#mm-max');\n    const elSel = elRoot.querySelector('#mm-selected');\n    const elGame = elRoot.querySelector('#mm-game');\n    const btnFull = elRoot.querySelector('#mm-full');\n    const btnRestart = elRoot.querySelector('#mm-restart');\n    const modal = elRoot.querySelector('#mm-modal');\n    const modalTitle = elRoot.querySelector('#mm-modal-title');\n    const modalText = elRoot.querySelector('#mm-modal-text');\n    const modalSecret = elRoot.querySelector('#mm-modal-secret');\n    const modalClose = elRoot.querySelector('#mm-modal-close');\n\n    \/\/ --- Config ---\n    const COLORS = [\n      {name:'Rouge',  value:'#e74c3c'},\n      {name:'Bleu',   value:'#3498db'},\n      {name:'Vert',   value:'#2ecc71'},\n      {name:'Jaune',  value:'#f1c40f'},\n      {name:'Violet', value:'#9b59b6'},\n      {name:'Orange', value:'#e67e22'}\n    ];\n    const LEN = 4, MAX = 10; elMax.textContent = MAX;\n\n    \/\/ --- \u00c9tat ---\n    let secret = []; let turn = 1; let selColor = null; let rows = [];\n\n    function makeSecret(){\n      const arr = []; for(let i=0;i<LEN;i++){ arr.push(COLORS[Math.floor(Math.random()*COLORS.length)]); } return arr;\n    }\n\n    function buildBoard(){\n      elBoard.innerHTML=''; rows = [];\n      for(let r=0;r<MAX;r++){\n        const row = document.createElement('div'); row.className='mm-row'+(r===0?' mm-active':''); row.dataset.index=r+1;\n        const holes = document.createElement('div'); holes.className='mm-holes';\n        const slots=[]; for(let i=0;i<LEN;i++){\n          const h=document.createElement('button'); h.type='button'; h.className='mm-hole'; h.setAttribute('aria-label',`Emplacement ${i+1}`);\n          h.addEventListener('click',()=>{ if(!row.classList.contains('mm-active')) return; if(!selColor) return; setHole(h, selColor.value); h.dataset.color=selColor.value; h.classList.add('mm-filled'); checkFill(row); });\n          holes.appendChild(h); slots.push(h);\n        }\n        const fb=document.createElement('div'); fb.className='mm-feedback'; fb.innerHTML='<span class=\"mm-dot none\"><\/span><span class=\"mm-dot none\"><\/span><span class=\"mm-dot none\"><\/span><span class=\"mm-dot none\"><\/span> <span>En attente\u2026<\/span>';\n        const actions=document.createElement('div'); actions.className='mm-actionsRow';\n        const v=document.createElement('button'); v.className='mm-btn'; v.textContent='Valider'; v.disabled=true; v.addEventListener('click',()=>validate(row, slots, fb));\n        const c=document.createElement('button'); c.className='mm-btn secondary'; c.textContent='Effacer'; c.addEventListener('click',()=>{ slots.forEach(h=>{setHole(h,null); h.removeAttribute('data-color'); h.classList.remove('mm-filled');}); v.disabled=true; });\n        actions.appendChild(v); actions.appendChild(c);\n        row.appendChild(holes); row.appendChild(fb); row.appendChild(actions);\n        elBoard.appendChild(row); rows.push({row,slots,fb,v});\n      }\n    }\n\n    function setHole(hole, color){\n      let peg = hole.querySelector('.mm-peg');\n      if(!color){ if(peg) peg.remove(); return; }\n      if(!peg){ peg=document.createElement('i'); peg.className='mm-peg'; hole.appendChild(peg); }\n      peg.style.background=color;\n    }\n\n    function checkFill(row){ const {v} = rows[row.dataset.index-1]; const filled=[...row.querySelectorAll('.mm-hole')].every(h=>h.dataset.color); v.disabled=!filled; }\n\n    function buildPalette(){\n      elPalette.innerHTML='';\n      COLORS.forEach(c=>{ const sw=document.createElement('button'); sw.type='button'; sw.className='mm-swatch'; sw.title=c.name; const i=document.createElement('i'); i.style.background=c.value; sw.appendChild(i);\n        sw.addEventListener('click',()=>{\n          if(selColor && selColor.value===c.value){ selColor=null; updateSel(); elPalette.querySelectorAll('.mm-swatch').forEach(x=>x.classList.remove('mm-selected')); return; }\n          selColor=c; updateSel(); elPalette.querySelectorAll('.mm-swatch').forEach(x=>x.classList.remove('mm-selected')); sw.classList.add('mm-selected');\n        }); elPalette.appendChild(sw); });\n    }\n\n    function updateSel(){ elSel.textContent = selColor? selColor.name : 'aucune'; elSel.style.color = selColor? selColor.value : 'var(--mm-muted)'; }\n\n    function score(guess){ const s=secret.map(x=>x.value), g=guess.slice(); let wp=0; const su=[], gu=[]; for(let i=0;i<LEN;i++){ if(g[i]===s[i]) wp++; else {su.push(s[i]); gu.push(g[i]);} } let mis=0; const cnt=su.reduce((m,c)=>((m[c]=(m[c]||0)+1),m),{}); for(const x of gu){ if(cnt[x]>0){mis++; cnt[x]--;}} return {wp, mis}; }\n\n    function updateFB(el,{wp,mis}){ el.innerHTML=''; const mk=cls=>{const d=document.createElement('span'); d.className='mm-dot '+cls; return d}; for(let i=0;i<wp;i++) el.appendChild(mk('good')); for(let i=0;i<mis;i++) el.appendChild(mk('mis')); for(let i=wp+mis;i<LEN;i++) el.appendChild(mk('none')); const t=document.createElement('span'); t.style.marginLeft='6px'; t.textContent=`${wp} bien plac\u00e9e(s), ${mis} bonne(s) couleur(s)`; el.appendChild(t); }\n\n    function validate(row, slots, fb){ const guess=slots.map(h=>h.dataset.color); const {wp,mis}=score(guess); updateFB(fb,{wp,mis}); if(wp===LEN){ end(true); return;} if(turn===MAX){ end(false); return;} row.classList.remove('mm-active'); turn++; elTurn.textContent=turn; const next=rows[turn-1].row; next.classList.add('mm-active'); next.scrollIntoView({block:'center'}); }\n\n    function end(win){ modalTitle.textContent = win? 'Victoire !':'Dommage\u2026'; modalText.textContent = win? `Code trouv\u00e9 en ${turn} tour(s).` : 'Le code secret \u00e9tait :'; modalSecret.innerHTML=''; secret.forEach(c=>{ const wrap=document.createElement('div'); wrap.style.width='42px'; wrap.style.height='42px'; wrap.style.borderRadius='50%'; wrap.style.display='grid'; wrap.style.placeItems='center'; wrap.style.background='linear-gradient(180deg,#2f335d,#212650)'; wrap.style.border='1px solid rgba(212,175,55,.35)'; const p=document.createElement('i'); p.className='mm-peg'; p.style.width='32px'; p.style.height='32px'; p.style.background=c.value; wrap.appendChild(p); modalSecret.appendChild(wrap); }); modal.style.display='flex'; }\n\n    function restart(){ secret=makeSecret(); turn=1; elTurn.textContent=turn; selColor=null; updateSel(); buildBoard(); elPalette.querySelectorAll('.mm-swatch').forEach(x=>x.classList.remove('mm-selected')); }\n\n    \/\/ Plein \u00e9cran limit\u00e9 au conteneur du jeu\n    function toggleFS(){ const fsEl=document.fullscreenElement||document.webkitFullscreenElement; if(!fsEl){ (elGame.requestFullscreen||elGame.webkitRequestFullscreen).call(elGame); } else { (document.exitFullscreen||document.webkitExitFullscreen).call(document); } }\n\n    \/\/ \u00c9v\u00e9nements\n    btnFull.addEventListener('click', toggleFS);\n    btnRestart.addEventListener('click', restart);\n    document.addEventListener('keydown', (e)=>{ if(e.key.toLowerCase()==='f') toggleFS(); if(e.key.toLowerCase()==='r') restart(); });\n    modalClose.addEventListener('click', ()=>{ modal.style.display='none'; restart(); });\n    modal.addEventListener('click', (e)=>{ if(e.target===modal){ modal.style.display='none'; restart(); } });\n\n    \/\/ Init\n    buildPalette(); restart();\n  })();\n  <\/script>\n<\/body>\n<\/html>\n\n\n","protected":false},"excerpt":{"rendered":"<p>Mastermind \u2013 Widget Autonome MASTERmind \u2014 \u00c9dition Baroque \u2922 Plein \u00e9cran \u21bb Recommencer Manche 1\/10 Couleur s\u00e9lectionn\u00e9e : aucune PALETTE ROYALE bien plac\u00e9e bonne couleur, mauvaise place pas dans le code Astuce\u00a0: choisissez une couleur puis cliquez les emplacements de la ligne active. Validez quand les 4 sont remplis. (Plein \u00e9cran\u00a0: bouton ou touche F) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-9915","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/comments?post=9915"}],"version-history":[{"count":9,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9915\/revisions"}],"predecessor-version":[{"id":9924,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9915\/revisions\/9924"}],"wp:attachment":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/media?parent=9915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}