PageSourceSearch

https://z-add.co.uk/build/assets/TicTacToe-C27pw_KC.js

js z-add.co.uk collected 2026-09-24 14:29:24 UTC 5,557 bytes, 1 lines download raw bytes

1import{b as u,j as r}from"./client-B-Oz738J.js";import{T as H}from"./ToolPage-Dwy0IH4M.js";import{M as O,s as I}from"./ToolUi-CDNt51r_.js";import"./SeoHead-CTJ5a3SL.js";import"./CopyButton-DzWiNVYm.js";const S=null,_=[[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]],P=()=>Array(9).fill(S);function X(e){for(const n of _){const[s,o,t]=n;if(e[s]&&e[s]===e[o]&&e[s]===e[t])return n}return null}function M(e){const n=X(e);return n?e[n[0]]:e.every(s=>s!==S)?"draw":null}const p=e=>e.reduce((n,s,o)=>s===S?[...n,o]:n,[]),y=e=>e==="X"?"O":"X",$=new Map;function Y(e,n,s){const o=M(e),t=9-p(e).length;if(o===s)return 10-t;if(o===y(s))return t-10;if(o==="draw")return 0;const c=e.map(f=>f??".").join("")+n+s,l=$.get(c);if(l!==void 0)return l;const d=p(e).map(f=>{const x=e.slice();return x[f]=n,Y(x,y(n),s)}),h=n===s?Math.max(...d):Math.min(...d);return $.set(c,h),h}function J(e,n){const s=p(e).map(t=>{const c=e.slice();return c[t]=n,{move:t,score:Y(c,y(n),n)}}),o=Math.max(...s.map(t=>t.score));return{moves:s.filter(t=>t.score===o).map(t=>t.move),score:o}}const w=[{id:"easy",label:"Easy",mistakeChance:.75,description:"Mostly random moves — a good place to start."},{id:"medium",label:"Medium",mistakeChance:.4,description:"Blocks and wins fairly often, but still makes real mistakes."},{id:"hard",label:"Hard",mistakeChance:.15,description:"Plays well. Rarely gives you an opening."},{id:"unbeatable",label:"Unbeatable",mistakeChance:0,description:"Perfect play. The best you can do is draw."}];function K(e,n,s,o=Math.random){const t=w.find(d=>d.id===s);if(!t)throw new Error(`Unknown difficulty: ${s}`);const c=p(e);if(c.length===0)throw new Error("No legal moves available.");if(t.mistakeChance>0&&o()<t.mistakeChance)return c[Math.floor(o()*c.length)];const{moves:l}=J(e,n);return l[Math.floor(o()*l.length)]}const q=[["X","Play as X (go first)"],["O","Play as O (go second)"]],G=w.map(e=>[e.id,e.label]),D="wormhole:tic-tac-toe:scores",T=()=>({wins:0,draws:0,losses:0});function W(){try{const e=JSON.parse(localStorage.getItem(D));return e&&typeof e=="object"?e:{}}catch{return{}}}function R(e){try{localStorage.setItem(D,JSON.stringify(e))}catch{}}function z({index:e,value:n,onClick:s,disabled:o,highlighted:t}){const c=`row ${Math.floor(e/3)+1}, column ${e%3+1}`;return r.jsx("button",{type:"button",onClick:s,disabled:o||n!==null,"aria-label":n?`${c}: ${n}`:`${c}: empty`,className:`aspect-square flex items-center justify-center text-4xl sm:text-5xl font-bold rounded-md border-2 transition-colors ${t?"bg-green-100 border-green-400 text-green-800":"bg-white border-gray-200 text-gray-800 hover:border-indigo-300 disabled:hover:border-gray-200"} ${n?"":"disabled:cursor-not-allowed"}`,children:n})}function se({section:e,item:n}){const[s,o]=u.useState("X"),[t,c]=u.useState("medium"),[l,d]=u.useState(P),[h,f]=u.useState(!1),[x,C]=u.useState(W),b=u.useRef(!1),g=y(s),m=M(l),A=u.useMemo(()=>X(l),[l]),j=l.filter(a=>a==="X").length===l.filter(a=>a==="O").length?"X":"O",N=!m&&j===s,k=x[t]??T(),v=()=>{d(P()),b.current=!1};u.useEffect(()=>{v()},[s,t]),u.useEffect(()=>{if(m||j!==g)return;f(!0);const a=setTimeout(()=>{d(i=>{if(M(i))return i;const U=K(i,g,t),E=i.slice();return E[U]=g,E}),f(!1)},350+Math.random()*300);return()=>clearTimeout(a)},[l,j,g,m,t]),u.useEffect(()=>{!m||b.current||(b.current=!0,C(a=>{const i={...a,[t]:{...T(),...a[t]}};return m==="draw"?i[t].draws++:m===s?i[t].wins++:i[t].losses++,R(i),i}))},[m,t,s]);const B=a=>{if(!N||l[a]!==null)return;const i=l.slice();i[a]=s,d(i)},F=()=>{const a={...x,[t]:T()};C(a),R(a)},L=m==="draw"?"It's a draw.":m===s?"You win!":m?"The computer wins.":N?"Your turn.":h?"The computer is thinking…":"Waiting for the computer…";return r.jsxs(H,{section:e,item:n,children:[r.jsxs("div",{className:"flex flex-wrap items-start gap-6",children:[r.jsxs("div",{children:[r.jsx("span",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Difficulty"}),r.jsx(O,{value:t,onChange:c,options:G,label:"Difficulty"}),r.jsx("p",{className:"mt-1 text-xs text-gray-500 max-w-xs",children:w.find(a=>a.id===t).description})]}),r.jsxs("div",{children:[r.jsx("span",{className:"block text-sm font-medium text-gray-700 mb-1",children:"You play as"}),r.jsx(O,{value:s,onChange:o,options:q,label:"Mark"})]})]}),r.jsxs("div",{className:"flex flex-col items-center gap-4",children:[r.jsx("p",{role:"status","aria-live":"polite",className:"text-lg font-medium text-gray-900 h-7",children:L}),r.jsx("div",{className:"grid grid-cols-3 gap-2 w-full max-w-xs",role:"grid","aria-label":"Tic-tac-toe board",children:l.map((a,i)=>r.jsx(z,{index:i,value:a,onClick:()=>B(i),disabled:!N,highlighted:A?.includes(i)??!1}
1,i))}),r.jsx("button",{type:"button",onClick:v,className:I,children:"New game"})]}),r.jsxs("div",{className:"border-t border-gray-200 pt-4",children:[r.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[r.jsxs("p",{className:"text-sm text-gray-700",children:["At ",r.jsx("span",{className:"font-medium",children:w.find(a=>a.id===t).label}),":"," ",r.jsxs("span",{className:"font-medium text-green-700",children:[k.wins," won"]}),","," ",r.jsxs("span",{className:"font-medium text-gray-600",children:[k.draws," drawn"]}),","," ",r.jsxs("span",{className:"font-medium text-red-700",children:[k.losses," lost"]})]}),r.jsx("button",{type:"button",onClick:F,className:I,children:"Reset score"})]}),r.jsx("p",{className:"mt-2 text-xs text-gray-500",children:"Your score is kept in this browser only, per difficulty level."})]})]})}export{se as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.