您只需要将下面的代码复制到一个文本编辑器中,保存为 snake.html 文件,然后用浏览器打开这个文件即可开始游戏。

网页制作贪吃蛇游戏代码
(图片来源网络,侵删)

完整代码 (snake.html)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">贪吃蛇游戏</title>
    <style>
        /* 基础样式重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: 'Arial', sans-serif;
            background: linear-gradient(135deg, #1e3c72, #2a5298);
            color: #fff;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            flex-direction: column;
        }
        /* 游戏容器 */
        .game-container {
            text-align: center;
            background: rgba(0, 0, 0, 0.3);
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
        }
        h1 {
            margin-bottom: 20px;
            font-size: 2.5em;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
        }
        /* 游戏信息栏 */
        .game-info {
            display: flex;
            justify-content: space-between;
            margin-bottom: 15px;
            font-size: 1.2em;
            max-width: 400px;
        }
        /* 游戏画布 */
        #gameCanvas {
            border: 3px solid #fff;
            border-radius: 10px;
            background-color: #111;
            box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);
        }
        /* 控制按钮 */
        .controls {
            margin-top: 20px;
        }
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 12px 24px;
            font-size: 16px;
            border-radius: 8px;
            cursor: pointer;
            margin: 0 10px;
            transition: background-color 0.3s, transform 0.1s;
        }
        button:hover {
            background-color: #45a049;
        }
        button:active {
            transform: scale(0.98);
        }
        /* 游戏结束覆盖层 */
        .game-over {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.8);
            padding: 30px;
            border-radius: 10px;
            text-align: center;
            display: none; /* 默认隐藏 */
        }
        .game-over h2 {
            color: #ff4757;
            margin-bottom: 15px;
        }
        /* 移动端控制按钮 */
        .mobile-controls {
            display: none; /* 默认隐藏 */
            margin-top: 20px;
            grid-template-columns: repeat(3, 60px);
            grid-template-rows: repeat(3, 60px);
            gap: 5px;
            justify-content: center;
        }
        .mobile-controls button {
            width: 60px;
            height: 60px;
            font-size: 24px;
            padding: 0;
        }
        .mobile-controls button:nth-child(2) { grid-column: 2; grid-row: 1; } /* 上 */
        .mobile-controls button:nth-child(3) { grid-column: 1; grid-row: 2; } /* 左 */
        .mobile-controls button:nth-child(4) { grid-column: 3; grid-row: 2; } /* 右 */
        .mobile-controls button:nth-child(5) { grid-column: 2; grid-row: 3; } /* 下 */
        /* 响应式设计:当屏幕宽度小于600px时显示移动端控制 */
        @media (max-width: 600px) {
            .mobile-controls {
                display: grid;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>贪吃蛇</h1>
        <div class="game-info">
            <div>得分: <span id="score">0</span></div>
            <div>最高分: <span id="highScore">0</span></div>
        </div>
        <canvas id="gameCanvas" width="400" height="400"></canvas>
        <div class="controls">
            <button id="startBtn">开始游戏</button>
            <button id="pauseBtn">暂停</button>
        </div>
        <div class="mobile-controls">
            <button id="upBtn">↑</button>
            <button id="leftBtn">←</button>
            <button id="rightBtn">→</button>
            <button id="downBtn">↓</button>
        </div>
    </div>
    <div class="game-over" id="gameOverScreen">
        <h2>游戏结束!</h2>
        <p>你的得分是: <span id="finalScore">0</span></p>
        <button id="restartBtn">重新开始</button>
    </div>
    <script>
        // 游戏配置
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const scoreElement = document.getElementById('score');
        const highScoreElement = document.getElementById('highScore');
        const finalScoreElement = document.getElementById('finalScore');
        const gameOverScreen = document.getElementById('gameOverScreen');
        // 游戏设置
        const gridSize = 20; // 网格大小
        const tileCount = canvas.width / gridSize; // 网格数量 (20x20)
        let snake = [
            {x: 10, y: 10} // 蛇的初始位置
        ];
        let food = {};
        let dx = 0; // x轴方向移动速度
        let dy = 0; // y轴方向移动速度
        let score = 0;
        let highScore = localStorage.getItem('snakeHighScore') || 0;
        let gameRunning = false;
        let gamePaused = false;
        highScoreElement.textContent = highScore;
        // 生成食物
        function generateFood() {
            food = {
                x: Math.floor(Math.random() * tileCount),
                y: Math.floor(Math.random() * tileCount)
            };
            // 确保食物不会生成在蛇身上
            for (let segment of snake) {
                if (segment.x === food.x && segment.y === food.y) {
                    generateFood(); // 如果重叠,递归调用直到找到合适位置
                    return;
                }
            }
        }
        // 绘制游戏元素
        function drawGame() {
            // 清空画布
            ctx.fillStyle = '#111';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            // 绘制蛇
            ctx.fillStyle = '#4CAF50'; // 蛇的颜色
            for (let segment of snake) {
                ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize - 2, gridSize - 2);
            }
            // 绘制蛇头(用不同颜色)
            ctx.fillStyle = '#8BC34A';
            ctx.fillRect(snake[0].x * gridSize, snake[0].y * gridSize, gridSize - 2, gridSize - 2);
            // 绘制食物
            ctx.fillStyle = '#ff4757'; // 食物的颜色
            ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize - 2, gridSize - 2);
        }
        // 移动蛇
        function moveSnake() {
            const head = {x: snake[0].x + dx, y: snake[0].y + dy};
            snake.unshift(head); // 在蛇头添加一个新的头部
            // 检查是否吃到食物
            if (head.x === food.x && head.y === food.y) {
                score += 10;
                scoreElement.textContent = score;
                generateFood();
            } else {
                snake.pop(); // 如果没吃到,移除蛇尾
            }
        }
        // 检查游戏是否结束
        function checkGameOver() {
            const head = snake[0];
            // 1. 撞墙检测
            if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
                return true;
            }
            // 2. 撞到自己检测
            for (let i = 1; i < snake.length; i++) {
                if (head.x === snake[i].x && head.y === snake[i].y) {
                    return true;
                }
            }
            return false;
        }
        // 游戏主循环
        function gameLoop() {
            if (!gameRunning || gamePaused) return;
            moveSnake();
            if (checkGameOver()) {
                gameOver();
                return;
            }
            drawGame();
            setTimeout(gameLoop, 100); // 控制游戏速度
        }
        // 游戏结束逻辑
        function gameOver() {
            gameRunning = false;
            finalScoreElement.textContent = score;
            gameOverScreen.style.display = 'block';
            // 更新最高分
            if (score > highScore) {
                highScore = score;
                highScoreElement.textContent = highScore;
                localStorage.setItem('snakeHighScore', highScore);
            }
        }
        // 开始游戏
        function startGame() {
            snake = [{x: 10, y: 10}];
            dx = 0;
            dy = 0;
            score = 0;
            scoreElement.textContent = score;
            generateFood();
            gameRunning = true;
            gamePaused = false;
            gameOverScreen.style.display = 'none';
            gameLoop();
        }
        // 暂停/继续游戏
        function togglePause() {
            if (!gameRunning) return;
            gamePaused = !gamePaused;
            if (!gamePaused) {
                gameLoop();
            }
        }
        // 键盘控制
        document.addEventListener('keydown', (e) => {
            if (!gameRunning || gamePaused) return;
            // 防止蛇直接掉头
            switch(e.key) {
                case 'ArrowUp':
                    if (dy !== 1) { dx = 0; dy = -1; }
                    break;
                case 'ArrowDown':
                    if (dy !== -1) { dx = 0; dy = 1; }
                    break;
                case 'ArrowLeft':
                    if (dx !== 1) { dx = -1; dy = 0; }
                    break;
                case 'ArrowRight':
                    if (dx !== -1) { dx = 1; dy = 0; }
                    break;
            }
        });
        // 移动端按钮控制
        document.getElementById('upBtn').addEventListener('click', () => { if (gameRunning && !gamePaused && dy !== 1) { dx = 0; dy = -1; } });
        document.getElementById('downBtn').addEventListener('click', () => { if (gameRunning && !gamePaused && dy !== -1) { dx = 0; dy = 1; } });
        document.getElementById('leftBtn').addEventListener('click', () => { if (gameRunning && !gamePaused && dx !== 1) { dx = -1; dy = 0; } });
        document.getElementById('rightBtn').addEventListener('click', () => { if (gameRunning && !gamePaused && dx !== -1) { dx = 1; dy = 0; } });
        // 按钮事件监听
        document.getElementById('startBtn').addEventListener('click', startGame);
        document.getElementById('pauseBtn').addEventListener('click', togglePause);
        document.getElementById('restartBtn').addEventListener('click', startGame);
        // 初始绘制
        drawGame();
    </script>
</body>
</html>

代码结构解析

这个贪吃蛇游戏主要由三部分构成:HTML、CSS 和 JavaScript。

HTML 结构

  • <canvas>: 这是游戏的核心画布,所有的图形(蛇、食物)都将在这里被绘制。
  • <div> 容器: 用于包裹游戏界面,包括标题、得分显示、控制按钮等,方便进行样式布局。
  • <button>: 提供了“开始游戏”、“暂停”和“重新开始”的功能。
  • <span>: 用于动态显示当前得分和最高分。
  • <div class="game-over">: 游戏结束时显示的弹窗,覆盖在游戏画布上。

CSS 样式

  • 整体布局: 使用 flexbox 将游戏容器居中显示,并设置了一个漂亮的渐变背景。
  • 画布样式: 给 canvas 添加了白色边框和圆角,使其看起来像一个独立的游戏区域。
  • 按钮样式: 设计了有悬停和点击效果的按钮,提升用户体验。
  • 响应式设计: 通过 @media 查询,在屏幕宽度较小时(如手机)显示虚拟方向键,方便触摸操作。

JavaScript 游戏逻辑

这是游戏最核心的部分,负责处理所有的游戏行为。

  • 变量定义:

    • snake: 一个数组,存储蛇身体的每一节坐标。[{x:10, y:10}, {x:9, y:10}] 表示一个两节长的蛇。
    • food: 一个对象,存储食物的坐标。
    • dx, dy: 控制蛇的移动方向。dx=1, dy=0 表示向右移动。
    • score, highScore: 记录当前得分和历史最高分,最高分使用 localStorage 保存,这样即使刷新页面也不会丢失。
  • 核心函数:

    网页制作贪吃蛇游戏代码
    (图片来源网络,侵删)
    • generateFood(): 随机生成食物的坐标,并确保不会生成在蛇身上。
    • drawGame(): 清空画布,然后分别绘制蛇和食物。
    • moveSnake(): 根据当前方向 dx, dy 计算新的蛇头位置,并将其添加到蛇身体数组的开头,如果蛇头碰到食物,则身体增长(不删除尾部);否则,删除蛇尾。
    • `checkGameOver()**: 检查游戏是否结束,条件有两个:蛇头是否撞到墙壁,或者蛇头是否撞到了自己的身体。
    • gameLoop(): 游戏的主循环,它调用 moveSnake()drawGame(),并使用 setTimeout 来控制游戏速度(每100毫秒执行一次)。
    • startGame() / gameOver() / togglePause(): 控制游戏状态(开始、结束、暂停)的函数。
  • 事件监听:

    • 键盘事件: 监听键盘的上下左右箭头键,来改变蛇的移动方向,代码中加入了防止蛇直接掉头的逻辑。
    • 按钮事件: 监听“开始”、“暂停”等按钮的点击事件,调用相应的游戏控制函数。

如何运行和修改

  1. 运行: 将上述全部代码复制到一个名为 snake.html 的文件中,然后用 Chrome、Firefox 等任何现代浏览器打开它即可。
  2. 修改:
    • 改变游戏速度: 修改 gameLoop 函数中的 setTimeout 的延迟时间,数值越小,游戏速度越快。
    • 改变颜色: 在 CSS 的 drawGame 函数中修改 fillStyle 的值,或在 HTML 的 <style> 部分修改对应的 CSS 类。
    • 改变画布大小: 修改 <canvas>widthheight 属性,同时也要相应调整 gridSizetileCount 变量,以确保网格划分正确。

这个贪吃蛇游戏代码结构清晰,功能完整,并且具有良好的用户界面,是学习和实践网页游戏开发的绝佳范例。

网页制作贪吃蛇游戏代码
(图片来源网络,侵删)