SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>数独核对底稿生成器</title>
    <style>
        body { font-family: "微软雅黑", sans-serif; display: flex; flex-direction: column; align-items: center; padding: 20px; background-color: #f4f6f9; }
        .input-area { width: 700px; background: #fff; padding: 15px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); display: flex; gap: 10px; align-items: center; }
        textarea { flex: 1; height: 60px; font-size: 14px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; resize: none; font-family: monospace; }
        button { padding: 10px 20px; font-size: 16px; background-color: #0056b3; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; }
        button:hover { background-color: #004494; }
        
        .container { display: flex; gap: 30px; }
        .board { display: grid; grid-template-columns: repeat(9, 50px); grid-template-rows: repeat(9, 50px); border: 3px solid #333; background: #fff;}
        .cell { width: 50px; height: 50px; display: flex; justify-content: center; align-items: center; font-size: 24px; font-weight: bold; border: 1px solid #ccc; box-sizing: border-box; background-color: #fff; cursor: pointer; outline: none; text-align: center; transition: background-color 0.2s; }
        
        /* 3x3 粗边框 */
        .cell:nth-child(3n) { border-right: 3px solid #333; }
        .cell:nth-child(9n) { border-right: 1px solid #ccc; }
        .cell:nth-child(n+19):nth-child(-n+27), .cell:nth-child(n+46):nth-child(-n+54) { border-bottom: 3px solid #333; }
        
        .cell.initial { background-color: #e2e6ea; color: #333; pointer-events: none; }
        .cell.error { color: #d9534f; background-color: #f2dede; }
        
        .panel { width: 250px; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .panel h3 { margin-top: 0; color: #333; border-bottom: 2px solid #eee; padding-bottom: 10px; }
        .info-item { display: flex; justify-content: space-between; margin-bottom: 15px; font-size: 14px; color: #555; }
        .info-val { font-weight: bold; color: #000; }
        .status-error { color: #d9534f !important; }
    </style>
</head>
<body>

    <!-- 顶部输入区 -->
    <div class="input-area">
        <textarea id="puzzle-input" placeholder="在这里粘贴 81 个数字。例如:7 0 0 0 8 0 0 5 0 0 0 6 9 0 1... (0代表空格,允许带空格或换行)"></textarea>
        <button onclick="generateNewBoard()">生成底稿</button>
    </div>

    <!-- 游戏区 -->
    <div class="container">
        <div class="board" id="sudoku-board"></div>
        <div class="panel">
            <h3>数据核对底稿</h3>
            <div class="info-item"><span>待核对项</span><span class="info-val" id="blank-count">0</span></div>
            <div class="info-item"><span>异常项 (冲突)</span><span class="info-val" id="error-count">0</span></div>
            <div class="info-item"><span>核对状态</span><span class="info-val" id="status">进行中</span></div>
            <div class="info-item"><span>校验规则</span><span class="info-val" style="font-size:12px; color:#888;">同行/列/宫不重复</span></div>
        </div>
    </div>

    <script>
        let blanks = 0;
        const board = document.getElementById('sudoku-board');
        const blankCountEl = document.getElementById('blank-count');
        const errorCountEl = document.getElementById('error-count');
        const statusEl = document.getElementById('status');

        // 默认填入当前这道题目
        document.getElementById('puzzle-input').value = 
            "7 0 0 0 8 0 0 5 0 " +
            "0 0 6 9 0 1 0 0 0 " +
            "0 0 0 0 3 0 1 0 7 " +
            "6 0 0 5 0 0 8 0 0 " +
            "0 0 8 0 0 0 5 0 0 " +
            "0 0 9 0 0 4 0 0 3 " +
            "3 0 2 0 4 0 0 0 0 " +
            "0 0 0 2 0 7 4 0 0 " +
            "0 7 0 0 6 0 0 0 1";

        // 页面加载完成后先渲染一次
        window.onload = () => generateNewBoard();

        function generateNewBoard() {
            // 1. 获取并清洗输入内容
            let rawInput = document.getElementById('puzzle-input').value;
            // 只保留数字 (过滤掉空格、逗号、换行等)
            let digits = rawInput.replace(/[^0-9]/g, '');

            if (digits.length !== 81) {
                alert('输入错误:必须正好包含 81 个数字!当前包含 ' + digits.length + ' 个。');
                return;
            }

            // 2. 转换成二维数组
            let puzzle = [];
            for (let i = 0; i < 9; i++) {
                let row = [];
                for (let j = 0; j < 9; j++) {
                    row.push(parseInt(digits[i * 9 + j]));
                }
                puzzle.push(row);
            }

            // 3. 清空旧棋盘并重新渲染
            board.innerHTML = '';
            blanks = 0;

            for (let r = 0; r < 9; r++) {
                for (let c = 0; c < 9; c++) {
                    const cell = document.createElement('div');
                    cell.className = 'cell';
                    cell.dataset.row = r;
                    cell.dataset.col = c;
                    cell.id = `cell-${r}-${c}`;
                    
                    if (puzzle[r][c] !== 0) {
                        cell.textContent = puzzle[r][c];
                        cell.classList.add('initial');
                    } else {
                        blanks++;
                        cell.setAttribute('contenteditable', 'true');
                    }

                    cell.addEventListener('input', function() {
                        let val = this.textContent.trim();
                        if (val !== '' && !/^[1-9]$/.test(val)) {
                            this.textContent = '';
                        }
                        validateBoard();
                    });

                    cell.addEventListener('keydown', function(e) {
                        if (e.key === 'Enter') e.preventDefault();
                    });

                    board.appendChild(cell);
                }
            }
            // 初始化面板
            validateBoard();
        }

        // 核心:全盘查重逻辑 (与之前一致)
        function validateBoard() {
            let currentBoard = [];
            for(let r=0; r<9; r++) {
                let row = [];
                for(let c=0; c<9; c++) {
                    let val = document.getElementById(`cell-${r}-${c}`).textContent;
                    row.push(val ? parseInt(val) : 0);
                }
                currentBoard.push(row);
            }

            document.querySelectorAll('.cell').forEach(c => c.classList.remove('error'));
            let errorCells = new Set();

            // 查行/列
            for (let i = 0; i < 9; i++) {
                let rowSeen = {}, colSeen = {};
                for (let j = 0; j < 9; j++) {
                    let rVal = currentBoard[i][j];
                    if (rVal !== 0) {
                        if (rowSeen[rVal] !== undefined) {
                            errorCells.add(`${i}-${j}`); errorCells.add(`${i}-${rowSeen[rVal]}`);
                        } else rowSeen[rVal] = j;
                    }
                    let cVal = currentBoard[j][i];
                    if (cVal !== 0) {
                        if (colSeen[cVal] !== undefined) {
                            errorCells.add(`${j}-${i}`); errorCells.add(`${colSeen[cVal]}-${i}`);
                        } else colSeen[cVal] = j;
                    }
                }
            }

            // 查 3x3 宫
            for (let boxRow = 0; boxRow < 3; boxRow++) {
                for (let boxCol = 0; boxCol < 3; boxCol++) {
                    let boxSeen = {};
                    for (let r = 0; r < 3; r++) {
                        for (let c = 0; c < 3; c++) {
                            let actualR = boxRow * 3 + r;
                            let actualC = boxCol * 3 + c;
                            let val = currentBoard[actualR][actualC];
                            if (val !== 0) {
                                if (boxSeen[val] !== undefined) {
                                    errorCells.add(`${actualR}-${actualC}`); errorCells.add(`${boxSeen[val].r}-${boxSeen[val].c}`);
                                } else {
                                    boxSeen[val] = {r: actualR, c: actualC};
                                }
                            }
                        }
                    }
                }
            }

            // 标红
            errorCells.forEach(coord => {
                document.getElementById(`cell-${coord}`).classList.add('error');
            });

            updateStats(errorCells.size);
        }

        function updateStats(errorCount) {
            let filled = 0;
            document.querySelectorAll('.cell:not(.initial)').forEach(cell => {
                if (cell.textContent.trim() !== '') filled++;
            });

            blankCountEl.textContent = blanks - filled;
            errorCountEl.textContent = errorCount;

            if (errorCount > 0) {
                errorCountEl.classList.add('status-error');
                statusEl.textContent = '异常待处理';
                statusEl.classList.add('status-error');
            } else {
                errorCountEl.classList.remove('status-error');
                statusEl.classList.remove('status-error');
                if (filled === blanks) {
                    statusEl.textContent = '无冲突 (已填满)';
                    statusEl.style.color = '#28a745';
                } else {
                    statusEl.textContent = '进行中 (暂无冲突)';
                    statusEl.style.color = '#000';
                }
            }
        }
    </script>
</body>
</html>