/* SudokuPuzz.com – sudoku game (generator with unique solutions, notes, hints, daily puzzle). */ (function(){ var T={ en:{easy:"Easy",medium:"Medium",hard:"Hard",expert:"Expert",hints:"Hints",today:"Today's puzzle",todayBtn:"Play today's puzzle",newp:"New puzzle",undo:"Undo",erase:"Erase",notes:"Notes",on:"on",off:"off",hint:"Hint",check:"Check",solved:"Solved",next:"Next puzzle",keys:"Keyboard: arrows to move, 1–9 to fill, N for notes, Backspace to erase.",row:"Row",col:"column",empty:"empty",given:"given",board:"Sudoku board",enter:"Enter",in:"in"}, fr:{easy:"Facile",medium:"Moyen",hard:"Difficile",expert:"Expert",hints:"Indices",today:"Sudoku du jour",todayBtn:"Jouer le sudoku du jour",newp:"Nouvelle grille",undo:"Annuler",erase:"Effacer",notes:"Notes",on:"oui",off:"non",hint:"Indice",check:"Vérifier",solved:"Résolu",next:"Grille suivante",keys:"Clavier : flèches pour se déplacer, 1–9 pour remplir, N pour les notes, Retour arrière pour effacer.",row:"Ligne",col:"colonne",empty:"vide",given:"donné",board:"Grille de sudoku",enter:"Saisir",in:"en"}, de:{easy:"Leicht",medium:"Mittel",hard:"Schwer",expert:"Experte",hints:"Tipps",today:"Sudoku des Tages",todayBtn:"Sudoku des Tages spielen",newp:"Neues Rätsel",undo:"Zurück",erase:"Löschen",notes:"Notizen",on:"an",off:"aus",hint:"Tipp",check:"Prüfen",solved:"Gelöst",next:"Nächstes Rätsel",keys:"Tastatur: Pfeile zum Bewegen, 1–9 zum Ausfüllen, N für Notizen, Rücktaste zum Löschen.",row:"Reihe",col:"Spalte",empty:"leer",given:"vorgegeben",board:"Sudoku-Feld",enter:"Eingeben",in:"in"}, nl:{easy:"Gemakkelijk",medium:"Middelmatig",hard:"Moeilijk",expert:"Expert",hints:"Hints",today:"Sudoku van de dag",todayBtn:"Speel de sudoku van de dag",newp:"Nieuwe puzzel",undo:"Terug",erase:"Wissen",notes:"Notities",on:"aan",off:"uit",hint:"Hint",check:"Check",solved:"Opgelost",next:"Volgende puzzel",keys:"Toetsenbord: pijltjes om te bewegen, 1–9 om in te vullen, N voor notities, Backspace om te wissen.",row:"Rij",col:"kolom",empty:"leeg",given:"gegeven",board:"Sudoku-bord",enter:"Invullen",in:"in"}, sv:{easy:"Lätt",medium:"Medel",hard:"Svår",expert:"Expert",hints:"Ledtrådar",today:"Dagens sudoku",todayBtn:"Spela dagens sudoku",newp:"Nytt pussel",undo:"Ångra",erase:"Sudda",notes:"Anteckn.",on:"på",off:"av",hint:"Ledtråd",check:"Kolla",solved:"Löst",next:"Nästa pussel",keys:"Tangentbord: pilar för att flytta, 1–9 för att fylla i, N för anteckningar, Backsteg för att sudda.",row:"Rad",col:"kolumn",empty:"tom",given:"given",board:"Sudokubräde",enter:"Skriv",in:"på"}, es:{easy:"Fácil",medium:"Medio",hard:"Difícil",expert:"Experto",hints:"Pistas",today:"Sudoku del día",todayBtn:"Jugar el sudoku del día",newp:"Nuevo sudoku",undo:"Atrás",erase:"Borrar",notes:"Notas",on:"sí",off:"no",hint:"Pista",check:"Revisar",solved:"Resuelto",next:"Siguiente sudoku",keys:"Teclado: flechas para moverte, 1–9 para rellenar, N para notas, Retroceso para borrar.",row:"Fila",col:"columna",empty:"vacía",given:"dado",board:"Tablero de sudoku",enter:"Escribir",in:"en"}, pt:{easy:"Fácil",medium:"Médio",hard:"Difícil",expert:"Especialista",hints:"Dicas",today:"Sudoku do dia",todayBtn:"Jogar o sudoku do dia",newp:"Novo sudoku",undo:"Voltar",erase:"Apagar",notes:"Notas",on:"sim",off:"não",hint:"Dica",check:"Checar",solved:"Resolvido",next:"Próximo sudoku",keys:"Teclado: setas para mover, 1–9 para preencher, N para notas, Backspace para apagar.",row:"Linha",col:"coluna",empty:"vazia",given:"dado",board:"Tabuleiro de sudoku",enter:"Inserir",in:"em"}, it:{easy:"Facile",medium:"Medio",hard:"Difficile",expert:"Esperto",hints:"Aiuti",today:"Sudoku del giorno",todayBtn:"Gioca il sudoku del giorno",newp:"Nuovo sudoku",undo:"Annulla",erase:"Elimina",notes:"Note",on:"sì",off:"no",hint:"Aiuto",check:"Verifica",solved:"Risolto",next:"Prossimo sudoku",keys:"Tastiera: frecce per spostarti, 1–9 per inserire, N per le note, Backspace per cancellare.",row:"Riga",col:"colonna",empty:"vuota",given:"dato",board:"Griglia sudoku",enter:"Inserisci",in:"in"}, pl:{easy:"Łatwe",medium:"Średnie",hard:"Trudne",expert:"Ekspert",hints:"Podpowiedzi",today:"Sudoku dnia",todayBtn:"Zagraj w sudoku dnia",newp:"Nowe sudoku",undo:"Cofnij",erase:"Usuń",notes:"Notatki",on:"wł.",off:"wył.",hint:"Pomoc",check:"Sprawdź",solved:"Rozwiązane",next:"Następne sudoku",keys:"Klawiatura: strzałki do poruszania, 1–9 do wpisywania, N dla notatek, Backspace do usuwania.",row:"Wiersz",col:"kolumna",empty:"puste",given:"dane",board:"Plansza sudoku",enter:"Wpisz",in:"w czasie"}, nb:{easy:"Lett",medium:"Middels",hard:"Vanskelig",expert:"Ekspert",hints:"Hint",today:"Dagens sudoku",todayBtn:"Spill dagens sudoku",newp:"Ny sudoku",undo:"Angre",erase:"Slett",notes:"Notater",on:"på",off:"av",hint:"Hint",check:"Sjekk",solved:"Løst",next:"Neste sudoku",keys:"Tastatur: piler for å flytte, 1–9 for å fylle inn, N for notater, Backspace for å slette.",row:"Rad",col:"kolonne",empty:"tom",given:"gitt",board:"Sudokubrett",enter:"Skriv",in:"på"}, fi:{easy:"Helppo",medium:"Keskitaso",hard:"Vaikea",expert:"Asiantuntija",hints:"Vihjeet",today:"Päivän sudoku",todayBtn:"Pelaa päivän sudoku",newp:"Uusi sudoku",undo:"Kumoa",erase:"Pyyhi",notes:"Muistio",on:"päällä",off:"pois",hint:"Vihje",check:"Tarkista",solved:"Ratkaistu",next:"Seuraava sudoku",keys:"Näppäimistö: nuolet liikkumiseen, 1–9 täyttämiseen, N muistiinpanoihin, Askelpalautin pyyhkimiseen.",row:"Rivi",col:"sarake",empty:"tyhjä",given:"annettu",board:"Sudokuruudukko",enter:"Syötä",in:"ajassa"}, ro:{easy:"Ușor",medium:"Mediu",hard:"Greu",expert:"Expert",hints:"Indicii",today:"Sudoku-ul zilei",todayBtn:"Joacă sudoku-ul zilei",newp:"Sudoku nou",undo:"Înapoi",erase:"Șterge",notes:"Notițe",on:"da",off:"nu",hint:"Indiciu",check:"Verifică",solved:"Rezolvat",next:"Următorul sudoku",keys:"Tastatură: săgeți pentru mutare, 1–9 pentru completare, N pentru notițe, Backspace pentru ștergere.",row:"Rândul",col:"coloana",empty:"goală",given:"dat",board:"Tablă sudoku",enter:"Scrie",in:"în"}, cs:{easy:"Lehké",medium:"Střední",hard:"Těžké",expert:"Expert",hints:"Nápovědy",today:"Sudoku dne",todayBtn:"Hrát sudoku dne",newp:"Nové sudoku",undo:"Zpět",erase:"Smazat",notes:"Poznámky",on:"zap.",off:"vyp.",hint:"Rada",check:"Kontrola",solved:"Vyřešeno",next:"Další sudoku",keys:"Klávesnice: šipky pro pohyb, 1–9 pro vyplnění, N pro poznámky, Backspace pro smazání.",row:"Řádek",col:"sloupec",empty:"prázdné",given:"zadané",board:"Hrací plocha sudoku",enter:"Zadat",in:"za"}, el:{easy:"Εύκολο",medium:"Μέτριο",hard:"Δύσκολο",expert:"Ειδικός",hints:"Βοήθειες",today:"Sudoku της ημέρας",todayBtn:"Παίξτε το sudoku της ημέρας",newp:"Νέο sudoku",undo:"Πίσω",erase:"Σβήσε",notes:"Σημ.",on:"ναι",off:"όχι",hint:"Βοήθεια",check:"Έλεγχος",solved:"Λύθηκε",next:"Επόμενο sudoku",keys:"Πληκτρολόγιο: βέλη για μετακίνηση, 1–9 για συμπλήρωση, N για σημειώσεις, Backspace για διαγραφή.",row:"Γραμμή",col:"στήλη",empty:"κενό",given:"δεδομένο",board:"Πίνακας sudoku",enter:"Εισαγωγή",in:"σε"}, hu:{easy:"Könnyű",medium:"Közepes",hard:"Nehéz",expert:"Szakértő",hints:"Tippek",today:"A nap sudokuja",todayBtn:"A nap sudokuja",newp:"Új sudoku",undo:"Vissza",erase:"Törlés",notes:"Jegyzet",on:"be",off:"ki",hint:"Tipp",check:"Ellenőriz",solved:"Megoldva",next:"Következő sudoku",keys:"Billentyűzet: nyilak a mozgáshoz, 1–9 a kitöltéshez, N a jegyzetekhez, Backspace a törléshez.",row:"Sor",col:"oszlop",empty:"üres",given:"adott",board:"Sudoku tábla",enter:"Beírás",in:"idő:"}, sk:{easy:"Ľahké",medium:"Stredné",hard:"Ťažké",expert:"Expert",hints:"Nápovede",today:"Sudoku dňa",todayBtn:"Hrať sudoku dňa",newp:"Nové sudoku",undo:"Späť",erase:"Zmazať",notes:"Poznámky",on:"zap.",off:"vyp.",hint:"Rada",check:"Kontrola",solved:"Vyriešené",next:"Ďalšie sudoku",keys:"Klávesnica: šípky na pohyb, 1–9 na vyplnenie, N pre poznámky, Backspace na zmazanie.",row:"Riadok",col:"stĺpec",empty:"prázdne",given:"zadané",board:"Hracia plocha sudoku",enter:"Zadať",in:"za"}, da:{easy:"Nem",medium:"Medium",hard:"Svær",expert:"Ekspert",hints:"Hints",today:"Dagens sudoku",todayBtn:"Spil dagens sudoku",newp:"Ny sudoku",undo:"Fortryd",erase:"Slet",notes:"Noter",on:"til",off:"fra",hint:"Hint",check:"Tjek",solved:"Løst",next:"Næste sudoku",keys:"Tastatur: pile for at flytte, 1–9 for at udfylde, N for noter, Backspace for at slette.",row:"Række",col:"kolonne",empty:"tom",given:"givet",board:"Sudokuplade",enter:"Indtast",in:"på"} }; var root=document.querySelector("[data-sudoku]"); if(!root) return; var L=T[root.getAttribute("data-sudoku")]||T.en; var CLUES={easy:40,medium:32,hard:27,expert:23}; var R=[],C=[],B=[],i,j;for(i=0;i<81;i++){R[i]=(i/9)|0;C[i]=i%9;B[i]=((R[i]/3)|0)*3+((C[i]/3)|0)} var PEERS=[];for(i=0;i<81;i++){var p=[];for(j=0;j<81;j++)if(j!==i&&(R[j]===R[i]||C[j]===C[i]||B[j]===B[i]))p.push(j);PEERS.push(p)} function pop(m){var n=0;while(m){m&=m-1;n++}return n} function rngFrom(a){return function(){a|=0;a=a+0x6D2B79F5|0;var t=Math.imul(a^a>>>15,1|a);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296}} function shuffle(a,rng){for(var i=a.length-1;i>0;i--){var j=(rng()*(i+1))|0,t=a[i];a[i]=a[j];a[j]=t}return a} function solve(grid,limit,rng){ var g=grid.slice(),rm=[0,0,0,0,0,0,0,0,0],cm=rm.slice(),bm=rm.slice(),i; for(i=0;i<81;i++)if(g[i]){var b=1<=limit)return} })(); return{count:count,solution:sol}; } function generate(level,seed){ var rng=rngFrom(seed),full=solve(new Array(81).fill(0),1,rng).solution,p=full.slice(),target=CLUES[level],clues=81; var order=shuffle(Array.from({length:41},function(_,k){return k}),rng); for(var k=0;ktarget;k++){var a=order[k],b=80-a,va=p[a],vb=p[b];p[a]=0;p[b]=0; if(solve(p,2).count!==1){p[a]=va;p[b]=vb}else clues-=a===b?1:2} return{puzzle:p,solution:full}; } var KEY="sudokupuzz-v2",S=null,sel=-1,noteMode=false,hist=[],tick=null; function $(s){return root.querySelector(s)} var board=$(".sp-board"),pad=$(".sp-pad"),cells=[],keys=[]; board.setAttribute("aria-label",L.board); for(i=0;i<81;i++){(function(i){var b=document.createElement("button");b.type="button"; b.className="sp-cell"+(C[i]%3===2&&C[i]<8?" br":"")+(R[i]%3===2&&R[i]<8?" bb":""); b.setAttribute("role","gridcell");b.addEventListener("click",function(){sel=i;render()});board.appendChild(b);cells.push(b)})(i)} for(i=1;i<=9;i++){(function(d){var k=document.createElement("button");k.type="button";k.className="sp-key";k.innerHTML=d+""; k.setAttribute("aria-label",L.enter+" "+d);k.addEventListener("click",function(){input(d)});pad.appendChild(k);keys.push(k)})(i)} root.querySelectorAll("[data-t]").forEach(function(el){el.textContent=L[el.getAttribute("data-t")]}); root.querySelectorAll(".sp-levels button").forEach(function(b){b.textContent=L[b.getAttribute("data-l")]}); function todaySeed(){var d=new Date();return d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate()} function newGame(level,daily){ var seed=daily?todaySeed()*7+1:(Math.random()*2147483647)|0,g=generate(level,seed); S={level:level,puzzle:g.puzzle,solution:g.solution,values:g.puzzle.slice(),notes:new Array(81).fill(0),wrong:[],time:0,hints:0,done:false,daily:daily?todaySeed():0}; hist=[];sel=S.puzzle.indexOf(0);save();render();startClock(); } function save(){try{localStorage.setItem(KEY,JSON.stringify(S))}catch(e){}} function load(){try{var s=JSON.parse(localStorage.getItem(KEY));if(s&&s.solution&&s.values.length===81&&CLUES[s.level])return s}catch(e){}return null} function fmt(t){return String((t/60)|0).padStart(2,"0")+":"+String(t%60).padStart(2,"0")} function startClock(){clearInterval(tick);tick=setInterval(function(){if(S.done||document.hidden)return;S.time++;$(".sp-clock").textContent=fmt(S.time);if(S.time%5===0)save()},1000)} function snap(){hist.push({v:S.values.slice(),n:S.notes.slice()});if(hist.length>200)hist.shift()} function dropWrong(i){S.wrong=S.wrong.filter(function(x){return x!==i})} function clearPeerNotes(i,d){PEERS[i].forEach(function(p){S.notes[p]&=~(1<=0?S.values[sel]:0,counts=new Array(10).fill(0),i; for(i=0;i<81;i++)counts[S.values[i]]++; for(i=0;i<81;i++){ var el=cells[i],v=S.values[i],given=!!S.puzzle[i]; var peer=sel>=0&&i!==sel&&(R[i]===R[sel]||C[i]===C[sel]||B[i]===B[sel]); var conflict=v&&!given&&PEERS[i].some(function(p){return S.values[p]===v}); el.classList.toggle("sel",i===sel);el.classList.toggle("peer",peer); el.classList.toggle("same",!!sv&&v===sv&&i!==sel);el.classList.toggle("user",!!v&&!given); el.classList.toggle("conflict",!!conflict);el.classList.toggle("wrong",S.wrong.indexOf(i)>=0); if(v)el.textContent=v; else if(S.notes[i]){var h='';for(var d=1;d<=9;d++)h+=''+(S.notes[i]&(1<";el.innerHTML=h+""} else el.textContent=""; el.setAttribute("aria-label",L.row+" "+(R[i]+1)+", "+L.col+" "+(C[i]+1)+", "+(v?(given?L.given+" ":"")+v:L.empty)); el.setAttribute("aria-selected",i===sel?"true":"false"); } keys.forEach(function(k,j){var left=9-counts[j+1];k.classList.toggle("done",left<=0);k.querySelector("small").textContent=left>0?left:""}); $(".sp-lvl").textContent=L[S.level];$(".sp-clock").textContent=fmt(S.time);$(".sp-hints").textContent=S.hints; $(".sp-daily").textContent=S.daily?" · "+L.today:""; root.querySelectorAll(".sp-levels button").forEach(function(b){b.classList.toggle("on",b.getAttribute("data-l")===S.level)}); $(".sp-notesbtn").setAttribute("aria-pressed",noteMode?"true":"false");$(".sp-notestate").textContent=noteMode?L.on:L.off; pad.classList.toggle("notes-on",noteMode); $(".sp-solved").hidden=!S.done; if(S.done)$(".sp-solvedmeta").textContent=L[S.level]+" "+L.in+" "+fmt(S.time)+(S.hints?" · "+L.hints+": "+S.hints:""); } $(".sp-undo").onclick=undo;$(".sp-erase").onclick=erase;$(".sp-hint").onclick=hint;$(".sp-check").onclick=check; $(".sp-notesbtn").onclick=function(){noteMode=!noteMode;render()}; $(".sp-again").onclick=function(){newGame(S.level,false)}; $(".sp-today").onclick=function(){newGame("medium",true)}; root.querySelectorAll(".sp-levels button").forEach(function(b){b.onclick=function(){newGame(b.getAttribute("data-l"),false)}}); document.addEventListener("keydown",function(e){ if(e.target.closest&&e.target.closest("input,textarea,select"))return; if(!S)return;var k=e.key; if((e.ctrlKey||e.metaKey)&&k.toLowerCase()==="z"){e.preventDefault();undo();return} if(sel<0&&!/^Arrow/.test(k))return; if(/^[1-9]$/.test(k)){input(+k);return} if(k==="Backspace"||k==="Delete"||k==="0"){erase();return} if(k==="n"||k==="N"){noteMode=!noteMode;render();return} var mv={ArrowUp:-9,ArrowDown:9,ArrowLeft:-1,ArrowRight:1}[k]; if(mv&&!S.done&&root.contains(document.activeElement)){e.preventDefault();if(sel<0)sel=0;else{var n=sel+mv;if(n>=0&&n<81&&(Math.abs(mv)===9||R[n]===R[sel]))sel=n}render();cells[sel].focus({preventScroll:true})} }); S=load(); if(S){render();startClock()}else newGame("medium",false); })();