|
|
以下是基于HTML5+CSS3+JavaScript的贪吃蛇游戏完整实现,包含游戏控制、计分系统和响应式设计:
html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>经典贪吃蛇</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* CSS内容将放在单独文件中 */
</style>
</head>
<body>
<div class="game-container">
<h1>???? 贪吃蛇大冒险</h1>
<div class="game-info">
<span id="score">得分: 0</span>
<span id="high-score">最高分: 0</span>
<button id="start-btn"><i class="fas fa-play"></i> 开始</button>
</div>
<canvas id="game-canvas" width="400" height="400"></canvas>
<div class="controls">
<p>使用 <i class="fas fa-arrow-up"></i><i class="fas fa-arrow-down"></i><i class="fas fa-arrow-left"></i><i class="fas fa-arrow-right"></i> 控制方向</p>
<p>按空格键暂停/继续</p>
</div>
</div>
<script src="game.js"></script>
</body>
</html>l:
css:
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.game-container {
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
padding: 2rem;
text-align: center;
max-width: 500px;
width: 90%;
}
h1 {
color: #2c3e50;
margin-bottom: 1.5rem;
}
#game-canvas {
border: 2px solid #3498db;
border-radius: 8px;
background-color: #ecf0f1;
display: block;
margin: 0 auto;
}
.game-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
padding: 0.5rem 1rem;
background: #f8f9fa;
border-radius: 8px;
}
button {
background: #3498db;
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s;
}
button:hover {
background: #2980b9;
transform: translateY(-2px);
}
.controls {
margin-top: 1rem;
color: #7f8c8d;
font-size: 0.9rem;
}
js:
document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const highScoreDisplay = document.getElementById('high-score');
const startBtn = document.getElementById('start-btn');
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let speed = 7;
let snake = [{x: 10, y: 10}];
let food = {x: 5, y: 5};
let direction = {x: 0, y: 0};
let lastDirection = {x: 0, y: 0};
let score = 0;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let gameRunning = false;
let gamePaused = false;
let gameLoop;
highScoreDisplay.textContent = `最高分: ${highScore}`;
function drawGame() {
// 清空画布
ctx.fillStyle = '#ecf0f1';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制蛇
snake.forEach((segment, index) => {
ctx.fillStyle = index === 0 ? '#2ecc71' : '#27ae60';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
ctx.strokeStyle = '#fff';
ctx.strokeRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
});
// 绘制食物
ctx.fillStyle = '#e74c3c';
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize/2,
food.y * gridSize + gridSize/2,
gridSize/2,
0,
Math.PI * 2
);
ctx.fill();
}
function moveSnake() {
const head = {x: snake[0].x + direction.x, y: snake[0].y + direction.y};
// 检查是否撞墙
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
gameOver();
return;
}
// 检查是否撞到自己
for (let i = 1; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver();
return;
}
}
// 移动蛇
snake.unshift(head);
// 检查是否吃到食物
if (head.x === food.x && head.y === food.y) {
score += 10;
scoreDisplay.textContent = `得分: ${score}`;
generateFood();
} else {
snake.pop();
}
}
function generateFood() {
let validPosition = false;
while (!validPosition) {
food = {
x: Math.floor(Math.random() * tileCount),
y: Math.floor(Math.random() * tileCount)
};
validPosition = true;
// 确保食物不会出现在蛇身上
for (let segment of snake) {
if (segment.x === food.x && segment.y === food.y) {
validPosition = false;
break;
}
}
}
}
function gameOver() {
clearInterval(gameLoop);
gameRunning = false;
startBtn.innerHTML = '<i class="fas fa-redo"></i> 重新开始';
if (score > highScore) {
highScore = score;
localStorage.setItem('snakeHighScore', highScore);
highScoreDisplay.textContent = `最高分: ${highScore}`;
}
alert(`游戏结束! 你的得分是: ${score}`);
}
function startGame() {
if (gameRunning) return;
snake = [{x: 10, y: 10}];
direction = {x: 0, y: 0};
lastDirection = {x: 0, y: 0};
score = 0;
scoreDisplay.textContent = `得分: ${score}`;
generateFood();
gameRunning = true;
gamePaused = false;
startBtn.innerHTML = '<i class="fas fa-pause"></i> 暂停';
gameLoop = setInterval(() => {
if (!gamePaused) {
moveSnake();
drawGame();
}
}, 1000 / speed);
}
function togglePause() {
if (!gameRunning) return;
gamePaused = !gamePaused;
startBtn.innerHTML = gamePaused
? '<i class="fas fa-play"></i> 继续'
: '<i class="fas fa-pause"></i> 暂停';
}
// 事件监听
startBtn.addEventListener('click', () => {
if (gameRunning && !gamePaused) {
togglePause();
} else {
startGame();
}
});
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
// 防止180度转弯
switch(e.key) {
case 'ArrowUp':
if (lastDirection.y !== 0) return;
direction = {x: 0, y: -1};
break;
case 'ArrowDown':
if (lastDirection.y !== 0) return;
direction = {x: 0, y: 1};
break;
case 'ArrowLeft':
if (lastDirection.x !== 0) return;
direction = {x: -1, y: 0};
break;
case 'ArrowRight':
if (lastDirection.x !== 0) return;
direction = {x: 1, y: 0};
break;
case ' ':
togglePause();
break;
}
lastDirection = {...direction};
});
// 初始绘制
drawGame();
});
|
|