1. 项目概述与核心思路
贪吃蛇作为经典游戏,其核心玩法简单却充满趣味性。使用HTML+jQuery实现Q版贪吃蛇,不仅能掌握前端基础技术,还能深入理解游戏开发的基本逻辑。这个项目特别适合前端初学者作为第一个完整的游戏开发实践。
选择jQuery而非原生JS主要考虑两点:一是jQuery的DOM操作和事件处理更简洁,二是其跨浏览器兼容性更好。游戏主体将采用div+CSS实现而非Canvas,这样更易于理解基础原理,后续升级为Canvas版本也会更顺畅。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础结构
2.1 HTML骨架搭建
首先创建标准的HTML5文档结构:
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Q版贪吃蛇</title>
<style>
body {
font-family: 'Arial Rounded MT Bold', sans-serif;
background-color: #f0f8ff;
text-align: center;
}
#game-container {
width: 400px;
height: 400px;
margin: 20px auto;
position: relative;
background-color: #e6f7ff;
border: 3px solid #4da6ff;
border-radius: 10px;
overflow: hidden;
}
</style>
</head>
<body>
<h1>🐍 Q版贪吃蛇 🐍</h1>
<div id="game-container"></div>
<p>得分: <span id="score">0</span></p>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="game.js"></script>
</body>
</html>
2.2 jQuery引入与初始化
从CDN引入jQuery 3.6.0版本,这是目前稳定且兼容性最好的版本。在game.js中,我们首先定义游戏的基本参数:
javascript复制$(document).ready(function() {
// 游戏配置
const config = {
gridSize: 20, // 网格大小(px)
rows: 20, // 行数
cols: 20, // 列数
speed: 150, // 初始速度(ms)
colors: {
snake: '#4CAF50',
head: '#2E7D32',
food: '#FF5252'
}
};
// 游戏状态
let gameState = {
snake: [],
direction: 'right',
food: null,
score: 0,
timer: null,
isPaused: false
};
initializeGame();
});
3. 核心游戏逻辑实现
3.1 蛇的移动与控制
蛇身使用一个数组来存储每个节点的坐标,移动时在数组头部添加新位置,尾部删除旧位置:
javascript复制function moveSnake() {
if (gameState.isPaused) return;
const head = {...gameState.snake[0]};
// 根据当前方向计算新头部位置
switch(gameState.direction) {
case 'up': head.y--; break;
case 'down': head.y++; break;
case 'left': head.x--; break;
case 'right': head.x++; break;
}
// 检查碰撞
if (checkCollision(head)) {
gameOver();
return;
}
// 添加新头部
gameState.snake.unshift(head);
// 检查是否吃到食物
if (head.x === gameState.food.x && head.y === gameState.food.y) {
updateScore();
createFood();
} else {
// 没吃到食物则移除尾部
const tail = gameState.snake.pop();
$(`.snake-part[data-x="${tail.x}"][data-y="${tail.y}"]`).remove();
}
renderSnake();
}
// 键盘控制
$(document).keydown(function(e) {
if (gameState.timer === null) return;
switch(e.key) {
case 'ArrowUp':
if (gameState.direction !== 'down') gameState.direction = 'up';
break;
case 'ArrowDown':
if (gameState.direction !== 'up') gameState.direction = 'down';
break;
case 'ArrowLeft':
if (gameState.direction !== 'right') gameState.direction = 'left';
break;
case 'ArrowRight':
if (gameState.direction !== 'left') gameState.direction = 'right';
break;
case ' ':
togglePause();
break;
}
});
3.2 食物生成与碰撞检测
食物的生成需要考虑不能出现在蛇身上:
javascript复制function createFood() {
let foodPos;
const maxAttempts = 100;
let attempts = 0;
do {
foodPos = {
x: Math.floor(Math.random() * config.cols),
y: Math.floor(Math.random() * config.rows)
};
attempts++;
} while (
gameState.snake.some(part => part.x === foodPos.x && part.y === foodPos.y) &&
attempts < maxAttempts
);
if (attempts >= maxAttempts) {
// 找不到合适位置,可能是蛇已占满空间
victory();
return;
}
gameState.food = foodPos;
// 移除旧食物
$('#game-container .food').remove();
// 创建新食物
$('<div>')
.addClass('food')
.css({
width: config.gridSize - 2,
height: config.gridSize - 2,
left: foodPos.x * config.gridSize,
top: foodPos.y * config.gridSize,
backgroundColor: config.colors.food,
borderRadius: '50%',
position: 'absolute'
})
.attr('data-x', foodPos.x)
.attr('data-y', foodPos.y)
.appendTo('#game-container');
}
function checkCollision(head) {
// 边界检查
if (head.x < 0 || head.x >= config.cols ||
head.y < 0 || head.y >= config.rows) {
return true;
}
// 自身碰撞检查(跳过头部)
for (let i = 1; i < gameState.snake.length; i++) {
if (gameState.snake[i].x === head.x && gameState.snake[i].y === head.y) {
return true;
}
}
return false;
}
4. 游戏界面渲染与交互
4.1 蛇的渲染优化
使用CSS过渡效果让移动更平滑:
javascript复制function renderSnake() {
// 先移除所有蛇身元素(简化实现)
$('#game-container .snake-part').remove();
gameState.snake.forEach((part, index) => {
const isHead = index === 0;
$('<div>')
.addClass('snake-part')
.css({
width: config.gridSize - (isHead ? 0 : 2),
height: config.gridSize - (isHead ? 0 : 2),
left: part.x * config.gridSize,
top: part.y * config.gridSize,
backgroundColor: isHead ? config.colors.head : config.colors.snake,
borderRadius: isHead ? '5px' : '3px',
position: 'absolute',
zIndex: isHead ? 2 : 1,
transition: 'all 0.1s ease-out'
})
.attr('data-x', part.x)
.attr('data-y', part.y)
.appendTo('#game-container');
});
}
4.2 游戏控制与状态管理
实现开始、暂停、重新开始等功能:
javascript复制function startGame() {
// 初始化蛇身
gameState.snake = [
{x: 5, y: 10},
{x: 4, y: 10},
{x: 3, y: 10}
];
gameState.direction = 'right';
gameState.score = 0;
gameState.isPaused = false;
$('#score').text('0');
$('#game-container').empty();
createFood();
renderSnake();
// 启动游戏循环
gameState.timer = setInterval(moveSnake, config.speed);
}
function togglePause() {
gameState.isPaused = !gameState.isPaused;
if (gameState.isPaused) {
$('#game-container').append(
$('<div>').addClass('pause-overlay').text('已暂停 - 按空格键继续')
);
} else {
$('#game-container .pause-overlay').remove();
}
}
function gameOver() {
clearInterval(gameState.timer);
gameState.timer = null;
$('#game-container').append(
$('<div>')
.addClass('game-over')
.html('<h2>游戏结束!</h2><p>最终得分: ' + gameState.score + '</p><button id="restart">再玩一次</button>')
.css({
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0,0,0,0.7)',
color: 'white',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
zIndex: 10
})
);
$('#restart').click(startGame);
}
function victory() {
clearInterval(gameState.timer);
gameState.timer = null;
$('#game-container').append(
$('<div>')
.addClass('victory')
.html('<h2>恭喜通关!</h2><p>你吃满了整个屏幕!</p><button id="restart">再玩一次</button>')
.css({
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(76,175,80,0.7)',
color: 'white',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
zIndex: 10
})
);
$('#restart').click(startGame);
}
5. 进阶功能与优化建议
5.1 难度动态调整
随着分数增加提高游戏速度:
javascript复制function updateScore() {
gameState.score += 10;
$('#score').text(gameState.score);
// 每100分加速一次
if (gameState.score % 100 === 0) {
config.speed = Math.max(50, config.speed - 10);
clearInterval(gameState.timer);
gameState.timer = setInterval(moveSnake, config.speed);
}
}
5.2 移动端适配
添加触摸控制支持:
javascript复制// 在initializeGame中添加
$('#game-container').on('swipeleft', function() {
if (gameState.direction !== 'right') gameState.direction = 'left';
}).on('swiperight', function() {
if (gameState.direction !== 'left') gameState.direction = 'right';
}).on('swipeup', function() {
if (gameState.direction !== 'down') gameState.direction = 'up';
}).on('swipedown', function() {
if (gameState.direction !== 'up') gameState.direction = 'down';
});
// 需要引入jQuery Mobile或类似库支持触摸事件
5.3 本地存储高分记录
javascript复制function updateScore() {
gameState.score += 10;
$('#score').text(gameState.score);
// 更新最高分
const highScore = localStorage.getItem('snakeHighScore') || 0;
if (gameState.score > highScore) {
localStorage.setItem('snakeHighScore', gameState.score);
$('#high-score').text(gameState.score);
}
// 难度调整...
}
// 在HTML中添加显示最高分的元素
6. 完整源码与部署建议
将所有代码整合后,完整的game.js内容如下:
javascript复制$(document).ready(function() {
// 游戏配置
const config = {
gridSize: 20,
rows: 20,
cols: 20,
speed: 150,
colors: {
snake: '#4CAF50',
head: '#2E7D32',
food: '#FF5252'
}
};
// 游戏状态
let gameState = {
snake: [],
direction: 'right',
food: null,
score: 0,
timer: null,
isPaused: false
};
// 初始化游戏
function initializeGame() {
// 显示最高分
const highScore = localStorage.getItem('snakeHighScore') || 0;
$('body').append('<p>最高分: <span id="high-score">' + highScore + '</span></p>');
// 添加开始按钮
$('#game-container').before('<button id="start-btn">开始游戏</button>');
$('#start-btn').click(startGame);
}
function startGame() {
// 初始化蛇身
gameState.snake = [
{x: 5, y: 10},
{x: 4, y: 10},
{x: 3, y: 10}
];
gameState.direction = 'right';
gameState.score = 0;
gameState.isPaused = false;
$('#score').text('0');
$('#game-container').empty();
$('#start-btn').remove();
createFood();
renderSnake();
// 启动游戏循环
gameState.timer = setInterval(moveSnake, config.speed);
}
// ...(之前的所有函数实现)
initializeGame();
});
部署建议:
- 将HTML和JS文件放在同一目录下
- 可以直接在浏览器中打开HTML文件本地运行
- 要部署到网站,只需上传这两个文件即可
- 考虑添加favicon.ico改善用户体验
这个Q版贪吃蛇游戏完整实现了经典玩法,并加入了暂停、难度调整、最高分记录等增强功能。代码结构清晰,注释完整,非常适合作为jQuery学习的实践项目。通过这个项目,你可以掌握:
- jQuery的DOM操作和事件处理
- 游戏循环的基本原理
- 键盘事件处理
- CSS动画与定位
- 本地存储的使用
