<!DOCTYPE html>
<html>
<head>
<title>完整版数独游戏</title>
<style>
/* 棋盘样式 */
table { border-collapse: collapse; margin: 20px auto; }
td {
width: 40px;
height: 40px;
border: 1px solid #ccc;
text-align: center;
font-size: 20px;
cursor: pointer;
transition: background 0.3s;
}
.thick-right { border-right: 3px solid #333; }
.thick-bottom { border-bottom: 3px solid #333; }
.conflict { background-color: #ffcccc !important; }
.error { background-color: #ff9999 !important; }
.initial { background-color: #f0f0f0; }
.selected { background-color: #e6f3ff; }
/* 输入面板 */
#input-panel {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background: white;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
border-radius: 8px;
}
/* 控制按钮 */
.controls {
text-align: center;
margin-top: 20px;
}
button {
padding: 10px 20px;
margin: 0 5px;
cursor: pointer;
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
</style>
</head>
<body>
<table id="sudoku-grid"></table>
<div class="controls">
<button onclick="checkSolution()">检查答案</button>
<button onclick="showSolution()">显示答案</button>
<button onclick="newGame()">新游戏</button>
</div>
<div id="input-panel" style="display: none;">
<input type="number" id="number-input" min="1" max="9" autofocus>
<button onclick="confirmInput()">确认</button>
<button onclick="cancelInput()">取消</button>
</div>
<script>
// 游戏状态管理
let currentBoard = Array(9).fill().map(() => Array(9).fill(0));
let initialBoard = Array(9).fill().map(() => Array(9).fill(0));
let selectedCell = null;
// 初始化棋盘
function initializeBoard() {
const grid = document.getElementById('sudoku-grid');
grid.innerHTML = '';
for (let row = 0; row < 9; row++) {
const tr = document.createElement('tr');
for (let col = 0; col < 9; col++) {
const td = document.createElement('td');
td.addEventListener('click', () => handleCellClick(row, col));
// 添加粗边框样式
if (col % 3 === 2 && col !== 8) td.classList.add('thick-right');
if (row % 3 === 2 && row !== 8) td.classList.add('thick-bottom');
tr.appendChild(td);
}
grid.appendChild(tr);
}
}
// 单元格点击处理
function handleCellClick(row, col) {
if (initialBoard[row][col] !== 0) return;
// 清除之前选中的样式
document.querySelectorAll('.selected').forEach(cell => {
cell.classList.remove('selected');
});
selectedCell = { row, col };
document.querySelector(`tr:nth-child(${row + 1}) td:nth-child(${col + 1})`)
.classList.add('selected');
// 显示输入面板
document.getElementById('input-panel').style.display = 'block';
document.getElementById('number-input').focus();
}
// 输入处理
function confirmInput() {
const input = document.getElementById('number-input');
const value = parseInt(input.value);
const { row, col } = selectedCell;
const cell = document.querySelector(`tr:nth-child(${row + 1}) td:nth-child(${col + 1})`);
if (isNaN(value) || value < 1 || value > 9) {
alert('请输入1-9之间的数字');
return;
}
currentBoard[row][col] = value;
cell.textContent = value;
cell.classList.remove('conflict');
// 实时验证
if (!isValid(currentBoard, row, col, value)) {
cell.classList.add('conflict');
}
cancelInput();
}
function cancelInput() {
document.getElementById('input-panel').style.display = 'none';
document.getElementById('number-input').value = '';
selectedCell = null;
}
// 核心算法
function solveSudoku(board) {
const emptyCell = findEmptyCell(board);
if (!emptyCell) return true;
const [row, col] = emptyCell;
for (let num = 1; num <= 9; num++) {
if (isValid(board, row, col, num)) {
board[row][col] = num;
if (solveSudoku(board)) return true;
board[row][col] = 0;
}
}
return false;
}
function findEmptyCell(board) {
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
if (board[row][col] === 0) return [row, col];
}
}
return null;
}
function isValid(board, row, col, num) {
// 行检查
for (let c = 0; c < 9; c++) {
if (board[row][c] === num && c !== col) return false;
}
// 列检查
for (let r = 0; r < 9; r++) {
if (board[r][col] === num && r !== row) return false;
}
// 宫格检查
const startRow = Math.floor(row / 3) * 3;
const startCol = Math.floor(col / 3) * 3;
for (let r = startRow; r < startRow + 3; r++) {
for (let c = startCol; c < startCol + 3; c++) {
if (board[r][c] === num && r !== row && c !== col) return false;
}
}
return true;
}
// 游戏功能
function checkSolution() {
let hasError = false;
let hasEmpty = false;
const cells = document.querySelectorAll('td');
cells.forEach(cell => {
cell.classList.remove('error', 'conflict');
const row = cell.parentElement.rowIndex;
const col = cell.cellIndex;
const value = currentBoard[row][col];
if (value === 0) {
hasEmpty = true;
cell.classList.add('error');
hasError = true;
} else if (!isValid(currentBoard, row, col, value)) {
cell.classList.add('conflict');
hasError = true;
}
});
if (!hasError && !hasEmpty) {
alert('恭喜!解答正确!');
return true;
}
alert(hasError ? '存在错误或冲突!' : '尚未完成所有单元格!');
return false;
}
function showSolution() {
const solution = JSON.parse(JSON.stringify(currentBoard));
if (!solveSudoku(solution)) {
alert('此数独无解!');
return;
}
const cells = document.querySelectorAll('td');
cells.forEach((cell, index) => {
const row = Math.floor(index / 9);
const col = index % 9;
if (initialBoard[row][col] === 0) {
currentBoard[row][col] = solution[row][col];
cell.textContent = solution[row][col];
cell.classList.remove('conflict');
}
});
checkSolution();
}
// 新游戏初始化
function newGame() {
// 简单示例数独(可替换为随机生成)
const sample = [
[5,3,0,0,7,0,0,0,0],
[6,0,0,1,9,5,0,0,0],
[0,9,8,0,0,0,0,6,0],
[8,0,0,0,6,0,0,0,3],
[4,0,0,8,0,3,0,0,1],
[7,0,0,0,2,0,0,0,6],
[0,6,0,0,0,0,2,8,0],
[0,0,0,4,1,9,0,0,5],
[0,0,0,0,8,0,0,7,9]
];
currentBoard = JSON.parse(JSON.stringify(sample));
initialBoard = JSON.parse(JSON.stringify(sample));
const cells = document.querySelectorAll('td');
cells.forEach((cell, index) => {
const row = Math.floor(index / 9);
const col = index % 9;
cell.textContent = sample[row][col] || '';
cell.className = '';
if (sample[row][col] !== 0) {
cell.classList.add('initial');
}
if (col % 3 === 2 && col !== 8) cell.classList.add('thick-right');
if (row % 3 === 2 && row !== 8) cell.classList.add('thick-bottom');
});
}
// 启动游戏
initializeBoard();
newGame();
</script>
</body>
</html> 这个就是之前版本的带编辑后 可以点击检视答案的,我只是让把显示动画的效果加到里面