贪吃蛇游戏

分数: 0

方向键控制蛇的移动,吃到食物得分,撞到边界或自己游戏结束

游戏分析与学习指南

玩法介绍

技术点分析

开发步骤

  1. 页面结构设计
    • 创建HTML文档,设置游戏标题和基本布局
    • 设计游戏容器、分数显示区域和控制按钮
  2. 样式设计
    • 设置页面背景、字体和颜色方案
    • 设计游戏容器、蛇身和食物的样式
    • 设置控制按钮的样式和悬停效果
  3. 游戏核心功能开发
    • 初始化游戏状态变量
    • 实现游戏初始化函数
    • 开发蛇的渲染函数
    • 实现食物生成算法
    • 开发蛇的移动逻辑
    • 实现碰撞检测功能
    • 添加键盘控制逻辑
  4. 游戏控制功能开发
    • 实现开始游戏功能
    • 实现暂停/恢复功能
    • 实现重新开始功能
  5. 测试与优化
    • 测试游戏逻辑的正确性
    • 修复可能的bug,如食物生成位置冲突等
    • 优化用户体验

代码主要结构

HTML结构

<!DOCTYPE html>
<html>
<head>
    <!-- 标题、元信息和CSS样式 -->
</head>
<body>
    <h1>贪吃蛇游戏</h1>
    <div id="score">分数: 0</div>
    <div id="game-container">
        <div id="snake"></div>
        <div id="food"></div>
    </div>
    <div class="controls">
        <!-- 控制按钮 -->
    </div>
    <!-- 游戏说明和分析 -->
    <script>
        <!-- JavaScript代码 -->
    </script>
</body>
</html>

JavaScript核心变量

// DOM元素引用
const snake, food, gameContainer, scoreElement;

// 游戏状态变量
let snakeSize, snakePos, foodPos, direction, gameLoop, score, isPaused;

核心函数

// 初始化游戏
function initGame() { ... }

// 生成食物
function generateFood() { ... }

// 渲染蛇
function renderSnake() { ... }

// 移动蛇
function moveSnake() { ... }

// 检查碰撞
function checkCollision(head) { ... }

// 游戏控制函数
function startGame() { ... }
function pauseGame() { ... }
function restartGame() { ... }

游戏逻辑流程

1. 初始化游戏状态
2. 生成初始食物
3. 启动游戏循环(setInterval)
4. 每次循环中:
   - 检查游戏是否暂停
   - 计算蛇头新位置
   - 检查碰撞
   - 更新蛇的位置
   - 检查是否吃到食物
   - 重新渲染蛇

完整代码示例

// DOM元素引用
const snake = document.getElementById('snake');
const food = document.getElementById('food');
const gameContainer = document.getElementById('game-container');
const scoreElement = document.getElementById('score');

// 游戏状态变量
let snakeSize = 20;
let snakePos = [{ x: 100, y: 100 }];
let foodPos = { x: 0, y: 0 };
let direction = { x: snakeSize, y: 0 };
let gameLoop;
let score = 0;
let isPaused = false;

// 初始化游戏
function initGame() {
    snakePos = [{ x: 100, y: 100 }];
    direction = { x: snakeSize, y: 0 };
    score = 0;
    scoreElement.textContent = `分数: ${score}`;
    generateFood();
    renderSnake();
}

// 生成食物
function generateFood() {
    const maxX = gameContainer.clientWidth - snakeSize;
    const maxY = gameContainer.clientHeight - snakeSize;
    foodPos.x = Math.floor(Math.random() * (maxX / snakeSize)) * snakeSize;
    foodPos.y = Math.floor(Math.random() * (maxY / snakeSize)) * snakeSize;
    // 避免食物生成在蛇身上
    if (snakePos.some(pos => pos.x === foodPos.x && pos.y === foodPos.y)) {
        generateFood();
    }
    food.style.left = `${foodPos.x}px`;
    food.style.top = `${foodPos.y}px`;
}

// 渲染蛇
function renderSnake() {
    snake.innerHTML = '';
    snakePos.forEach((pos, index) => {
        const segment = document.createElement('div');
        segment.style.position = 'absolute';
        segment.style.width = `${snakeSize}px`;
        segment.style.height = `${snakeSize}px`;
        segment.style.left = `${pos.x}px`;
        segment.style.top = `${pos.y}px`;
        segment.style.backgroundColor = index === 0 ? '#4CAF50' : '#8BC34A';
        segment.style.borderRadius = '3px';
        snake.appendChild(segment);
    });
}

// 移动蛇
function moveSnake() {
    if (isPaused) return;

    const head = { x: snakePos[0].x + direction.x, y: snakePos[0].y + direction.y };

    // 检查碰撞
    if (checkCollision(head)) {
        clearInterval(gameLoop);
        alert(`游戏结束!最终分数: ${score}`);
        return;
    }

    snakePos.unshift(head);

    // 检查是否吃到食物
    if (head.x === foodPos.x && head.y === foodPos.y) {
        score += 10;
        scoreElement.textContent = `分数: ${score}`;
        generateFood();
    } else {
        snakePos.pop();
    }

    renderSnake();
}

// 检查碰撞
function checkCollision(head) {
    // 边界碰撞
    if (head.x < 0 || head.x >= gameContainer.clientWidth ||
        head.y < 0 || head.y >= gameContainer.clientHeight) {
        return true;
    }
    // 自身碰撞
    return snakePos.slice(1).some(pos => pos.x === head.x && pos.y === head.y);
}

// 控制方向
document.addEventListener('keydown', (e) => {
    switch (e.key) {
        case 'ArrowUp':
            if (direction.y === 0) direction = { x: 0, y: -snakeSize };
            break;
        case 'ArrowDown':
            if (direction.y === 0) direction = { x: 0, y: snakeSize };
            break;
        case 'ArrowLeft':
            if (direction.x === 0) direction = { x: -snakeSize, y: 0 };
            break;
        case 'ArrowRight':
            if (direction.x === 0) direction = { x: snakeSize, y: 0 };
            break;
    }
});

// 游戏控制函数
function startGame() {
    if (gameLoop) clearInterval(gameLoop);
    isPaused = false;
    gameLoop = setInterval(moveSnake, 150);
}

function pauseGame() {
    isPaused = !isPaused;
}

function restartGame() {
    clearInterval(gameLoop);
    initGame();
}

// 初始化
initGame();