<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>15拼图游戏</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
color: #333;
}
.container {
background-color: rgba(255, 255, 255, 0.95);
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
padding: 30px;
max-width: 500px;
width: 100%;
text-align: center;
}
h1 {
color: #2c3e50;
margin-bottom: 20px;
font-size: 28px;
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
}
.instructions {
background-color: #f8f9fa;
border-left: 4px solid #3498db;
padding: 15px;
margin: 20px 0;
text-align: left;
border-radius: 0 8px 8px 0;
font-size: 15px;
}
.game-board {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 8px;
margin: 25px auto;
max-width: 350px;
}
.tile {
aspect-ratio: 1;
background: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 3px 6px rgba(0,0,0,0.1);
user-select: none;
}
.tile:hover {
transform: scale(1.03);
background: #2980b9;
}
.empty {
background: #ecf0f1;
box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
}
.empty:hover {
background: #ecf0f1;
transform: none;
cursor: default;
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
margin: 20px 0;
}
button {
background: #2ecc71;
color: white;
border: none;
padding: 12px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: all 0.2s;
box-shadow: 0 3px 6px rgba(0,0,0,0.1);
}
button:hover {
background: #27ae60;
transform: translateY(-2px);
}
button#reset {
background: #e74c3c;
}
button#reset:hover {
background: #c0392b;
}
.message {
margin-top: 20px;
padding: 15px;
border-radius: 8px;
font-weight: bold;
display: none;
}
.success {
background-color: #d4edda;
color: #155724;
display: block;
animation: fadeIn 0.5s;
}
.key-hint {
margin-top: 15px;
font-size: 14px;
color: #7f8c8d;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@media (max-width: 480px) {
.container {
padding: 20px;
}
.game-board {
max-width: 300px;
}
.tile {
font-size: 20px;
}
button {
padding: 10px 15px;
font-size: 14px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>15拼图游戏</h1>
<div class="instructions">
<p>在4×4的16个格中随机填上1-15的数字,剩下一个格为空。</p>
<p>使用方向键或点击移动空格旁的数字,最终形成以下图案为过关:</p>
<p>1 2 3 4<br>5 6 7 8<br>9 10 11 12<br>13 14 15</p>
</div>
<div class="game-board" id="gameBoard">
<!-- 拼图块将通过JavaScript动态生成 -->
</div>
<div class="controls">
<button id="newGame">新游戏</button>
<button id="reset">重置</button>
</div>
<div class="message" id="message"></div>
<div class="key-hint">
使用键盘方向键 ↑ ↓ ← → 也可以移动数字
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const gameBoard = document.getElementById('gameBoard');
const newGameBtn = document.getElementById('newGame');
const resetBtn = document.getElementById('reset');
const messageDiv = document.getElementById('message');
let board = [];
let emptyPos = {row: 3, col: 3}; // 空格位置
let initialBoard = []; // 存储初始状态用于重置
// 初始化游戏
function initGame() {
// 创建1-15的数字数组
let numbers = Array.from({length: 15}, (_, i) => i + 1);
// 随机打乱数组(Fisher-Yates洗牌算法)
for (let i = numbers.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
// 初始化4x4游戏板
board = [];
let index = 0;
for (let i = 0; i < 4; i++) {
board[i] = [];
for (let j = 0; j < 4; j++) {
if (i === 3 && j === 3) {
board[i][j] = 0; // 最后一个位置为空
emptyPos = {row: i, col: j};
} else {
board[i][j] = numbers[index++];
}
}
}
// 保存初始状态
initialBoard = JSON.parse(JSON.stringify(board));
renderBoard();
messageDiv.className = 'message';
}
// 渲染游戏板
function renderBoard() {
gameBoard.innerHTML = '';
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const tileValue = board[i][j];
const tile = document.createElement('div');
tile.className = tileValue === 0 ? 'tile empty' : 'tile';
tile.textContent = tileValue === 0 ? '' : tileValue;
tile.dataset.row = i;
tile.dataset.col = j;
// 添加点击事件
if (tileValue !== 0) {
tile.addEventListener('click', function() {
const row = parseInt(this.dataset.row);
const col = parseInt(this.dataset.col);
moveTile(row, col);
});
}
gameBoard.appendChild(tile);
}
}
}
// 移动拼图块
function moveTile(row, col) {
// 检查是否与空格相邻
if (
(Math.abs(row - emptyPos.row) === 1 && col === emptyPos.col) ||
(Math.abs(col - emptyPos.col) === 1 && row === emptyPos.row)
) {
// 交换位置
board[emptyPos.row][emptyPos.col] = board[row][col];
board[row][col] = 0;
emptyPos = {row, col};
renderBoard();
checkWin();
}
}
// 检查是否获胜
function checkWin() {
let expectedValue = 1;
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
// 跳过最后一个位置
if (i === 3 && j === 3) {
if (board[i][j] !== 0) return false;
} else {
if (board[i][j] !== expectedValue++) return false;
}
}
}
// 显示胜利消息
messageDiv.textContent = '恭喜!您成功完成了拼图!';
messageDiv.className = 'message success';
}
// 重置游戏
function resetGame() {
board = JSON.parse(JSON.stringify(initialBoard));
// 找到空格位置
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (board[i][j] === 0) {
emptyPos = {row: i, col: j};
break;
}
}
}
renderBoard();
messageDiv.className = 'message';
}
// 键盘控制
document.addEventListener('keydown', function(event) {
let newRow = emptyPos.row;
let newCol = emptyPos.col;
switch(event.key) {
case 'ArrowUp':
if (emptyPos.row < 3) newRow++;
break;
case 'ArrowDown':
if (emptyPos.row > 0) newRow--;
break;
case 'ArrowLeft':
if (emptyPos.col < 3) newCol++;
break;
case 'ArrowRight':
if (emptyPos.col > 0) newCol--;
break;
default:
return; // 如果不是方向键,不做任何事
}
if (newRow !== emptyPos.row || newCol !== emptyPos.col) {
moveTile(newRow, newCol);
}
});
// 按钮事件监听
newGameBtn.addEventListener('click', initGame);
resetBtn.addEventListener('click', resetGame);
// 初始化游戏
initGame();
});
</script>
</body>
</html>
index.html
style.css
index.js
index.html