{"id":71,"date":"2026-09-28T13:48:54","date_gmt":"2026-09-28T13:48:54","guid":{"rendered":"https:\/\/thenewsmark.org\/?page_id=71"},"modified":"2026-09-28T13:48:54","modified_gmt":"2026-09-28T13:48:54","slug":"sudoku","status":"publish","type":"page","link":"https:\/\/thenewsmark.org\/index.php\/sudoku\/","title":{"rendered":"SuDoKu"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Daily Hard Sudoku<\/title>\n\n<style>\n    * {\n        box-sizing: border-box;\n    }\n\n    body {\n        margin: 0;\n        min-height: 100vh;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        font-family: Arial, sans-serif;\n        background: #111827;\n        color: white;\n    }\n\n    .game {\n        width: min(95vw, 520px);\n        text-align: center;\n    }\n\n    h1 {\n        margin-bottom: 5px;\n    }\n\n    .subtitle {\n        color: #9ca3af;\n        margin-bottom: 20px;\n    }\n\n    #board {\n        display: grid;\n        grid-template-columns: repeat(9, 1fr);\n        width: min(90vw, 450px);\n        aspect-ratio: 1;\n        margin: auto;\n        border: 3px solid white;\n    }\n\n    .cell {\n        width: 100%;\n        aspect-ratio: 1;\n        border: 1px solid #4b5563;\n        background: #1f2937;\n        color: white;\n        font-size: clamp(18px, 5vw, 30px);\n        text-align: center;\n        outline: none;\n    }\n\n    .cell:focus {\n        background: #374151;\n    }\n\n    \/* Thick 3x3 box borders *\/\n    .cell:nth-child(3n) {\n        border-right: 3px solid white;\n    }\n\n    .cell:nth-child(9n) {\n        border-right: none;\n    }\n\n    .cell:nth-child(n+19):nth-child(-n+27),\n    .cell:nth-child(n+46):nth-child(-n+54) {\n        border-bottom: 3px solid white;\n    }\n\n    .given {\n        background: #374151;\n        font-weight: bold;\n    }\n\n    .correct {\n        background: #166534 !important;\n        color: #bbf7d0;\n    }\n\n    .wrong {\n        background: #991b1b !important;\n        color: #fecaca;\n    }\n\n    .controls {\n        margin-top: 20px;\n    }\n\n    button {\n        border: none;\n        border-radius: 8px;\n        padding: 12px 20px;\n        margin: 5px;\n        font-size: 16px;\n        font-weight: bold;\n        cursor: pointer;\n    }\n\n    #guessBtn {\n        background: #22c55e;\n        color: white;\n    }\n\n    #newGameBtn {\n        background: #374151;\n        color: white;\n    }\n\n    button:hover {\n        opacity: 0.85;\n    }\n\n    #status {\n        margin-top: 12px;\n        min-height: 24px;\n        font-weight: bold;\n    }\n\n    .tries {\n        margin-top: 10px;\n        color: #d1d5db;\n    }\n\n    .tries span {\n        color: #f87171;\n        font-weight: bold;\n    }\n<\/style>\n<\/head>\n\n<body>\n\n<div class=\"game\">\n    <h1>Daily Hard Sudoku<\/h1>\n    <div class=\"subtitle\" id=\"date\"><\/div>\n\n    <div id=\"board\"><\/div>\n\n    <div class=\"controls\">\n        <button id=\"guessBtn\">Guess<\/button>\n        <button id=\"newGameBtn\">New Puzzle<\/button>\n\n        <div class=\"tries\">\n            Wrong guesses remaining: <span id=\"tries\">3<\/span>\n        <\/div>\n\n        <div id=\"status\"><\/div>\n    <\/div>\n<\/div>\n\n<script>\n\/* =========================\n   DAILY SEED\n========================= *\/\n\nfunction getDailySeed() {\n    const today = new Date();\n\n    const dateString =\n        today.getFullYear() + \"-\" +\n        (today.getMonth() + 1) + \"-\" +\n        today.getDate();\n\n    let seed = 0;\n\n    for (let i = 0; i < dateString.length; i++) {\n        seed = ((seed << 5) - seed) + dateString.charCodeAt(i);\n        seed |= 0;\n    }\n\n    return Math.abs(seed);\n}\n\n\/* =========================\n   SEEDED RANDOM\n========================= *\/\n\nfunction seededRandom(seed) {\n    let x = seed;\n\n    return function () {\n        x = (x * 1664525 + 1013904223) % 4294967296;\n        return x \/ 4294967296;\n    };\n}\n\n\/* =========================\n   SUDOKU GENERATOR\n========================= *\/\n\nfunction generateSolvedBoard(random) {\n    const board = Array.from(\n        { length: 9 },\n        () => Array(9).fill(0)\n    );\n\n    function shuffle(array) {\n        for (let i = array.length - 1; i > 0; i--) {\n            const j = Math.floor(random() * (i + 1));\n            [array[i], array[j]] = [array[j], array[i]];\n        }\n        return array;\n    }\n\n    function solve() {\n        let row = -1;\n        let col = -1;\n\n        for (let r = 0; r < 9; r++) {\n            for (let c = 0; c < 9; c++) {\n                if (board[r][c] === 0) {\n                    row = r;\n                    col = c;\n                    break;\n                }\n            }\n            if (row !== -1) break;\n        }\n\n        if (row === -1) return true;\n\n        let numbers = shuffle([1,2,3,4,5,6,7,8,9]);\n\n        for (const num of numbers) {\n            let valid = true;\n\n            for (let i = 0; i < 9; i++) {\n                if (board[row][i] === num ||\n                    board[i][col] === num) {\n                    valid = false;\n                    break;\n                }\n            }\n\n            const boxRow = Math.floor(row \/ 3) * 3;\n            const boxCol = Math.floor(col \/ 3) * 3;\n\n            for (let r = boxRow; r < boxRow + 3; r++) {\n                for (let c = boxCol; c < boxCol + 3; c++) {\n                    if (board[r][c] === num) {\n                        valid = false;\n                    }\n                }\n            }\n\n            if (valid) {\n                board[row][col] = num;\n\n                if (solve()) return true;\n\n                board[row][col] = 0;\n            }\n        }\n\n        return false;\n    }\n\n    solve();\n    return board;\n}\n\n\/* =========================\n   CREATE PUZZLE\n========================= *\/\n\nfunction createPuzzle(seed) {\n    const random = seededRandom(seed);\n\n    const solution = generateSolvedBoard(random);\n\n    const puzzle = solution.map(row => [...row]);\n\n    \/*\n       Remove lots of numbers to make the puzzle difficult.\n       Around 52 cells removed = 29 clues.\n    *\/\n\n    let cellsToRemove = 52;\n\n    while (cellsToRemove > 0) {\n        const r = Math.floor(random() * 9);\n        const c = Math.floor(random() * 9);\n\n        if (puzzle[r][c] !== 0) {\n            puzzle[r][c] = 0;\n            cellsToRemove--;\n        }\n    }\n\n    return {\n        puzzle,\n        solution\n    };\n}\n\n\/* =========================\n   GAME STATE\n========================= *\/\n\nlet seed = getDailySeed();\nlet game = createPuzzle(seed);\n\nlet puzzle = game.puzzle;\nlet solution = game.solution;\n\nlet wrongGuesses = 0;\nconst maxWrongGuesses = 3;\n\nconst boardElement = document.getElementById(\"board\");\nconst triesElement = document.getElementById(\"tries\");\nconst statusElement = document.getElementById(\"status\");\nconst dateElement = document.getElementById(\"date\");\n\nconst today = new Date();\n\ndateElement.textContent =\n    \"Puzzle for \" +\n    today.toLocaleDateString(undefined, {\n        weekday: \"long\",\n        month: \"long\",\n        day: \"numeric\",\n        year: \"numeric\"\n    });\n\n\/* =========================\n   DRAW BOARD\n========================= *\/\n\nfunction drawBoard() {\n    boardElement.innerHTML = \"\";\n\n    for (let r = 0; r < 9; r++) {\n        for (let c = 0; c < 9; c++) {\n\n            const input = document.createElement(\"input\");\n\n            input.className = \"cell\";\n            input.type = \"text\";\n            input.inputMode = \"numeric\";\n            input.maxLength = 1;\n\n            input.dataset.row = r;\n            input.dataset.col = c;\n\n            if (puzzle[r][c] !== 0) {\n                input.value = puzzle[r][c];\n                input.readOnly = true;\n                input.classList.add(\"given\");\n            }\n\n            input.addEventListener(\"input\", function () {\n                this.value = this.value.replace(\/[^1-9]\/g, \"\");\n\n                this.classList.remove(\"correct\", \"wrong\");\n                statusElement.textContent = \"\";\n            });\n\n            boardElement.appendChild(input);\n        }\n    }\n}\n\n\/* =========================\n   GUESS BUTTON\n========================= *\/\n\ndocument.getElementById(\"guessBtn\").addEventListener(\"click\", () => {\n\n    if (wrongGuesses >= maxWrongGuesses) {\n        statusElement.textContent =\n            \"Game over \u2014 you used all 3 guesses.\";\n        statusElement.style.color = \"#f87171\";\n        return;\n    }\n\n    const cells = document.querySelectorAll(\".cell\");\n\n    let foundNumber = false;\n    let allCorrect = true;\n\n    cells.forEach(cell => {\n\n        const r = Number(cell.dataset.row);\n        const c = Number(cell.dataset.col);\n\n        if (puzzle[r][c] !== 0) return;\n\n        if (cell.value !== \"\") {\n            foundNumber = true;\n\n            const guess = Number(cell.value);\n\n            if (guess === solution[r][c]) {\n                cell.classList.add(\"correct\");\n                cell.classList.remove(\"wrong\");\n            } else {\n                cell.classList.add(\"wrong\");\n                cell.classList.remove(\"correct\");\n                allCorrect = false;\n            }\n        }\n    });\n\n    if (!foundNumber) {\n        statusElement.textContent =\n            \"Enter at least one number first.\";\n        statusElement.style.color = \"#fbbf24\";\n        return;\n    }\n\n    if (allCorrect) {\n        statusElement.textContent =\n            \"Correct! \ud83c\udf89 Keep solving!\";\n        statusElement.style.color = \"#4ade80\";\n    } else {\n        wrongGuesses++;\n\n        const remaining = maxWrongGuesses - wrongGuesses;\n\n        triesElement.textContent = remaining;\n\n        if (remaining === 0) {\n            statusElement.textContent =\n                \"Game over! You used all 3 guesses.\";\n            statusElement.style.color = \"#f87171\";\n\n            revealSolution();\n        } else {\n            statusElement.textContent =\n                \"Some guesses are wrong. \" +\n                remaining +\n                \" guess\" +\n                (remaining === 1 ? \"\" : \"es\") +\n                \" remaining.\";\n            statusElement.style.color = \"#f87171\";\n        }\n    }\n});\n\n\/* =========================\n   REVEAL SOLUTION\n========================= *\/\n\nfunction revealSolution() {\n\n    const cells = document.querySelectorAll(\".cell\");\n\n    cells.forEach(cell => {\n\n        const r = Number(cell.dataset.row);\n        const c = Number(cell.dataset.col);\n\n        if (puzzle[r][c] === 0) {\n            cell.value = solution[r][c];\n            cell.readOnly = true;\n        }\n    });\n}\n\n\/* =========================\n   NEW PUZZLE\n========================= *\/\n\ndocument.getElementById(\"newGameBtn\").addEventListener(\"click\", () => {\n\n    \/*\n       Generates another puzzle using a random seed.\n       The daily puzzle itself remains determined by the date.\n    *\/\n\n    seed = Math.floor(Math.random() * 1000000000);\n\n    game = createPuzzle(seed);\n\n    puzzle = game.puzzle;\n    solution = game.solution;\n\n    wrongGuesses = 0;\n\n    triesElement.textContent = maxWrongGuesses;\n\n    statusElement.textContent = \"\";\n    statusElement.style.color = \"\";\n\n    drawBoard();\n});\n\n\/* =========================\n   START\n========================= *\/\n\ndrawBoard();\n<\/script>\n\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Daily Hard Sudoku Daily Hard Sudoku Guess New Puzzle Wrong guesses remaining: 3<\/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-71","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/pages\/71","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/comments?post=71"}],"version-history":[{"count":2,"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/pages\/71\/revisions"}],"predecessor-version":[{"id":73,"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/pages\/71\/revisions\/73"}],"wp:attachment":[{"href":"https:\/\/thenewsmark.org\/index.php\/wp-json\/wp\/v2\/media?parent=71"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}