{"id":2,"date":"2025-10-09T19:41:37","date_gmt":"2025-10-09T19:41:37","guid":{"rendered":"http:\/\/lab2-2.fr\/?page_id=2"},"modified":"2025-11-20T11:07:57","modified_gmt":"2025-11-20T11:07:57","slug":"sample-page","status":"publish","type":"page","link":"https:\/\/lab2-2.fr\/","title":{"rendered":"WELCOME"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2\" class=\"elementor elementor-2\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a7ca7ef e-flex e-con-boxed e-con e-parent\" data-id=\"a7ca7ef\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<header class=\"elementor-element elementor-element-5782efd e-con-full e-flex e-con e-child\" data-id=\"5782efd\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2cc0548 elementor-widget elementor-widget-html\" data-id=\"2cc0548\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!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>LAB 2.2 \u2014 Tic-Tac-Toe IA \u2022 Site en construction<\/title>\n\n<style>\n  :root{\n    --blue:#1A47FF;\n    --white:#fff;\n    --ink:#6f7b98;\n    --grid:#e8edff;\n  }\n  *{box-sizing:border-box}\n\n  \/* ===== MOBILE FIRST ===== *\/\n  html,body{\n    margin:0; height:100%;\n    background:var(--white); color:var(--ink);\n    font-family:\"Salo\",system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;\n    overflow-x:hidden;\n  }\n\n  \/* Masquer menus\/titres WP\/Elementor *\/\n  .site-header,#site-header,#masthead,.wp-block-navigation,nav.site,nav.primary,\n  .elementor-location-header,.e-con-inner>nav,.navbar,.main-header,.menu,.header,\n  .et-l--header,.oxy-header,header.wp-block-template-part,\n  .elementor-widget-theme-post-title,.elementor-heading-title,.entry-title,.page-title,.elementor-page-title{\n    display:none!important;\n  }\n\n  .wrap{\n    min-height:100svh;\n    display:flex; align-items:center; justify-content:center;\n    padding:24px 12px 32px;\n  }\n\n  .content{\n    width:100%; max-width:1100px;\n    display:flex; flex-direction:column; align-items:center; gap:22px;\n  }\n\n  \/* \u201cSITE EN CONSTRUCTION\u201d \u2014 Argent Pixel forc\u00e9 *\/\n  #app .under-construction,#app .under-construction *{\n    font-family:\"Argent Pixel\",\"Salo\",system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif!important;\n  }\n  .under-construction{\n    color:var(--blue); border:2px solid var(--blue); font-weight:700;\n    padding:6px 10px; letter-spacing:.02em; margin-bottom:8px; text-align:center;\n    display:inline-block;\n  }\n\n  \/* ===== JEU ===== *\/\n  .game{ width:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; }\n\n  .board{\n    width:min(92vw,360px); \/* 100% safe on mobile *\/\n    display:grid; grid-template-columns:repeat(3,1fr); gap:0;\n    background:#fff;\n    border:4px solid var(--blue);           \/* \u2705 cadre externe 4px *\/\n    box-shadow:0 0 0 6px rgba(26,71,255,.12);\/* halo l\u00e9ger *\/\n    margin:0 auto !important;               \/* \u2705 centre le plateau *\/\n  }\n\n  \/* On \u00e9vite les doubles bordures : on dessine UNIQUEMENT vers le haut et la gauche\n     pour l\u2019int\u00e9rieur de la grille \u2192 \u00e9paisseur identique partout et lignes align\u00e9es. *\/\n  .cell{\n    aspect-ratio:1\/1;\n    display:flex; align-items:center; justify-content:center;\n    border:0; position:relative;\n    color:var(--blue);\n    font-family:\"Argent Pixel\",\"Salo\",system-ui; font-weight:800; line-height:1;\n    font-size:clamp(42px,14vw,86px);\n    user-select:none; cursor:pointer;\n  }\n  \/* traits verticaux internes (colonnes 2 et 3) *\/\n  .cell:nth-child(3n+2),\n  .cell:nth-child(3n+3){ border-left:4px solid var(--blue); }\n  \/* traits horizontaux internes (lignes 2 et 3) *\/\n  .cell:nth-child(n+4){ border-top:4px solid var(--blue); }\n\n  .cell.empty:hover{ background:var(--grid); }\n\n  \/* ===== SCORE + CTAs ===== *\/\n  .side{\n    width:clamp(280px,92vw,360px);\n    display:grid; gap:18px; justify-items:center;\n  }\n  .scorebox{\n    width:100%; background:#fff; padding:14px; display:grid; gap:12px;\n    border:4px solid var(--blue);\n    box-shadow:0 0 0 2px #fff inset, 0 0 0 6px rgba(26,71,255,.12);\n    overflow:hidden;\n  }\n  .score-title{ font-family:\"Argent Pixel\",\"Salo\",system-ui; color:var(--blue); font-weight:700; letter-spacing:.02em; text-align:left; }\n  .scorebar{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }\n  .stat{ border:4px solid var(--blue); padding:10px 8px; background:#fff; position:relative; }\n  .stat::before{ content:\"\"; position:absolute; left:8px; right:8px; top:-6px; height:4px; background:var(--blue); }\n  .label{ font-size:.8rem; opacity:.85; }\n  .value{ margin-top:4px; color:var(--blue); font-family:\"Argent Pixel\",\"Salo\",system-ui; font-variant-numeric:tabular-nums; font-size:1.25rem; }\n  .ticker{ width:100%; height:10px; border:4px solid var(--blue); display:grid; grid-template-columns:repeat(20,1fr); gap:2px; padding:4px; background:#fff; }\n  .tick{ background:var(--grid); } .tick.fill{ background:var(--blue); }\n\n  \/* CTA \u2014 m\u00eame largeur pour les 2 (100%) *\/\n  .btn{\n    width:100%;\n    position:relative; display:block; text-align:center;\n    background:var(--blue); color:#fff; border:4px solid var(--blue);\n    padding:12px 14px; font-weight:700; font-size:1rem; text-decoration:none;\n    font-family:\"Argent Pixel\",\"Salo\",system-ui;\n  }\n  .btn .txt{ position:relative; line-height:1.05; display:inline-block; }\n  .btn .txt::after{\n    content:\"\"; position:absolute; left:50%; bottom:-1px; width:52%; height:2px; background:#fff;\n    transform:translateX(-50%) scaleX(0); transform-origin:left; transition:transform .2s ease;\n  }\n  .btn:hover .txt::after{ transform:translateX(-50%) scaleX(1); }\n  .btn.secondary{ background:#fff; color:var(--blue); border-color:var(--blue); }\n  .btn.secondary .txt::after{ background:var(--blue); }\n  .note{ font-size:.9rem; opacity:.85; text-align:center; }\n\n  \/* ===== DESKTOP : 2 colonnes, jeu parfaitement CENTR\u00c9 ===== *\/\n  @media (min-width:980px){\n    .content{\n      display:grid; grid-template-columns:auto 360px; column-gap:32px;\n      align-items:start; justify-content:center;\n    }\n    .game{ justify-self:center !important; }\n    .board{ width:clamp(360px,38vw,440px); }\n    .side{ width:360px; justify-self:center; }\n  }\n\n  \/* Overlay (pause\/fin) *\/\n  .overlay{ position:fixed; inset:0; display:none; place-items:center; background:rgba(255,255,255,.94); z-index:10; }\n  .card{ background:#fff; border:4px solid var(--blue); padding:16px 14px; text-align:center; max-width:min(92vw,520px); }\n  .card h1{ margin:0 0 8px; font-size:1.1rem; color:var(--blue); font-family:\"Argent Pixel\",\"Salo\",system-ui; }\n  .card p{ margin:6px 0; font-size:.95rem; }\n<\/style>\n<\/head>\n<body>\n  <div class=\"wrap\" id=\"app\">\n    <section class=\"content\">\n      <!-- ===== Jeu ===== -->\n      <div class=\"game\" aria-label=\"Jeu Morpion (Tic-Tac-Toe)\">\n        <div class=\"under-construction\">SITE EN CONSTRUCTION<\/div>\n\n        <div class=\"board\" id=\"board\" role=\"grid\" aria-label=\"Grille 3 par 3\">\n          <div class=\"cell empty\" id=\"c-0-0\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-0-1\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-0-2\" role=\"gridcell\"><\/div>\n\n          <div class=\"cell empty\" id=\"c-1-0\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-1-1\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-1-2\" role=\"gridcell\"><\/div>\n\n          <div class=\"cell empty\" id=\"c-2-0\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-2-1\" role=\"gridcell\"><\/div>\n          <div class=\"cell empty\" id=\"c-2-2\" role=\"gridcell\"><\/div>\n        <\/div>\n      <\/div>\n\n      <!-- ===== Score + CTAs ===== -->\n      <aside class=\"side\">\n        <div class=\"scorebox\" aria-live=\"polite\">\n          <div class=\"score-title\">SCORE<\/div>\n          <div class=\"scorebar\">\n            <div class=\"stat\"><div class=\"label\">Victoires<\/div><div class=\"value\" id=\"score-p\">0<\/div><\/div>\n            <div class=\"stat\"><div class=\"label\">Nuls<\/div><div class=\"value\" id=\"score-d\">0<\/div><\/div>\n            <div class=\"stat\"><div class=\"label\">Bot<\/div><div class=\"value\" id=\"score-b\">0<\/div><\/div>\n          <\/div>\n          <div class=\"ticker\" id=\"ticker\">\n            <!-- 20 segments -->\n            <div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div>\n            <div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div>\n            <div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div>\n            <div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div><div class=\"tick\"><\/div>\n          <\/div>\n        <\/div>\n\n        <a class=\"btn\"\n           href=\"mailto:contact@lab2-2.com?subject=Projet%20web%20-%20LAB%202.2&body=Bonjour%20LAB%202.2%2C%0A%0AMon%20projet%20%3A%20[Site%20vitrine%2C%20e-commerce%2C%20branding%2C%20automatisation...]%0AObjectifs%20%3A%20[...]%0ABudget%20indicatif%20%3A%20[...]%0AD%C3%A9lai%20souhait%C3%A9%20%3A%20[...]%0A%0AMerci%20!\">\n          <span class=\"txt\">Demander un devis<\/span>\n        <\/a>\n\n        <a class=\"btn secondary\" target=\"_blank\" rel=\"noopener\"\n           href=\"https:\/\/www.instagram.com\/lab2.deux?utm_source=ig_web_button_share_sheet&igsh=ZDNlZDc0MzIxNw==\">\n          <span class=\"txt\">Instagram @lab2.deux<\/span>\n        <\/a>\n\n        <div class=\"note\">Contact direct&nbsp;: <a href=\"mailto:contact@lab2-2.com\" style=\"color:var(--blue);text-decoration:none;border-bottom:2px solid transparent\">contact@lab2-2.com<\/a><\/div>\n      <\/aside>\n    <\/section>\n  <\/div>\n\n  <!-- Overlay -->\n  <div class=\"overlay\" id=\"ov\"><div class=\"card\" id=\"ov-card\"><\/div><\/div>\n\n<script>\n\/* IA \u201cdouce\u201d + scoreboard \u00e0 droite en desktop (mobile first) *\/\n(function(){\n  const BLUNDER_WIN_PROB=0.20, MISS_BLOCK_PROB=0.60, RANDOM_MOVE_PROB=0.30;\n\n  const cells=[...document.querySelectorAll('.cell')];\n  const scoreP=document.getElementById('score-p');\n  const scoreD=document.getElementById('score-d');\n  const scoreB=document.getElementById('score-b');\n  const ticker=document.getElementById('ticker').children;\n  const ov=document.getElementById('ov'), ovCard=document.getElementById('ov-card');\n\n  const P='X', B='O';\n  let board=[[\"\",\"\",\"\"],[\"\",\"\",\"\"],[\"\",\"\",\"\"]];\n  let playerTurn=true;\n  let botStartsNext=false;\n\n  const KEY='lab22.ttt.scores';\n  let scores=JSON.parse(localStorage.getItem(KEY)||'{\"p\":0,\"d\":0,\"b\":0}');\n  updateScore(); updateTicker();\n\n  cells.forEach(cell=>{\n    cell.addEventListener('click',()=>onClick(cell));\n    cell.addEventListener('touchend',e=>{e.preventDefault();onClick(cell);},{passive:false});\n  });\n\n  function startRound(){\n    reset();\n    if(botStartsNext){ playerTurn=false; setTimeout(botTurn,180); } else { playerTurn=true; }\n    botStartsNext=!botStartsNext;\n  }\n\n  function onClick(cell){\n    if(!playerTurn) return;\n    const [i,j]=cell.id.split('-').slice(1).map(Number);\n    if(board[i][j]!=\"\") return;\n    board[i][j]=P; render();\n    if(isWin(P)) return end('win');\n    if(isFull()) return end('draw');\n    playerTurn=false; setTimeout(botTurn,140);\n  }\n\n  function botTurn(){\n    const myWin=findImmediateWin(B);\n    if(myWin && Math.random()>=BLUNDER_WIN_PROB){\n      play(myWin.i,myWin.j,B);\n      if(isWin(B)) return end('lose');\n      if(isFull()) return end('draw');\n      playerTurn=true; return;\n    }\n    const theirWin=findImmediateWin(P);\n    if(theirWin && Math.random()>=MISS_BLOCK_PROB){\n      play(theirWin.i,theirWin.j,B);\n      if(isWin(B)) return end('lose');\n      if(isFull()) return end('draw');\n      playerTurn=true; return;\n    }\n    if(Math.random()<RANDOM_MOVE_PROB){\n      const empties=emptyCells();\n      if(empties.length){\n        const rnd=empties[Math.floor(Math.random()*empties.length)];\n        play(rnd.i,rnd.j,B);\n        if(isWin(B)) return end('lose');\n        if(isFull()) return end('draw');\n        playerTurn=true; return;\n      }\n    }\n    let bestScore=-Infinity, bestMove=null;\n    for(let i=0;i<3;i++)for(let j=0;j<3;j++) if(board[i][j]===\"\"){\n      board[i][j]=B; const sc=minimax(board,0,false,-Infinity,+Infinity); board[i][j]=\"\";\n      if(sc>bestScore){ bestScore=sc; bestMove={i,j}; }\n    }\n    if(bestMove) play(bestMove.i,bestMove.j,B);\n    if(isWin(B)) return end('lose');\n    if(isFull()) return end('draw');\n    playerTurn=true;\n  }\n\n  function minimax(b,d,max,a,bt){\n    if(isWin(B)) return 10-d;\n    if(isWin(P)) return d-10;\n    if(full(b))  return 0;\n    if(max){\n      let best=-Infinity;\n      for(let i=0;i<3;i++)for(let j=0;j<3;j++)if(b[i][j]===\"\"){\n        b[i][j]=B; const v=minimax(b,d+1,false,a,bt); b[i][j]=\"\";\n        best=Math.max(best,v); a=Math.max(a,best); if(bt<=a) return best;\n      }\n      return best;\n    }else{\n      let best=+Infinity;\n      for(let i=0;i<3;i++)for(let j=0;j<3;j++)if(b[i][j]===\"\"){\n        b[i][j]=P; const v=minimax(b,d+1,true,a,bt); b[i][j]=\"\";\n        best=Math.min(best,v); bt=Math.min(bt,best); if(bt<=a) return best;\n      }\n      return best;\n    }\n  }\n\n  function render(){ for(let i=0;i<3;i++)for(let j=0;j<3;j++){ const c=document.getElementById(`c-${i}-${j}`), v=board[i][j]; c.textContent=v; c.classList.toggle('empty',v===\"\"); } }\n  function play(i,j,s){ board[i][j]=s; render(); }\n  function emptyCells(){ const r=[]; for(let i=0;i<3;i++)for(let j=0;j<3;j++) if(board[i][j]===\"\") r.push({i,j}); return r; }\n  function full(b){ for(let i=0;i<3;i++)for(let j=0;j<3;j++) if(b[i][j]===\"\") return false; return true; }\n  function isFull(){ return full(board); }\n  function isWin(s){ for(let i=0;i<3;i++) if(board[i][0]===s&&board[i][1]===s&&board[i][2]===s) return true;\n                     for(let j=0;j<3;j++) if(board[0][j]===s&&board[1][j]===s&&board[2][j]===s) return true;\n                     if(board[0][0]===s&&board[1][1]===s&&board[2][2]===s) return true;\n                     if(board[0][2]===s&&board[1][1]===s&&board[2][0]===s) return true; return false; }\n  function findImmediateWin(s){ for(let i=0;i<3;i++)for(let j=0;j<3;j++) if(board[i][j]===\"\"){ board[i][j]=s; const ok=isWin(s); board[i][j]=\"\"; if(ok) return {i,j}; } return null; }\n\n  function end(t){\n    if(t==='win') scores.p++; else if(t==='lose') scores.b++; else scores.d++;\n    updateScore(); updateTicker();\n    showOverlay(`<h1 style=\"font-family:'Argent Pixel','Salo',system-ui\">${t==='win'?'Bravo \ud83c\udf89':t==='lose'?'Le bot gagne \ud83e\udd16':'Match nul'}<\/h1>\n      <p>${t==='win'?'Vous avez gagn\u00e9 !':t==='lose'?'Revanche ?':'Bien jou\u00e9 !'}<\/p>\n      <p><button class=\"btn\" data-act=\"restart\"><span class=\"txt\">\u21ba Rejouer<\/span><\/button><\/p>`);\n  }\n\n  function reset(){ board=[[\"\",\"\",\"\"],[\"\",\"\",\"\"],[\"\",\"\",\"\"]]; playerTurn=true; render(); }\n  function updateScore(){ scoreP.textContent=scores.p; scoreD.textContent=scores.d; scoreB.textContent=scores.b; localStorage.setItem(KEY,JSON.stringify(scores)); }\n  function updateTicker(){ const total=scores.p+scores.b+scores.d; const rate=total?Math.round((scores.p\/total)*20):0; for(let i=0;i<20;i++) ticker[i].classList.toggle('fill',i<rate); }\n\n  function showOverlay(html){ ovCard.innerHTML=html; ov.style.display='grid'; bindOverlay(); }\n  function hideOverlay(){ ov.style.display='none'; }\n  function bindOverlay(){ const s=ov.querySelector('[data-act=\"start\"]'); const r=ov.querySelector('[data-act=\"restart\"]');\n    if(s) s.addEventListener('click',()=>{ startRound(); hideOverlay(); });\n    if(r) r.addEventListener('click',()=>{ startRound(); hideOverlay(); }); }\n\n  window.addEventListener('keydown',e=>{ const k=(e.key||'').toLowerCase();\n    if(k===' '){ e.preventDefault(); if(ov.style.display==='grid') hideOverlay(); else showOverlay(`<h1 style=\"font-family:'Argent Pixel','Salo',system-ui\">Pause<\/h1><p><button class=\"btn\" data-act=\"start\"><span class=\"txt\">\u25b6 Reprendre<\/span><\/button><\/p>`); }\n    if(k==='r'){ e.preventDefault(); startRound(); }});\n\n  (function(){ const who=(Math.random()<0.5);\n    showOverlay(`<h1 style=\"font-family:'Argent Pixel','Salo',system-ui\">${who?'Vous commencez':'Le bot commence'}<\/h1>\n      <p><b>Vous \u00eates X<\/b> \u2022 Le bot est O.<\/p>\n      <p><button class=\"btn\" data-act=\"start\"><span class=\"txt\">\u25b6 Jouer<\/span><\/button><\/p>`); })();\n\n  render();\n})();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/header>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>LAB 2.2 \u2014 Tic-Tac-Toe IA \u2022 Site en construction SITE EN CONSTRUCTION SCORE Victoires0 Nuls0 Bot0 Demander un devis Instagram @lab2.deux Contact direct&nbsp;: contact@lab2-2.com<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-2","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/pages\/2","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/comments?post=2"}],"version-history":[{"count":27,"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/pages\/2\/revisions"}],"predecessor-version":[{"id":141,"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/pages\/2\/revisions\/141"}],"wp:attachment":[{"href":"https:\/\/lab2-2.fr\/index.php\/wp-json\/wp\/v2\/media?parent=2"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}