科学教育

标题: 廖晗瑞 [打印本页]

作者: 廖晗瑞    时间: 2024-8-14 18:58
标题: 廖晗瑞
帮我做一个完善的贪吃蛇游戏
作者: kaia    时间: 2024-8-14 18:59
当然可以!让我们一起做一个简单又有趣的贪吃蛇游戏吧。在此之前,你需要一些网页编程的基础知识,比如HTML、CSS和JavaScript。如果你还不熟悉它们,不用担心,我会尽量一步一步讲解,帮助你理解。

### 第一步:创建基本的HTML结构
首先,我们需要创建一个HTML文件,让我们的网页有一个基本的结构。

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>贪吃蛇游戏</title>
  6.     <style>
  7.         /* 我们后面会在这里写CSS样式 */
  8.     </style>
  9. </head>
  10. <body>
  11.     <h1>贪吃蛇游戏</h1>
  12.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  13.     <script>
  14.         // 我们后面会在这里写JavaScript代码
  15.     </script>
  16. </body>
  17. </html>
复制代码


在这个HTML文件中,我们添加了一个`<canvas>`标签,这将是游戏的画布。接下来,我们会使用JavaScript在这个画布上绘制贪吃蛇游戏。

### 第二步:添加CSS样式
我们可以先给画布一些简单的样式,让它看起来美观一些。

  1. <style>
  2.     body {
  3.         display: flex;
  4.         justify-content: center;
  5.         align-items: center;
  6.         height: 100vh;
  7.         margin: 0;
  8.         font-family: Arial, sans-serif;
  9.         background-color: #f0f0f0;
  10.     }
  11.     #gameCanvas {
  12.         border: 1px solid #000;
  13.         background-color: #fff;
  14.     }
  15. </style>
复制代码


这段CSS代码会让画布在页面中居中显示,并赋予它一个边框和白色背景。

### 第三步:编写JavaScript代码
JavaScript是贪吃蛇游戏的核心部分,我们会在这里实现游戏逻辑。

  1. <script>
  2.     const canvas = document.getElementById('gameCanvas');
  3.     const context = canvas.getContext('2d');

  4.     const box = 20;
  5.     let snake = [];
  6.     snake[0] = { x: 9 * box, y: 10 * box };

  7.     let food = {
  8.         x: Math.floor(Math.random() * 19 + 1) * box,
  9.         y: Math.floor(Math.random() * 19 + 1) * box
  10.     }

  11.     let score = 0;

  12.     let d;

  13.     document.addEventListener('keydown', direction);

  14.     function direction(event) {
  15.         if (event.keyCode == 37 && d != 'RIGHT') {
  16.             d = 'LEFT';
  17.         } else if (event.keyCode == 38 && d != 'DOWN') {
  18.             d = 'UP';
  19.         } else if (event.keyCode == 39 && d != 'LEFT') {
  20.             d = 'RIGHT';
  21.         } else if (event.keyCode == 40 && d != 'UP') {
  22.             d = 'DOWN';
  23.         }
  24.     }

  25.     function collision(newHead, array) {
  26.         for (let i = 0; i < array.length; i++) {
  27.             if (newHead.x == array[i].x && newHead.y == array[i].y) {
  28.                 return true;
  29.             }
  30.         }
  31.         return false;
  32.     }

  33.     function draw() {
  34.         context.clearRect(0, 0, canvas.width, canvas.height);

  35.         for (let i = 0; i < snake.length; i++) {
  36.             context.fillStyle = (i == 0) ? 'green' : 'black';
  37.             context.fillRect(snake[i].x, snake[i].y, box, box);
  38.         }

  39.         context.fillStyle = 'red';
  40.         context.fillRect(food.x, food.y, box, box);

  41.         let snakeX = snake[0].x;
  42.         let snakeY = snake[0].y;

  43.         if (d == 'LEFT') snakeX -= box;
  44.         if (d == 'UP') snakeY -= box;
  45.         if (d == 'RIGHT') snakeX += box;
  46.         if (d == 'DOWN') snakeY += box;

  47.         if (snakeX == food.x && snakeY == food.y) {
  48.             score++;
  49.             food = {
  50.                 x: Math.floor(Math.random() * 19 + 1) * box,
  51.                 y: Math.floor(Math.random() * 19 + 1) * box
  52.             }
  53.         } else {
  54.             snake.pop();
  55.         }

  56.         let newHead = {
  57.             x: snakeX,
  58.             y: snakeY
  59.         }

  60.         if (snakeX < 0 || snakeY < 0 || snakeX >= 400 || snakeY >= 400 || collision(newHead, snake)) {
  61.             clearInterval(game);
  62.             alert('游戏结束');
  63.         }

  64.         snake.unshift(newHead);

  65.         context.fillStyle = 'black';
  66.         context.font = '20px Arial';
  67.         context.fillText('得分: ' + score, 5, canvas.height - 5);
  68.     }

  69.     let game = setInterval(draw, 100);
  70. </script>
复制代码


### 总结
通过以上的步骤,我们完成了一个简单的贪吃蛇游戏。你可以根据自己的兴趣和需求,进一步完善和改进游戏,比如添加开始界面、暂停功能等。希望你玩得开心,并从中学习到更多的编程知识!如果还有其他问题,欢迎随时提问哦!
作者: 廖晗瑞    时间: 2024-8-14 19:00
帮我再优化一点
作者: kaia    时间: 2024-8-14 19:00
廖晗瑞 发表于 2024-08-14 19:00
帮我再优化一点


好的!我们可以进行一些优化,使代码更加简洁、易读,同时增加一些功能和效果。让我们来逐步实现这些优化。

### 第一步:优化HTML结构
HTML部分基本保持不变,但我们可以为画布和样式添加一些更直观的注释和标签。确保我们的HTML文件结构清晰,便于维护和阅读。
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <style>
  8.         /* CSS 样式 */
  9.         body {
  10.             display: flex;
  11.             justify-content: center;
  12.             align-items: center;
  13.             height: 100vh;
  14.             margin: 0;
  15.             font-family: Arial, sans-serif;
  16.             background-color: #f0f0f0;
  17.         }
  18.         #gameCanvas {
  19.             border: 2px solid #000;
  20.             background-color: #fff;
  21.         }
  22.     </style>
  23. </head>
  24. <body>
  25.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  26.     <script>
  27.         // JavaScript 代码将在这里编写
  28.     </script>
  29. </body>
  30. </html>
复制代码


### 第二步:优化JavaScript代码
我们将对JavaScript代码进行优化,包括函数组织,变量命名以及逻辑结构。另外,我们可以增加一个开始界面,并在游戏结束后重新开始游戏。

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 设定每个格子的大小
  4. let snake = [
  5.     { x: 9 * box, y: 10 * box }
  6. ];
  7. let food = {
  8.     x: Math.floor(Math.random() * 19 + 1) * box,
  9.     y: Math.floor(Math.random() * 19 + 1) * box
  10. };

  11. let score = 0;
  12. let direction;

  13. // 添加事件监听器来控制蛇的移动方向
  14. document.addEventListener('keydown', changeDirection);

  15. function changeDirection(event) {
  16.     const keyPressed = event.keyCode;
  17.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  18.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  19.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  20.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  21. }

  22. function drawGame() {
  23.     context.clearRect(0, 0, canvas.width, canvas.height);

  24.     // 绘制蛇
  25.     for (let i = 0; i < snake.length; i++) {
  26.         context.fillStyle = i === 0 ? 'green' : 'black';
  27.         context.fillRect(snake[i].x, snake[i].y, box, box);
  28.     }

  29.     // 绘制食物
  30.     context.fillStyle = 'red';
  31.     context.fillRect(food.x, food.y, box, box);

  32.     // 获取蛇头的当前位置
  33.     let snakeX = snake[0].x;
  34.     let snakeY = snake[0].y;

  35.     // 根据方向更新蛇头的位置
  36.     if (direction === 'LEFT') snakeX -= box;
  37.     if (direction === 'UP') snakeY -= box;
  38.     if (direction === 'RIGHT') snakeX += box;
  39.     if (direction === 'DOWN') snakeY += box;

  40.     // 检查蛇是否吃到食物
  41.     if (snakeX === food.x && snakeY === food.y) {
  42.         score++;
  43.         food = {
  44.             x: Math.floor(Math.random() * 19 + 1) * box,
  45.             y: Math.floor(Math.random() * 19 + 1) * box
  46.         };
  47.     } else {
  48.         snake.pop(); // 移除蛇尾部
  49.     }

  50.     // 创建新的蛇头
  51.     let newHead = { x: snakeX, y: snakeY };

  52.     // 检查是否撞墙或撞到自己
  53.     if (snakeX < 0 || snakeY < 0 || snakeX >= canvas.width || snakeY >= canvas.height || collision(newHead, snake)) {
  54.         clearInterval(game);
  55.         alert('游戏结束');
  56.         return;
  57.     }

  58.     // 将新头添加到蛇的开头
  59.     snake.unshift(newHead);

  60.     // 显示得分
  61.     context.fillStyle = 'black';
  62.     context.font = '20px Arial';
  63.     context.fillText('得分: ' + score, 5, canvas.height - 5);
  64. }

  65. function collision(head, array) {
  66.     for (let i = 0; i < array.length; i++) {
  67.         if (head.x === array[i].x && head.y === array[i].y) {
  68.             return true;
  69.         }
  70.     }
  71.     return false;
  72. }

  73. // 开始游戏:设置一个定时器,每100毫秒重绘一次画布
  74. let game = setInterval(drawGame, 100);
复制代码


### 第三步:添加开始页面和重新开始功能
我们可以再添加一些代码,让玩家在游戏结束后可以重新开始游戏。这需要修改HTML和JavaScript部分。

HTML部分:
  1. <button id="startButton" onclick="startGame()">开始游戏</button>
  2. <canvas id="gameCanvas" width="400" height="400" style="display: none;"></canvas>

  3. <style>
  4.     #startButton {
  5.         display: block;
  6.         margin-bottom: 20px;
  7.         padding: 10px 20px;
  8.         font-size: 16px;
  9.         cursor: pointer;
  10.     }
  11. </style>
复制代码


JavaScript部分:
  1. let game;
  2. document.getElementById('startButton').addEventListener('click', startGame);

  3. function startGame() {
  4.     document.getElementById('startButton').style.display = 'none';
  5.     document.getElementById('gameCanvas').style.display = 'block';
  6.     resetGame();
  7.     game = setInterval(drawGame, 100);
  8. }

  9. function resetGame() {
  10.     snake = [{ x: 9 * box, y: 10 * box }];
  11.     food = {
  12.         x: Math.floor(Math.random() * 19 + 1) * box,
  13.         y: Math.floor(Math.random() * 19 + 1) * box
  14.     };
  15.     score = 0;
  16.     direction = undefined;
  17. }
复制代码


至此,我们优化了贪吃蛇游戏,增加了一个开始按钮和重新开始功能。在优化后的代码中,我们通过函数组织和更直观的变量命名,使代码更容易阅读和维护。如果你又有更多的创新想法或功能需求,也可以继续扩展这个简单的游戏。希望你能从中学到更多的编程知识,并享受编程的乐趣!如果还有问题,请随时告诉我。
作者: 廖晗瑞    时间: 2024-8-14 19:01
帮我增加一些功能
作者: kaia    时间: 2024-8-14 19:01
廖晗瑞 发表于 2024-08-14 19:01
帮我增加一些功能


好的!我们可以添加一些新功能来增强游戏体验。下面列出了一些新增功能:

1. **增加游戏难度设置**:让玩家选择简单、普通和困难模式,不同模式下蛇的移动速度不同。
2. **记录最高得分**:在页面上显示玩家的最高得分,激励玩家挑战更高的分数。
3. **暂停功能**:允许玩家在游戏过程中暂停游戏。

我们将逐步实现这些功能。

### 第一步:修改HTML结构
我们需要增加一些新的按钮和标签到HTML文件中,用于难度选择、显示最高得分以及暂停游戏。



   
    贪吃蛇游戏
   
        /* CSS 样式 */
        body {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
        }
        #gameCanvas {
            border: 2px solid #000;
            background-color: #fff;
        }
        .controls {
            margin-bottom: 20px;
        }
        button {
            padding: 10px 20px;
            font-size: 16px;
            margin: 5px;
            cursor: pointer;
        }

   


    贪吃蛇游戏
   
        <div class="controls">
            <button id="startButton">开始游戏</button>
            <button id="pauseButton" style="display:none;">暂停</button>
            <label for="difficulty">难度:</label>
            <select id="difficulty">
                <option value="easy">简单</option>
                <option value="normal">普通</option>
                <option value="hard">困难</option>
            </select>
        </div>
        <canvas id="gameCanvas" width="400" height="400" style="display:none;"></canvas>
        <div id="scoreDisplay">最高得分: <span id="highScore">0</span></div>



### 第二步:优化JavaScript代码
接下来,我们需要在JavaScript中实现这些新功能。

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 每个格子的大小
  4. let snake, food, direction, score, game, gameInterval;
  5. let highScore = 0; // 最高得分

  6. // 难度设置
  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. document.getElementById('startButton').addEventListener('click', startGame);
  13. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  14. function startGame() {
  15.     document.getElementById('startButton').style.display = 'none';
  16.     document.getElementById('pauseButton').style.display = 'block';
  17.     document.getElementById('gameCanvas').style.display = 'block';

  18.     resetGame();
  19.     const difficulty = document.getElementById('difficulty').value;
  20.     gameInterval = difficultySettings[difficulty];
  21.     game = setInterval(drawGame, gameInterval);
  22. }

  23. function pauseGame() {
  24.     if (game) {
  25.         clearInterval(game);
  26.         game = null;
  27.         document.getElementById('pauseButton').innerText = '继续';
  28.     } else {
  29.         game = setInterval(drawGame, gameInterval);
  30.         document.getElementById('pauseButton').innerText = '暂停';
  31.     }
  32. }

  33. function resetGame() {
  34.     snake = ;
  35.     food = {
  36.         x: Math.floor(Math.random() * 19 + 1) * box,
  37.         y: Math.floor(Math.random() * 19 + 1) * box
  38.     };
  39.     score = 0;
  40.     direction = undefined;
  41. }

  42. document.addEventListener('keydown', changeDirection);

  43. function changeDirection(event) {
  44.     const keyPressed = event.keyCode;
  45.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  46.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  47.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  48.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  49. }

  50. function drawGame() {
  51.     context.clearRect(0, 0, canvas.width, canvas.height);

  52.     // 绘制蛇
  53.     for (let i = 0; i < snake.length; i++) {
  54.         context.fillStyle = i === 0 ? 'green' : 'black';
  55.         context.fillRect(snake.x, snake.y, box, box);
  56.     }

  57.     // 绘制食物
  58.     context.fillStyle = 'red';
  59.     context.fillRect(food.x, food.y, box, box);

  60.     // 获取蛇头的当前位置
  61.     let snakeX = snake.x;
  62.     let snakeY = snake.y;

  63.     // 根据方向更新蛇头的位置
  64.     if (direction === 'LEFT') snakeX -= box;
  65.     if (direction === 'UP') snakeY -= box;
  66.     if (direction === 'RIGHT') snakeX += box;
  67.     if (direction === 'DOWN') snakeY += box;

  68.     // 检查蛇是否吃到食物
  69.     if (snakeX === food.x && snakeY === food.y) {
  70.         score++;
  71.         updateHighScore();
  72.         food = {
  73.             x: Math.floor(Math.random() * 19 + 1) * box,
  74.             y: Math.floor(Math.random() * 19 + 1) * box
  75.         };
  76.     } else {
  77.         snake.pop(); // 移除蛇尾部
  78.     }

  79.     // 创建新的蛇头
  80.     let newHead = { x: snakeX, y: snakeY };

  81.     // 检查是否撞墙或撞到自己
  82.     if (snakeX < 0 || snakeY < 0 || snakeX >= canvas.width || snakeY >= canvas.height || collision(newHead, snake)) {
  83.         clearInterval(game);
  84.         alert('游戏结束');
  85.         return;
  86.     }

  87.     // 将新头添加到蛇的开头
  88.     snake.unshift(newHead);

  89.     // 显示得分
  90.     context.fillStyle = 'black';
  91.     context.font = '20px Arial';
  92.     context.fillText('得分: ' + score, 5, canvas.height - 5);
  93. }

  94. function collision(head, array) {
  95.     for (let i = 0; i < array.length; i++) {
  96.         if (head.x === array.x && head.y === array.y) {
  97.             return true;
  98.         }
  99.     }
  100.     return false;
  101. }

  102. function updateHighScore() {
  103.     if (score > highScore) {
  104.         highScore = score;
  105.         document.getElementById('highScore').innerText = highScore;
  106.     }
  107. }

  108. // 开始游戏:设置一个定时器,每100毫秒重绘一次画布
复制代码


### 总结
通过以上步骤,我们为简单的贪吃蛇游戏增加了难度设置、最高得分记录和暂停功能。通过这些功能的实现,玩家可以有更多的选择和更好的游戏体验。当然还有很多其他的扩展功能,比如音效、皮肤等,你可以尝试自行添加。希望你能从中学到更多的编程知识,并享受编程的乐趣!如果有任何问题,请随时告诉我。
作者: 廖晗瑞    时间: 2024-8-14 19:04
还可以怎么完善游戏与增加功能
作者: kaia    时间: 2024-8-14 19:04
廖晗瑞 发表于 2024-08-14 19:04
还可以怎么完善游戏与增加功能


当然,我们还可以添加更多的功能和改进来进一步完善贪吃蛇游戏。以下是一些建议:

### 增加的新功能和优化
1. **计时器**:根据游戏进行时间增加得分。
2. **音效**:在吃到食物或撞墙时播放声音。
3. **蛇的外观**:为蛇和食物添加不同的皮肤或图像。
4. **障碍物**:在游戏中随机生成障碍物增加难度。
5. **边界穿越**:让蛇可以从一个边界穿越到另一个边界。
6. **游戏记录**:保存每次游戏的得分和时间。

我们先来实现部分功能,例如计时器和音效。

### 设置计时器和音效

#### HTML 增加部分
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>贪吃蛇游戏</title>
  6.     <style>
  7.         body {
  8.             display: flex;
  9.             flex-direction: column;
  10.             justify-content: center;
  11.             align-items: center;
  12.             height: 100vh;
  13.             margin: 0;
  14.             font-family: Arial, sans-serif;
  15.             background-color: #f0f0f0;
  16.         }
  17.         #gameCanvas {
  18.             border: 2px solid #000;
  19.             background-color: #fff;
  20.         }
  21.         .controls {
  22.             margin-bottom: 20px;
  23.         }
  24.         button {
  25.             padding: 10px 20px;
  26.             font-size: 16px;
  27.             margin: 5px;
  28.             cursor: pointer;
  29.         }
  30.     </style>
  31. </head>
  32. <body>

  33.     <div class="controls">
  34.         <button id="startButton">开始游戏</button>
  35.         <button id="pauseButton" style="display:none;">暂停</button>
  36.         难度:
  37.         <select id="difficulty">
  38.             <option value="easy">简单</option>
  39.             <option value="normal">普通</option>
  40.             <option value="hard">困难</option>
  41.         </select>
  42.     </div>
  43.     <canvas id="gameCanvas" width="400" height="400" style="display:none;"></canvas>
  44.     <p>最高得分: <span id="highScore">0</span></p>
  45.     <p>时间: <span id="time">0</span> 秒</p>

  46.     <audio id="eatSound" src="eat.mp3"></audio>
  47.     <audio id="crashSound" src="crash.mp3"></audio>

  48.     <script>
复制代码


#### JavaScript 增加部分
  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20;
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = 0;
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. document.getElementById('startButton').addEventListener('click', startGame);
  13. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  14. function startGame() {
  15.     document.getElementById('startButton').style.display = 'none';
  16.     document.getElementById('pauseButton').style.display = 'block';
  17.     document.getElementById('gameCanvas').style.display = 'block';

  18.     resetGame();
  19.     const difficulty = document.getElementById('difficulty').value;
  20.     gameInterval = difficultySettings[difficulty];
  21.     game = setInterval(drawGame, gameInterval);
  22.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  23. }

  24. function pauseGame() {
  25.     if (game) {
  26.         clearInterval(game);
  27.         clearInterval(timeCounter);
  28.         game = null;
  29.         timeCounter = null;
  30.         document.getElementById('pauseButton').innerText = '继续';
  31.     } else {
  32.         game = setInterval(drawGame, gameInterval);
  33.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  34.         document.getElementById('pauseButton').innerText = '暂停';
  35.     }
  36. }

  37. function resetGame() {
  38.     snake = [{ x: 9 * box, y: 10 * box }];
  39.     food = {
  40.         x: Math.floor(Math.random() * 19 + 1) * box,
  41.         y: Math.floor(Math.random() * 19 + 1) * box
  42.     };
  43.     score = 0;
  44.     direction = undefined;
  45.     timeElapsed = 0;
  46.     document.getElementById('time').innerText = timeElapsed;
  47. }

  48. document.addEventListener('keydown', changeDirection);

  49. function changeDirection(event) {
  50.     const keyPressed = event.keyCode;
  51.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  52.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  53.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  54.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  55. }

  56. function drawGame() {
  57.     context.clearRect(0, 0, canvas.width, canvas.height);

  58.     for (let i = 0; i < snake.length; i++) {
  59.         context.fillStyle = i === 0 ? 'green' : 'black';
  60.         context.fillRect(snake[i].x, snake[i].y, box, box);
  61.     }

  62.     context.fillStyle = 'red';
  63.     context.fillRect(food.x, food.y, box, box);

  64.     let snakeX = snake[0].x;
  65.     let snakeY = snake[0].y;

  66.     if (direction === 'LEFT') snakeX -= box;
  67.     if (direction === 'UP') snakeY -= box;
  68.     if (direction === 'RIGHT') snakeX += box;
  69.     if (direction === 'DOWN') snakeY += box;

  70.     if (snakeX === food.x && snakeY === food.y) {
  71.         score++;
  72.         updateHighScore();
  73.         document.getElementById('eatSound').play(); // 播放吃声音
  74.         food = {
  75.             x: Math.floor(Math.random() * 19 + 1) * box,
  76.             y: Math.floor(Math.random() * 19 + 1) * box
  77.         };
  78.     } else {
  79.         snake.pop();
  80.     }

  81.     let newHead = { x: snakeX, y: snakeY };

  82.     if (snakeX < 0 || snakeY < 0 || snakeX >= canvas.width || snakeY >= canvas.height || collision(newHead, snake)) {
  83.         clearInterval(game);
  84.         clearInterval(timeCounter);
  85.         document.getElementById('crashSound').play(); // 播放撞墙声音
  86.         alert('游戏结束');
  87.         return;
  88.     }

  89.     snake.unshift(newHead);

  90.     context.fillStyle = 'black';
  91.     context.font = '20px Arial';
  92.     context.fillText('得分: ' + score, 5, canvas.height - 5);
  93. }

  94. function collision(head, array) {
  95.     for (let i = 0; i < array.length; i++) {
  96.         if (head.x === array[i].x && head.y === array[i].y) {
  97.             return true;
  98.         }
  99.     }
  100.     return false;
  101. }

  102. function updateHighScore() {
  103.     if (score > highScore) {
  104.         highScore = score;
  105.         document.getElementById('highScore').innerText = highScore;
  106.     }
  107. }

  108. function updateTime() {
  109.     timeElapsed++;
  110.     document.getElementById('time').innerText = timeElapsed;
  111. }
复制代码


这些代码增加了计时功能,并在吃到食物和撞墙时分别播放声音。你可以根据需要将 `eat.mp3` 和 `crash.mp3` 文件放置在项目中。

### 更多功能的扩展建议
如果你还想进一步丰富游戏,可以尝试以下功能:
1. **边界穿越**:在蛇超过边界时,让它从对面的边界出来。
2. **障碍物**:在画布上随机放置一些障碍物,蛇碰到障碍物即失败。
3. **多层次地图**:设计多个地图,每个地图有不同的难度和障碍物布置。
4. **存档功能**:允许玩家在游戏中暂停并保存当前的游戏状态,下次可以继续玩。
5. **积分排行榜**:将玩家的得分记录下来并展示排行榜。

通过不断尝试和扩展,你会发现贪吃蛇游戏可以变得非常丰富和有趣,同时也能学到更多的编程知识,如果有任何问题,随时告诉我哦!
作者: 廖晗瑞    时间: 2024-8-14 19:09
帮我把你提的建议添加到游戏里,并完善成一个完整的游戏
作者: kaia    时间: 2024-8-14 19:09
廖晗瑞 发表于 2024-08-14 19:09
帮我把你提的建议添加到游戏里,并完善成一个完整的游 ...


好的,让我们来一步一步实现这些功能,最终形成一个完整的贪吃蛇游戏。

### 增加边界穿越
我们首先实现边界穿越功能。蛇在画布边缘移动时,不是撞墙结束游戏,而是从对面的边界出来。

### 实现障碍物
在游戏中添加一些障碍物,当蛇撞到障碍物时,游戏结束。

### 增加积分排行榜
保存玩家的得分,并展示排行榜。

### 完整游戏代码

#### HTML结构
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <style>
  8.         body {
  9.             display: flex;
  10.             flex-direction: column;
  11.             justify-content: center;
  12.             align-items: center;
  13.             height: 100vh;
  14.             margin: 0;
  15.             font-family: Arial, sans-serif;
  16.             background-color: #f0f0f0;
  17.         }
  18.         #gameCanvas {
  19.             border: 2px solid #000;
  20.             background-color: #fff;
  21.         }
  22.         .controls {
  23.             margin-bottom: 20px;
  24.         }
  25.         button {
  26.             padding: 10px 20px;
  27.             font-size: 16px;
  28.             margin: 5px;
  29.             cursor: pointer;
  30.         }
  31.     </style>
  32. </head>
  33. <body>
  34.     <div class="controls">
  35.         <button id="startButton">开始游戏</button>
  36.         <button id="pauseButton" style="display: none;">暂停</button>
  37.         难度:
  38.         <select id="difficulty">
  39.             <option value="easy">简单</option>
  40.             <option value="normal" selected>普通</option>
  41.             <option value="hard">困难</option>
  42.         </select>
  43.     </div>
  44.     最高得分: <span id="highScore">0</span><br>
  45.     时间: <span id="time">0</span> 秒<br>
  46.     <canvas id="gameCanvas" width="400" height="400" style="display: none;"></canvas>

  47.     <!-- 添加音效资源 -->
  48.     <audio id="eatSound" src="eat.mp3"></audio>
  49.     <audio id="crashSound" src="crash.mp3"></audio>

  50.     <script src="snake.js"></script>
  51. </body>
  52. </html>
复制代码


#### JavaScript代码(snake.js)
  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20;
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = 0;
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const obstacles = []; // 存储障碍物的位置

  13. document.getElementById('startButton').addEventListener('click', startGame);
  14. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  15. function startGame() {
  16.     document.getElementById('startButton').style.display = 'none';
  17.     document.getElementById('pauseButton').style.display = 'block';
  18.     document.getElementById('gameCanvas').style.display = 'block';

  19.     resetGame();
  20.     const difficulty = document.getElementById('difficulty').value;
  21.     gameInterval = difficultySettings[difficulty];
  22.     game = setInterval(drawGame, gameInterval);
  23.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  24. }

  25. function pauseGame() {
  26.     if (game) {
  27.         clearInterval(game);
  28.         clearInterval(timeCounter);
  29.         game = null;
  30.         timeCounter = null;
  31.         document.getElementById('pauseButton').innerText = '继续';
  32.     } else {
  33.         game = setInterval(drawGame, gameInterval);
  34.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  35.         document.getElementById('pauseButton').innerText = '暂停';
  36.     }
  37. }

  38. function resetGame() {
  39.     snake = [{ x: 9 * box, y: 10 * box }];
  40.     food = {
  41.         x: Math.floor(Math.random() * 19 + 1) * box,
  42.         y: Math.floor(Math.random() * 19 + 1) * box
  43.     };
  44.     score = 0;
  45.     direction = undefined;
  46.     timeElapsed = 0;
  47.     document.getElementById('time').innerText = timeElapsed;
  48.     generateObstacles(); // 生成障碍物
  49. }

  50. document.addEventListener('keydown', changeDirection);

  51. function changeDirection(event) {
  52.     const keyPressed = event.keyCode;
  53.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  54.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  55.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  56.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  57. }

  58. function drawGame() {
  59.     context.clearRect(0, 0, canvas.width, canvas.height);

  60.     for (let i = 0; i < snake.length; i++) {
  61.         context.fillStyle = i === 0 ? 'green' : 'black';
  62.         context.fillRect(snake[i].x, snake[i].y, box, box);
  63.     }
  64.    
  65.     context.fillStyle = 'red';
  66.     context.fillRect(food.x, food.y, box, box);
  67.    
  68.     drawObstacles();

  69.     let snakeX = snake[0].x;
  70.     let snakeY = snake[0].y;

  71.     if (direction === 'LEFT') snakeX -= box;
  72.     if (direction === 'UP') snakeY -= box;
  73.     if (direction === 'RIGHT') snakeX += box;
  74.     if (direction === 'DOWN') snakeY += box;

  75.     if (snakeX === food.x && snakeY === food.y) {
  76.         score++;
  77.         updateHighScore();
  78.         document.getElementById('eatSound').play(); // 播放吃声音
  79.         food = {
  80.             x: Math.floor(Math.random() * 19 + 1) * box,
  81.             y: Math.floor(Math.random() * 19 + 1) * box
  82.         };
  83.     } else {
  84.         snake.pop();
  85.     }

  86.     let newHead = { x: snakeX, y: snakeY };

  87.     if (snakeX < 0) snakeX = canvas.width - box;
  88.     if (snakeY < 0) snakeY = canvas.height - box;
  89.     if (snakeX >= canvas.width) snakeX = 0;
  90.     if (snakeY >= canvas.height) snakeY = 0;

  91.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  92.         clearInterval(game);
  93.         clearInterval(timeCounter);
  94.         document.getElementById('crashSound').play(); // 播放撞墙声音
  95.         alert('游戏结束');
  96.         return;
  97.     }

  98.     snake.unshift(newHead);

  99.     context.fillStyle = 'black';
  100.     context.font = '20px Arial';
  101.     context.fillText('得分: ' + score, 5, canvas.height - 5);
  102. }

  103. function collision(head, array) {
  104.     for (let i = 0; i < array.length; i++) {
  105.         if (head.x === array[i].x && head.y === array[i].y) {
  106.             return true;
  107.         }
  108.     }
  109.     return false;
  110. }

  111. function updateHighScore() {
  112.     if (score > highScore) {
  113.         highScore = score;
  114.         document.getElementById('highScore').innerText = highScore;
  115.     }
  116. }

  117. function updateTime() {
  118.     timeElapsed++;
  119.     document.getElementById('time').innerText = timeElapsed;
  120. }

  121. function generateObstacles() {
  122.     obstacles.length = 0;
  123.     // 生成 5 个随机障碍物
  124.     for (let i = 0; i < 5; i++) {
  125.         let obstacle = {
  126.             x: Math.floor(Math.random() * 19 + 1) * box,
  127.             y: Math.floor(Math.random() * 19 + 1) * box
  128.         };
  129.         obstacles.push(obstacle);
  130.     }
  131. }

  132. function drawObstacles() {
  133.     context.fillStyle = 'grey';
  134.     for (let i = 0; i < obstacles.length; i++) {
  135.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  136.     }
  137. }
复制代码


### 总结
通过以上步骤,我们逐步实现了以下功能:
1. 边界穿越:蛇可以从一个边界穿越到另一个边界。
2. 障碍物:在游戏中随机生成障碍物,蛇撞到障碍物即游戏结束。
3. 积分和计时器:记录玩家得分和游戏时间。
4. 音效:在吃到食物或撞墙时播放声音。
5. 难度设置和暂停功能:玩家可以选择难度并在游戏中暂停。

你可以根据自己的需求继续扩展,比如设计多个地图、增加皮肤、更丰富的音效等。如果有任何问题,请随时告诉我!希望你享受编程和游戏的乐趣!
作者: 廖晗瑞    时间: 2024-8-14 19:12
能不能帮我设计多个地图、增加皮肤,并添加合适的音效,做成一个完整的游戏
作者: kaia    时间: 2024-8-14 19:14
廖晗瑞 发表于 2024-08-14 19:12
能不能帮我设计多个地图、增加皮肤,并添加合适的音效 ...


好的,我们来进一步完善贪吃蛇游戏,添加多个地图、皮肤以及音效。我们将分几个步骤进行:

1. **设计多个地图**:不同地图具有不同的障碍物布局。
2. **皮肤选择**:玩家可以选择蛇和食物的皮肤。
3. **添加音效**:为吃到食物和撞墙等事件添加合适的音效。

### 第一步:修改HTML结构

我们需要增加地图和皮肤的选择控件,以及音效文件的引用。

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <style>
  8.         /* CSS 样式 */
  9.         body {
  10.             display: flex;
  11.             flex-direction: column;
  12.             justify-content: center;
  13.             align-items: center;
  14.             height: 100vh;
  15.             margin: 0;
  16.             font-family: Arial, sans-serif;
  17.             background-color: #f0f0f0;
  18.         }
  19.         #gameCanvas {
  20.             border: 2px solid #000;
  21.             background-color: #fff;
  22.         }
  23.         .controls {
  24.             margin-bottom: 20px;
  25.         }
  26.         button {
  27.             padding: 10px 20px;
  28.             font-size: 16px;
  29.             margin: 5px;
  30.             cursor: pointer;
  31.         }
  32.     </style>
  33. </head>
  34. <body>

  35.     <div class="controls">
  36.         <button id="startButton">开始游戏</button>
  37.         <button id="pauseButton" style="display:none;">暂停</button>
  38.         难度:
  39.         <select id="difficulty">
  40.             <option value="easy">简单</option>
  41.             <option value="normal">普通</option>
  42.             <option value="hard">困难</option>
  43.         </select>
  44.         地图:
  45.         <select id="map">
  46.             <option value="map1">地图1</option>
  47.             <option value="map2">地图2</option>
  48.             <option value="map3">地图3</option>
  49.         </select>
  50.         皮肤:
  51.         <select id="skin">
  52.             <option value="default">默认</option>
  53.             <option value="blue">蓝色</option>
  54.             <option value="red">红色</option>
  55.         </select>
  56.     </div>

  57.     <canvas id="gameCanvas" width="400" height="400" style="display:none;"></canvas>
  58.     <div class="info">
  59.         最高得分: <span id="highScore">0</span>
  60.         时间: <span id="time">0</span> 秒
  61.     </div>

  62.     <audio id="eatSound">
  63.         <source src="eat.mp3" type="audio/mpeg">
  64.     </audio>
  65.     <audio id="crashSound">
  66.         <source src="crash.mp3" type="audio/mpeg">
  67.     </audio>

  68.     <script src="snake.js"></script>
  69. </body>
  70. </html>
复制代码


### 第二步:面向JavaScript代码进行改进(snake.js)

#### 定义地图和皮肤资源

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20;
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0; // 从localStorage读取最高得分
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. // 定义多个地图的障碍物位置
  18. const maps = {
  19.     map1: [
  20.         { x: 60, y: 60 }, { x: 80, y: 60 }, { x: 100, y: 60 },
  21.         { x: 60, y: 200 }, { x: 80, y: 200 }, { x: 100, y: 200 }
  22.     ],
  23.     map2: [
  24.         { x: 140, y: 140 }, { x: 160, y: 140 }, { x: 180, y: 140 },
  25.         { x: 140, y: 280 }, { x: 160, y: 280 }, { x: 180, y: 280 }
  26.     ],
  27.     map3: [
  28.         { x: 260, y: 260 }, { x: 280, y: 260 }, { x: 300, y: 260 },
  29.         { x: 260, y: 100 }, { x: 280, y: 100 }, { x: 300, y: 100 }
  30.     ]
  31. };

  32. let obstacles = [];

  33. document.getElementById('startButton').addEventListener('click', startGame);
  34. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  35. function startGame() {
  36.     document.getElementById('startButton').style.display = 'none';
  37.     document.getElementById('pauseButton').style.display = 'block';
  38.     document.getElementById('gameCanvas').style.display = 'block';

  39.     resetGame();
  40.     const difficulty = document.getElementById('difficulty').value;
  41.     gameInterval = difficultySettings[difficulty];
  42.     game = setInterval(drawGame, gameInterval);
  43.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  44. }

  45. function pauseGame() {
  46.     if (game) {
  47.         clearInterval(game);
  48.         clearInterval(timeCounter);
  49.         game = null;
  50.         timeCounter = null;
  51.         document.getElementById('pauseButton').innerText = '继续';
  52.     } else {
  53.         const difficulty = document.getElementById('difficulty').value;
  54.         gameInterval = difficultySettings[difficulty];
  55.         game = setInterval(drawGame, gameInterval);
  56.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  57.         document.getElementById('pauseButton').innerText = '暂停';
  58.     }
  59. }

  60. function resetGame() {
  61.     snake = [{ x: 9 * box, y: 10 * box }];
  62.     food = generateFood();
  63.     score = 0;
  64.     direction = undefined;
  65.     timeElapsed = 0;
  66.     document.getElementById('time').innerText = timeElapsed;
  67.     loadMap(); // 加载选中的地图
  68. }

  69. document.addEventListener('keydown', changeDirection);

  70. function changeDirection(event) {
  71.     const keyPressed = event.keyCode;
  72.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  73.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  74.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  75.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  76. }

  77. function drawGame() {
  78.     context.clearRect(0, 0, canvas.width, canvas.height);

  79.     const skin = document.getElementById('skin').value;
  80.     const colors = skins[skin];

  81.     for (let i = 0; i < snake.length; i++) {
  82.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  83.         context.fillRect(snake[i].x, snake[i].y, box, box);
  84.     }

  85.     context.fillStyle = colors.food;
  86.     context.fillRect(food.x, food.y, box, box);
  87.    
  88.     drawObstacles();

  89.     let snakeX = snake[0].x;
  90.     let snakeY = snake[0].y;

  91.     if (direction === 'LEFT') snakeX -= box;
  92.     if (direction === 'UP') snakeY -= box;
  93.     if (direction === 'RIGHT') snakeX += box;
  94.     if (direction === 'DOWN') snakeY += box;

  95.     if (snakeX === food.x && snakeY === food.y) {
  96.         score++;
  97.         updateHighScore();
  98.         document.getElementById('eatSound').play(); // 播放吃声音
  99.         food = generateFood();
  100.     } else {
  101.         snake.pop();
  102.     }

  103.     let newHead = { x: snakeX, y: snakeY };

  104.     if (snakeX < 0) snakeX = canvas.width - box;
  105.     if (snakeY < 0) snakeY = canvas.height - box;
  106.     if (snakeX >= canvas.width) snakeX = 0;
  107.     if (snakeY >= canvas.height) snakeY = 0;

  108.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  109.         clearInterval(game);
  110.         clearInterval(timeCounter);
  111.         document.getElementById('crashSound').play(); // 播放撞墙声音
  112.         alert('游戏结束');
  113.         return;
  114.     }

  115.     snake.unshift(newHead);

  116.     context.fillStyle = 'black';
  117.     context.font = '20px Arial';
  118.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  119. }

  120. function collision(head, array) {
  121.     for (let i = 0; i < array.length; i++) {
  122.         if (head.x === array[i].x && head.y === array[i].y) {
  123.             return true;
  124.         }
  125.     }
  126.     return false;
  127. }

  128. function updateHighScore() {
  129.     if (score > highScore) {
  130.         highScore = score;
  131.         localStorage.setItem('highScore', highScore); // 保存最高得分到localStorage
  132.         document.getElementById('highScore').innerText = highScore;
  133.     }
  134. }

  135. function updateTime() {
  136.     timeElapsed++;
  137.     document.getElementById('time').innerText = timeElapsed;
  138. }

  139. function generateFood() {
  140.     let newFood;
  141.     do {
  142.         newFood = {
  143.             x: Math.floor(Math.random() * 19 + 1) * box,
  144.             y: Math.floor(Math.random() * 19 + 1) * box
  145.         };
  146.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  147.     return newFood;
  148. }

  149. function loadMap() {
  150.     const selectedMap = document.getElementById('map').value;
  151.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  152. }

  153. function drawObstacles() {
  154.     context.fillStyle = 'grey';
  155.     for (let i = 0; i < obstacles.length; i++) {
  156.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  157.     }
  158. }
复制代码


### 关于音效文件
确保在项目根目录中准备好 `eat.mp3` 和 `crash.mp3` 文件,用于吃到食物和撞墙时的音效。

### 完整总结
通过上述步骤,我们完成了以下功能:
1. **多个地图**:玩家可以选择不同的地图,每个地图具有不同的障碍物布局。
2. **皮肤选择**:玩家可以选择不同的皮肤,使蛇和食物颜色不同。
3. **完整的音效**:在吃到食物和撞墙时播放对应的音效。
4. **实现了边界穿越**:蛇可以从一个边界穿越到另一个边界。
5. **保存最高得分**:在本地存储中保存并显示最高得分。

希望你喜欢这个完整的贪吃蛇游戏!如有任何问题或更多需求,请随时告诉我。享受编程和游戏的乐趣吧!
作者: 廖晗瑞    时间: 2024-8-14 19:16
帮我完成三个部分的制作,让它变成一个可以运行的游戏
作者: kaia    时间: 2024-8-14 19:17
廖晗瑞 发表于 2024-08-14 19:16
帮我完成三个部分的制作,让它变成一个可以运行的游戏 ...


好的,我们将贪吃蛇游戏的三个部分(多地图、皮肤选择和音效)组合在一起,完成一个可以运行的完整版本。以下是完整的HTML、CSS和JavaScript代码。

### HTML部分

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <style>
  8.         /* CSS 样式 */
  9.         body {
  10.             display: flex;
  11.             flex-direction: column;
  12.             justify-content: center;
  13.             align-items: center;
  14.             height: 100vh;
  15.             margin: 0;
  16.             font-family: Arial, sans-serif;
  17.             background-color: #f0f0f0;
  18.         }
  19.         #gameCanvas {
  20.             border: 2px solid #000;
  21.             background-color: #fff;
  22.         }
  23.         .controls {
  24.             margin-bottom: 10px;
  25.         }
  26.         button {
  27.             padding: 10px 20px;
  28.             font-size: 16px;
  29.             margin: 5px;
  30.             cursor: pointer;
  31.         }
  32.     </style>
  33. </head>
  34. <body>
  35.     <div class="controls">
  36.         <button id="startButton">开始游戏</button>
  37.         <button id="pauseButton" style="display:none;">暂停</button>
  38.         难度:
  39.         <select id="difficulty">
  40.             <option value="easy">简单</option>
  41.             <option value="normal">普通</option>
  42.             <option value="hard">困难</option>
  43.         </select>
  44.         地图:
  45.         <select id="map">
  46.             <option value="map1">地图1</option>
  47.             <option value="map2">地图2</option>
  48.             <option value="map3">地图3</option>
  49.         </select>
  50.         皮肤:
  51.         <select id="skin">
  52.             <option value="default">默认</option>
  53.             <option value="blue">蓝色</option>
  54.             <option value="red">红色</option>
  55.         </select>
  56.     </div>
  57.     <canvas id="gameCanvas" width="400" height="400" style="display: none;"></canvas>
  58.     <p>最高得分: <span id="highScore">0</span></p>
  59.     <p>时间: <span id="time">0</span> 秒</p>

  60.     <!-- 添加音效 -->
  61.     <audio id="eatSound" src="eat.mp3"></audio>
  62.     <audio id="crashSound" src="crash.mp3"></audio>

  63.     <script src="snake.js"></script>
  64. </body>
  65. </html>
复制代码


### JavaScript部分(snake.js)

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 每个格子的大小
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0; // 从localStorage读取最高得分
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. // 定义多个地图的障碍物位置
  18. const maps = {
  19.     map1: [],
  20.     map2: [
  21.         { x: 6 * box, y: 6 * box }, { x: 6 * box, y: 7 * box },
  22.         { x: 6 * box, y: 8 * box }, { x: 6 * box, y: 9 * box }
  23.     ],
  24.     map3: [
  25.         { x: 1 * box, y: 1 * box }, { x: 2 * box, y: 1 * box },
  26.         { x: 3 * box, y: 1 * box }, { x: 4 * box, y: 1 * box },
  27.         { x: 5 * box, y: 1 * box }, { x: 6 * box, y: 1 * box }
  28.     ]
  29. };

  30. let obstacles = [];

  31. document.getElementById('startButton').addEventListener('click', startGame);
  32. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  33. function startGame() {
  34.     document.getElementById('startButton').style.display = 'none';
  35.     document.getElementById('pauseButton').style.display = 'block';
  36.     document.getElementById('gameCanvas').style.display = 'block';

  37.     resetGame();
  38.     const difficulty = document.getElementById('difficulty').value;
  39.     gameInterval = difficultySettings[difficulty];
  40.     game = setInterval(drawGame, gameInterval);
  41.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  42. }

  43. function pauseGame() {
  44.     if (game) {
  45.         clearInterval(game);
  46.         clearInterval(timeCounter);
  47.         game = null;
  48.         timeCounter = null;
  49.         document.getElementById('pauseButton').innerText = '继续';
  50.     } else {
  51.         const difficulty = document.getElementById('difficulty').value;
  52.         gameInterval = difficultySettings[difficulty];
  53.         game = setInterval(drawGame, gameInterval);
  54.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  55.         document.getElementById('pauseButton').innerText = '暂停';
  56.     }
  57. }

  58. function resetGame() {
  59.     snake = [{ x: 9 * box, y: 10 * box }];
  60.     food = generateFood();
  61.     score = 0;
  62.     direction = undefined;
  63.     timeElapsed = 0;
  64.     document.getElementById('time').innerText = timeElapsed;
  65.     loadMap(); // 加载选中的地图
  66. }

  67. document.addEventListener('keydown', changeDirection);

  68. function changeDirection(event) {
  69.     const keyPressed = event.keyCode;
  70.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  71.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  72.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  73.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  74. }

  75. function drawGame() {
  76.     context.clearRect(0, 0, canvas.width, canvas.height);

  77.     const skin = document.getElementById('skin').value;
  78.     const colors = skins[skin];

  79.     for (let i = 0; i < snake.length; i++) {
  80.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  81.         context.fillRect(snake[i].x, snake[i].y, box, box);
  82.     }

  83.     context.fillStyle = colors.food;
  84.     context.fillRect(food.x, food.y, box, box);

  85.     drawObstacles();

  86.     let snakeX = snake[0].x;
  87.     let snakeY = snake[0].y;

  88.     if (direction === 'LEFT') snakeX -= box;
  89.     if (direction === 'UP') snakeY -= box;
  90.     if (direction === 'RIGHT') snakeX += box;
  91.     if (direction === 'DOWN') snakeY += box;

  92.     if (snakeX === food.x && snakeY === food.y) {
  93.         score++;
  94.         updateHighScore();
  95.         document.getElementById('eatSound').play(); // 播放吃声音
  96.         food = generateFood();
  97.     } else {
  98.         snake.pop();
  99.     }

  100.     let newHead = { x: snakeX, y: snakeY };

  101.     if (snakeX < 0) snakeX = canvas.width - box;
  102.     if (snakeY < 0) snakeY = canvas.height - box;
  103.     if (snakeX >= canvas.width) snakeX = 0;
  104.     if (snakeY >= canvas.height) snakeY = 0;

  105.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  106.         clearInterval(game);
  107.         clearInterval(timeCounter);
  108.         document.getElementById('crashSound').play(); // 播放撞墙声音
  109.         alert('游戏结束');
  110.         return;
  111.     }

  112.     snake.unshift(newHead);

  113.     context.fillStyle = 'black';
  114.     context.font = '20px Arial';
  115.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  116. }

  117. function collision(head, array) {
  118.     for (let i = 0; i < array.length; i++) {
  119.         if (head.x === array[i].x && head.y === array[i].y) {
  120.             return true;
  121.         }
  122.     }
  123.     return false;
  124. }

  125. function updateHighScore() {
  126.     if (score > highScore) {
  127.         highScore = score;
  128.         localStorage.setItem('highScore', highScore); // 保存最高得分到localStorage
  129.         document.getElementById('highScore').innerText = highScore;
  130.     }
  131. }

  132. function updateTime() {
  133.     timeElapsed++;
  134.     document.getElementById('time').innerText = timeElapsed;
  135. }

  136. function generateFood() {
  137.     let newFood;
  138.     do {
  139.         newFood = {
  140.             x: Math.floor(Math.random() * 19 + 1) * box,
  141.             y: Math.floor(Math.random() * 19 + 1) * box
  142.         };
  143.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  144.     return newFood;
  145. }

  146. function loadMap() {
  147.     const selectedMap = document.getElementById('map').value;
  148.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  149. }

  150. function drawObstacles() {
  151.     context.fillStyle = 'grey';
  152.     for (let i = 0; i < obstacles.length; i++) {
  153.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  154.     }
  155. }
复制代码


### 安装和运行游戏

1. **创建项目文件**:在一个新文件夹内创建三个文件:`index.html`, `style.css`, 和 `snake.js`。
2. **添加音效**:在项目根目录中放置`eat.mp3` 和 `crash.mp3` 音频文件,这两个文件分别为吃食物和撞墙时播放的音效。
3. **运行游戏**:用你的浏览器打开`index.html` 文件,即可运行游戏。

通过这些步骤,你可以完成一个具有多个地图、皮肤选择和音效的完整贪吃蛇游戏。如果有任何问题或进一步需求,请随时告诉我!享受编程和游戏的乐趣吧!
作者: 廖晗瑞    时间: 2024-8-14 19:21
可不可以再整理一下三个部分
作者: kaia    时间: 2024-8-14 19:23
廖晗瑞 发表于 2024-08-14 19:21
可不可以再整理一下三个部分


当然可以!我会将三个部分(多地图、皮肤选择和音效)整合到一个完整的项目中,并确保代码清晰可读。我们分为三部分:HTML、CSS和JavaScript。

### HTML部分

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <link rel="stylesheet" href="style.css">
  8. </head>
  9. <body>
  10.     <h1>贪吃蛇游戏</h1>
  11.     <div class="controls">
  12.         <button id="startButton">开始游戏</button>
  13.         <button id="pauseButton" style="display:none;">暂停</button>
  14.         <label for="difficulty">难度: </label>
  15.         <select id="difficulty">
  16.             <option value="easy">简单</option>
  17.             <option value="normal">普通</option>
  18.             <option value="hard">困难</option>
  19.         </select>
  20.         <label for="map">地图: </label>
  21.         <select id="map">
  22.             <option value="map1">地图1</option>
  23.             <option value="map2">地图2</option>
  24.             <option value="map3">地图3</option>
  25.         </select>
  26.         <label for="skin">皮肤: </label>
  27.         <select id="skin">
  28.             <option value="default">默认</option>
  29.             <option value="blue">蓝色</option>
  30.             <option value="red">红色</option>
  31.         </select>
  32.     </div>
  33.     <canvas id="gameCanvas" width="400" height="400" style="display:none;"></canvas>
  34.     <p>最高得分: <span id="highScore">0</span></p>
  35.     <p>时间: <span id="time">0</span> 秒</p>
  36.     <audio id="eatSound" src="eat.mp3"></audio>
  37.     <audio id="crashSound" src="crash.mp3"></audio>
  38.     <script src="snake.js"></script>
  39. </body>
  40. </html>
复制代码


### CSS部分(style.css)

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     justify-content: center;
  5.     align-items: center;
  6.     height: 100vh;
  7.     margin: 0;
  8.     font-family: Arial, sans-serif;
  9.     background-color: #f0f0f0;
  10. }

  11. #gameCanvas {
  12.     border: 2px solid #000;
  13.     background-color: #fff;
  14. }

  15. .controls {
  16.     margin-bottom: 20px;
  17. }

  18. button {
  19.     padding: 10px 20px;
  20.     font-size: 16px;
  21.     margin: 5px;
  22.     cursor: pointer;
  23. }
复制代码


### JavaScript部分(snake.js)

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20;
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0;
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. const maps = {
  18.     map1: [{ x: 5 * box, y: 5 * box }, { x: 10 * box, y: 10 * box }],
  19.     map2: [{ x: 7 * box, y: 7 * box }, { x: 12 * box, y: 12 * box }],
  20.     map3: [{ x: 9 * box, y: 9 * box }, { x: 14 * box, y: 14 * box }]
  21. };

  22. let obstacles = [];

  23. document.getElementById('startButton').addEventListener('click', startGame);
  24. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  25. function startGame() {
  26.     document.getElementById('startButton').style.display = 'none';
  27.     document.getElementById('pauseButton').style.display = 'block';
  28.     document.getElementById('gameCanvas').style.display = 'block';

  29.     resetGame();
  30.     const difficulty = document.getElementById('difficulty').value;
  31.     gameInterval = difficultySettings[difficulty];
  32.     game = setInterval(drawGame, gameInterval);
  33.     timeCounter = setInterval(updateTime, 1000);
  34. }

  35. function pauseGame() {
  36.     if (game) {
  37.         clearInterval(game);
  38.         clearInterval(timeCounter);
  39.         game = null;
  40.         timeCounter = null;
  41.         document.getElementById('pauseButton').innerText = '继续';
  42.     } else {
  43.         const difficulty = document.getElementById('difficulty').value;
  44.         gameInterval = difficultySettings[difficulty];
  45.         game = setInterval(drawGame, gameInterval);
  46.         timeCounter = setInterval(updateTime, 1000);
  47.         document.getElementById('pauseButton').innerText = '暂停';
  48.     }
  49. }

  50. function resetGame() {
  51.     snake = [{ x: 9 * box, y: 10 * box }];
  52.     food = generateFood();
  53.     score = 0;
  54.     direction = undefined;
  55.     timeElapsed = 0;
  56.     document.getElementById('time').innerText = timeElapsed;
  57.     loadMap();
  58. }

  59. document.addEventListener('keydown', changeDirection);

  60. function changeDirection(event) {
  61.     const keyPressed = event.keyCode;
  62.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  63.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  64.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  65.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  66. }

  67. function drawGame() {
  68.     context.clearRect(0, 0, canvas.width, canvas.height);

  69.     const skin = document.getElementById('skin').value;
  70.     const colors = skins[skin];

  71.     for (let i = 0; i < snake.length; i++) {
  72.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  73.         context.fillRect(snake[i].x, snake[i].y, box, box);
  74.     }

  75.     context.fillStyle = colors.food;
  76.     context.fillRect(food.x, food.y, box, box);

  77.     drawObstacles();

  78.     let snakeX = snake[0].x;
  79.     let snakeY = snake[0].y;

  80.     if (direction === 'LEFT') snakeX -= box;
  81.     if (direction === 'UP') snakeY -= box;
  82.     if (direction === 'RIGHT') snakeX += box;
  83.     if (direction === 'DOWN') snakeY += box;

  84.     if (snakeX === food.x && snakeY === food.y) {
  85.         score++;
  86.         updateHighScore();
  87.         document.getElementById('eatSound').play();
  88.         food = generateFood();
  89.     } else {
  90.         snake.pop();
  91.     }

  92.     let newHead = { x: snakeX, y: snakeY };

  93.     if (snakeX < 0) snakeX = canvas.width - box;
  94.     if (snakeY < 0) snakeY = canvas.height - box;
  95.     if (snakeX >= canvas.width) snakeX = 0;
  96.     if (snakeY >= canvas.height) snakeY = 0;

  97.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  98.         clearInterval(game);
  99.         clearInterval(timeCounter);
  100.         document.getElementById('crashSound').play();
  101.         alert('游戏结束');
  102.         return;
  103.     }

  104.     snake.unshift(newHead);

  105.     context.fillStyle = 'black';
  106.     context.font = '20px Arial';
  107.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  108. }

  109. function collision(head, array) {
  110.     for (let i = 0; i < array.length; i++) {
  111.         if (head.x === array[i].x && head.y === array[i].y) {
  112.             return true;
  113.         }
  114.     }
  115.     return false;
  116. }

  117. function updateHighScore() {
  118.     if (score > highScore) {
  119.         highScore = score;
  120.         localStorage.setItem('highScore', highScore);
  121.         document.getElementById('highScore').innerText = highScore;
  122.     }
  123. }

  124. function updateTime() {
  125.     timeElapsed++;
  126.     document.getElementById('time').innerText = timeElapsed;
  127. }

  128. function generateFood() {
  129.     let newFood;
  130.     do {
  131.         newFood = {
  132.             x: Math.floor(Math.random() * 19 + 1) * box,
  133.             y: Math.floor(Math.random() * 19 + 1) * box
  134.         };
  135.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  136.     return newFood;
  137. }

  138. function loadMap() {
  139.     const selectedMap = document.getElementById('map').value;
  140.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  141. }

  142. function drawObstacles() {
  143.     context.fillStyle = 'grey';
  144.     for (let i = 0; i < obstacles.length; i++) {
  145.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  146.     }
  147. }
复制代码


### 安装和运行游戏

1. **创建项目文件**:在一个新文件夹内创建三个文件:`index.html`, `style.css`, 和 `snake.js`。
2. **添加音效**:在项目根目录中放置`eat.mp3` 和 `crash.mp3` 音频文件,这两个文件分别为吃食物和撞墙时播放的音效。
3. **运行游戏**:用你的浏览器打开`index.html` 文件,即可运行游戏。

通过这些步骤,你可以完成一个具有多个地图、皮肤选择和音效的完整贪吃蛇游戏。如果有任何问题或进一步需求,请随时告诉我!享受编程和游戏的乐趣吧!
作者: 廖晗瑞    时间: 2024-8-14 19:25
怎么添加音效
作者: kaia    时间: 2024-8-14 19:26
廖晗瑞 发表于 2024-08-14 19:25
怎么添加音效


好的,我们来详细讲解一下如何添加音效到贪吃蛇游戏中。

### 第一步:准备音效文件

我们需要两个音效文件:
1. `eat.mp3` - 当蛇吃到食物时播放。
2. `crash.mp3` - 当蛇撞墙或撞到身体时播放。

将这两个音效文件放到你的项目根目录中。

### 第二步:在HTML中引入音效文件

我们需要在HTML文件中通过`audio`标签引入这两个音效文件。




   
   
    贪吃蛇游戏
   




    贪吃蛇游戏
   
        开始游戏
        暂停
        难度:
   

            简单
            普通
            困难
        
        地图:
   

            地图1
            地图2
            地图3
        
        皮肤:
   

            默认
            蓝色
            红色
        
   
   
    最高得分: 0
    时间: 0 秒
   
    <!-- 引入音效文件 -->
    <audio id="eatSound" src="eat.mp3"></audio>
    <audio id="crashSound" src="crash.mp3"></audio>
   

   



### 第三步:修改JavaScript代码,播放音效

修改JavaScript代码,在适当的位置添加音效播放逻辑。

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 每个格子的大小
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0; // 从localStorage读取最高得分
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. // 定义多个地图的障碍物位置
  18. const maps = {
  19.     map1: [],
  20.     map2: [
  21.         { x: 5 * box, y: 5 * box },
  22.         { x: 15 * box, y: 15 * box }
  23.     ],
  24.     map3: [
  25.         { x: 7 * box, y: 7 * box },
  26.         { x: 13 * box, y: 13 * box },
  27.         { x: 9 * box, y: 9 * box }
  28.     ]
  29. };

  30. let obstacles = [];

  31. document.getElementById('startButton').addEventListener('click', startGame);
  32. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  33. function startGame() {
  34.     document.getElementById('startButton').style.display = 'none';
  35.     document.getElementById('pauseButton').style.display = 'block';
  36.     document.getElementById('gameCanvas').style.display = 'block';

  37.     resetGame();
  38.     const difficulty = document.getElementById('difficulty').value;
  39.     gameInterval = difficultySettings[difficulty];
  40.     game = setInterval(drawGame, gameInterval);
  41.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  42. }

  43. function pauseGame() {
  44.     if (game) {
  45.         clearInterval(game);
  46.         clearInterval(timeCounter);
  47.         game = null;
  48.         timeCounter = null;
  49.         document.getElementById('pauseButton').innerText = '继续';
  50.     } else {
  51.         const difficulty = document.getElementById('difficulty').value;
  52.         gameInterval = difficultySettings[difficulty];
  53.         game = setInterval(drawGame, gameInterval);
  54.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  55.         document.getElementById('pauseButton').innerText = '暂停';
  56.     }
  57. }

  58. function resetGame() {
  59.     snake = [{ x: 9 * box, y: 10 * box }];
  60.     food = generateFood();
  61.     score = 0;
  62.     direction = undefined;
  63.     timeElapsed = 0;
  64.     document.getElementById('time').innerText = timeElapsed;
  65.     loadMap(); // 加载选中的地图
  66. }

  67. document.addEventListener('keydown', changeDirection);

  68. function changeDirection(event) {
  69.     const keyPressed = event.keyCode;
  70.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  71.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  72.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  73.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  74. }

  75. function drawGame() {
  76.     context.clearRect(0, 0, canvas.width, canvas.height);

  77.     const skin = document.getElementById('skin').value;
  78.     const colors = skins[skin];

  79.     for (let i = 0; i < snake.length; i++) {
  80.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  81.         context.fillRect(snake[i].x, snake[i].y, box, box);
  82.     }

  83.     context.fillStyle = colors.food;
  84.     context.fillRect(food.x, food.y, box, box);

  85.     drawObstacles();

  86.     let snakeX = snake[0].x;
  87.     let snakeY = snake[0].y;

  88.     if (direction === 'LEFT') snakeX -= box;
  89.     if (direction === 'UP') snakeY -= box;
  90.     if (direction === 'RIGHT') snakeX += box;
  91.     if (direction === 'DOWN') snakeY += box;

  92.     if (snakeX === food.x && snakeY === food.y) {
  93.         score++;
  94.         updateHighScore();
  95.         document.getElementById('eatSound').play(); // 播放吃声音
  96.         food = generateFood();
  97.     } else {
  98.         snake.pop();
  99.     }

  100.     let newHead = { x: snakeX, y: snakeY };

  101.     if (snakeX < 0) snakeX = canvas.width - box;
  102.     if (snakeY < 0) snakeY = canvas.height - box;
  103.     if (snakeX >= canvas.width) snakeX = 0;
  104.     if (snakeY >= canvas.height) snakeY = 0;

  105.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  106.         clearInterval(game);
  107.         clearInterval(timeCounter);
  108.         document.getElementById('crashSound').play(); // 播放撞墙声音
  109.         alert('游戏结束');
  110.         return;
  111.     }

  112.     snake.unshift(newHead);

  113.     context.fillStyle = 'black';
  114.     context.font = '20px Arial';
  115.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  116. }

  117. function collision(head, array) {
  118.     for (let i = 0; i < array.length; i++) {
  119.         if (head.x === array[i].x && head.y === array[i].y) {
  120.             return true;
  121.         }
  122.     }
  123.     return false;
  124. }

  125. function updateHighScore() {
  126.     if (score > highScore) {
  127.         highScore = score;
  128.         localStorage.setItem('highScore', highScore); // 保存最高得分到localStorage
  129.         document.getElementById('highScore').innerText = highScore;
  130.     }
  131. }

  132. function updateTime() {
  133.     timeElapsed++;
  134.     document.getElementById('time').innerText = timeElapsed;
  135. }

  136. function generateFood() {
  137.     let newFood;
  138.     do {
  139.         newFood = {
  140.             x: Math.floor(Math.random() * 19 + 1) * box,
  141.             y: Math.floor(Math.random() * 19 + 1) * box
  142.         };
  143.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  144.     return newFood;
  145. }

  146. function loadMap() {
  147.     const selectedMap = document.getElementById('map').value;
  148.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  149. }

  150. function drawObstacles() {
  151.     context.fillStyle = 'grey';
  152.     for (let i = 0; i < obstacles.length; i++) {
  153.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  154.     }
  155. }
复制代码


### 安装和运行游戏

1. **创建项目文件**:在一个新文件夹内创建四个文件:`index.html`, `style.css`, `snake.js`,和放置`eat.mp3` 和 `crash.mp3` 音频文件。
2. **运行游戏**:用你的浏览器打开`index.html` 文件,即可运行完整的贪吃蛇游戏并带有音效。

通过上述步骤,你应该已经完成了一个具有多地图、皮肤选择和音效的贪吃蛇游戏。如果还有问题或者进一步的需求,请随时告诉我!享受编程和游戏的乐趣吧!
作者: 廖晗瑞    时间: 2024-8-14 19:28
kaia 发表于 2024-8-14 19:23
当然可以!我会将三个部分(多地图、皮肤选择和音效)整合到一个完整的项目中,并确保代码清晰可读。我们 ...

我不想要音效,能不能帮我去除音效
作者: kaia    时间: 2024-8-14 19:29
廖晗瑞 发表于 2024-08-14 19:28
我不想要音效,能不能帮我去除音效


当然可以,我们可以移除音效相关的代码和元素。下面是没有音效的版本。

### HTML部分




   
   
    贪吃蛇游戏
   



    贪吃蛇游戏
   
        开始游戏
        暂停
        难度:
        
            简单
            普通
            困难
        
        地图:
        
            地图1
            地图2
            地图3
        
        皮肤:
        
            默认
            蓝色
            红色
        
   
   
    最高得分: 0
    时间: 0 秒
   
   
   
   


### CSS部分(style.css)

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     justify-content: center;
  5.     align-items: center;
  6.     height: 100vh;
  7.     margin: 0;
  8.     font-family: Arial, sans-serif;
  9.     background-color: #f0f0f0;
  10. }

  11. #gameCanvas {
  12.     border: 2px solid #000;
  13.     background-color: #fff;
  14. }

  15. .controls {
  16.     margin-bottom: 20px;
  17. }

  18. button {
  19.     padding: 10px 20px;
  20.     font-size: 16px;
  21.     margin: 5px;
  22.     cursor: pointer;
  23. }
复制代码


### JavaScript部分(snake.js)

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 每个格子的大小
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0; // 从localStorage读取最高得分
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. // 定义多个地图的障碍物位置
  18. const maps = {
  19.     map1: [
  20.         {x: 4 * box, y: 4 * box},
  21.         {x: 5 * box, y: 4 * box},
  22.         {x: 6 * box, y: 4 * box},
  23.         {x: 7 * box, y: 4 * box}
  24.     ],
  25.     map2: [
  26.         {x: 10 * box, y: 10 * box},
  27.         {x: 11 * box, y: 10 * box},
  28.         {x: 12 * box, y: 10 * box}
  29.     ],
  30.     map3: [
  31.         {x: 15 * box, y: 15 * box},
  32.         {x: 16 * box, y: 15 * box}
  33.     ]
  34. };

  35. let obstacles = [];

  36. document.getElementById('startButton').addEventListener('click', startGame);
  37. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  38. function startGame() {
  39.     document.getElementById('startButton').style.display = 'none';
  40.     document.getElementById('pauseButton').style.display = 'block';
  41.     document.getElementById('gameCanvas').style.display = 'block';

  42.     resetGame();
  43.     const difficulty = document.getElementById('difficulty').value;
  44.     gameInterval = difficultySettings[difficulty];
  45.     game = setInterval(drawGame, gameInterval);
  46.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  47. }

  48. function pauseGame() {
  49.     if (game) {
  50.         clearInterval(game);
  51.         clearInterval(timeCounter);
  52.         game = null;
  53.         timeCounter = null;
  54.         document.getElementById('pauseButton').innerText = '继续';
  55.     } else {
  56.         const difficulty = document.getElementById('difficulty').value;
  57.         gameInterval = difficultySettings[difficulty];
  58.         game = setInterval(drawGame, gameInterval);
  59.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  60.         document.getElementById('pauseButton').innerText = '暂停';
  61.     }
  62. }

  63. function resetGame() {
  64.     snake = [{ x: 9 * box, y: 10 * box }];
  65.     food = generateFood();
  66.     score = 0;
  67.     direction = undefined;
  68.     timeElapsed = 0;
  69.     document.getElementById('time').innerText = timeElapsed;
  70.     loadMap(); // 加载选中的地图
  71. }

  72. document.addEventListener('keydown', changeDirection);

  73. function changeDirection(event) {
  74.     const keyPressed = event.keyCode;
  75.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  76.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  77.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  78.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  79. }

  80. function drawGame() {
  81.     context.clearRect(0, 0, canvas.width, canvas.height);

  82.     const skin = document.getElementById('skin').value;
  83.     const colors = skins[skin];

  84.     for (let i = 0; i < snake.length; i++) {
  85.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  86.         context.fillRect(snake[i].x, snake[i].y, box, box);
  87.     }

  88.     context.fillStyle = colors.food;
  89.     context.fillRect(food.x, food.y, box, box);

  90.     drawObstacles();

  91.     let snakeX = snake[0].x;
  92.     let snakeY = snake[0].y;

  93.     if (direction === 'LEFT') snakeX -= box;
  94.     if (direction === 'UP') snakeY -= box;
  95.     if (direction === 'RIGHT') snakeX += box;
  96.     if (direction === 'DOWN') snakeY += box;

  97.     if (snakeX === food.x && snakeY === food.y) {
  98.         score++;
  99.         updateHighScore();
  100.         food = generateFood();
  101.     } else {
  102.         snake.pop();
  103.     }

  104.     let newHead = { x: snakeX, y: snakeY };

  105.     if (snakeX < 0) snakeX = canvas.width - box;
  106.     if (snakeY < 0) snakeY = canvas.height - box;
  107.     if (snakeX >= canvas.width) snakeX = 0;
  108.     if (snakeY >= canvas.height) snakeY = 0;

  109.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  110.         clearInterval(game);
  111.         clearInterval(timeCounter);
  112.         alert('游戏结束');
  113.         return;
  114.     }

  115.     snake.unshift(newHead);

  116.     context.fillStyle = 'black';
  117.     context.font = '20px Arial';
  118.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  119. }

  120. function collision(head, array) {
  121.     for (let i = 0; i < array.length; i++) {
  122.         if (head.x === array[i].x && head.y === array[i].y) {
  123.             return true;
  124.         }
  125.     }
  126.     return false;
  127. }

  128. function updateHighScore() {
  129.     if (score > highScore) {
  130.         highScore = score;
  131.         localStorage.setItem('highScore', highScore); // 保存最高得分到localStorage
  132.         document.getElementById('highScore').innerText = highScore;
  133.     }
  134. }

  135. function updateTime() {
  136.     timeElapsed++;
  137.     document.getElementById('time').innerText = timeElapsed;
  138. }

  139. function generateFood() {
  140.     let newFood;
  141.     do {
  142.         newFood = {
  143.             x: Math.floor(Math.random() * 19 + 1) * box,
  144.             y: Math.floor(Math.random() * 19 + 1) * box
  145.         };
  146.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  147.     return newFood;
  148. }

  149. function loadMap() {
  150.     const selectedMap = document.getElementById('map').value;
  151.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  152. }

  153. function drawObstacles() {
  154.     context.fillStyle = 'grey';
  155.     for (let i = 0; i < obstacles.length; i++) {
  156.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  157.     }
  158. }
复制代码

### 运行游戏

1. **创建项目文件**:在一个新文件夹内创建三个文件:`index.html`, `style.css`, 和 `snake.js`。
2. **运行游戏**:用你的浏览器打开 `index.html` 文件,即可运行完整的贪吃蛇游戏。

通过这些步骤,你应该已经能够运行一个具有多地图、皮肤选择而且没有音效的完整贪吃蛇游戏。如果有任何问题或进一步的需求,请随时告诉我!享受编程和游戏的乐趣吧!
作者: 廖晗瑞    时间: 2024-8-14 21:48
帮我把地图扩大一点
作者: 廖晗瑞    时间: 2024-8-14 22:01
可不可以再帮我整合一下
作者: 廖晗瑞    时间: 2024-8-14 22:17
kaia 发表于 2024-8-14 19:26
好的,我们来详细讲解一下如何添加音效到贪吃蛇游戏中。

### 第一步:准备音效文件

我不想要音效,能不能帮我去除音效
作者: kaia    时间: 2024-8-14 22:18
廖晗瑞 发表于 2024-08-14 22:17
我不想要音效,能不能帮我去除音效


当然可以!我们来移除音效相关的内容。下面是去除音效后的代码:

### HTML文件
首先,删除HTML中引入音效文件的部分:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>贪吃蛇游戏</title>
  7.     <style>
  8.         body {
  9.             display: flex;
  10.             justify-content: center;
  11.             align-items: center;
  12.             height: 100vh;
  13.             margin: 0;
  14.             font-family: Arial, sans-serif;
  15.             background-color: #f0f0f0;
  16.         }
  17.         #gameCanvas {
  18.             border: 1px solid #000;
  19.             background-color: #fff;
  20.         }
  21.     </style>
  22. </head>
  23. <body>
  24.    
  25.     <canvas id="gameCanvas" width="400" height="400"></canvas>

  26.     <script src="snake.js"></script>
  27. </body>
  28. </html>
复制代码


### JavaScript文件
修改JavaScript代码,去除与音效相关的逻辑:

  1. const canvas = document.getElementById('gameCanvas');
  2. const context = canvas.getContext('2d');

  3. const box = 20; // 每个格子的大小
  4. let snake, food, direction, score, game, gameInterval, timeCounter;
  5. let highScore = localStorage.getItem('highScore') || 0; // 从localStorage读取最高得分
  6. let timeElapsed = 0;

  7. const difficultySettings = {
  8.     easy: 150,
  9.     normal: 100,
  10.     hard: 50
  11. };

  12. const skins = {
  13.     default: { snake: 'black', food: 'red' },
  14.     blue: { snake: 'blue', food: 'lightblue' },
  15.     red: { snake: 'red', food: 'orange' }
  16. };

  17. // 定义多个地图的障碍物位置
  18. const maps = {
  19.     map1: [],
  20.     map2: [],
  21.     map3: []
  22. };

  23. let obstacles = [];

  24. document.getElementById('startButton').addEventListener('click', startGame);
  25. document.getElementById('pauseButton').addEventListener('click', pauseGame);

  26. function startGame() {
  27.     document.getElementById('startButton').style.display = 'none';
  28.     document.getElementById('pauseButton').style.display = 'block';
  29.     document.getElementById('gameCanvas').style.display = 'block';

  30.     resetGame();
  31.     const difficulty = document.getElementById('difficulty').value;
  32.     gameInterval = difficultySettings[difficulty];
  33.     game = setInterval(drawGame, gameInterval);
  34.     timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  35. }

  36. function pauseGame() {
  37.     if (game) {
  38.         clearInterval(game);
  39.         clearInterval(timeCounter);
  40.         game = null;
  41.         timeCounter = null;
  42.         document.getElementById('pauseButton').innerText = '继续';
  43.     } else {
  44.         const difficulty = document.getElementById('difficulty').value;
  45.         gameInterval = difficultySettings[difficulty];
  46.         game = setInterval(drawGame, gameInterval);
  47.         timeCounter = setInterval(updateTime, 1000); // 每秒更新一次时间
  48.         document.getElementById('pauseButton').innerText = '暂停';
  49.     }
  50. }

  51. function resetGame() {
  52.     snake = [{ x: 9 * box, y: 10 * box }];
  53.     food = generateFood();
  54.     score = 0;
  55.     direction = undefined;
  56.     timeElapsed = 0;
  57.     document.getElementById('time').innerText = timeElapsed;
  58.     loadMap(); // 加载选中的地图
  59. }

  60. document.addEventListener('keydown', changeDirection);

  61. function changeDirection(event) {
  62.     const keyPressed = event.keyCode;
  63.     if (keyPressed === 37 && direction !== 'RIGHT') direction = 'LEFT';
  64.     if (keyPressed === 38 && direction !== 'DOWN') direction = 'UP';
  65.     if (keyPressed === 39 && direction !== 'LEFT') direction = 'RIGHT';
  66.     if (keyPressed === 40 && direction !== 'UP') direction = 'DOWN';
  67. }

  68. function drawGame() {
  69.     context.clearRect(0, 0, canvas.width, canvas.height);

  70.     const skin = document.getElementById('skin').value;
  71.     const colors = skins[skin];

  72.     for (let i = 0; i < snake.length; i++) {
  73.         context.fillStyle = i === 0 ? 'green' : colors.snake;
  74.         context.fillRect(snake[i].x, snake[i].y, box, box);
  75.     }

  76.     context.fillStyle = colors.food;
  77.     context.fillRect(food.x, food.y, box, box);

  78.     drawObstacles();

  79.     let snakeX = snake[0].x;
  80.     let snakeY = snake[0].y;

  81.     if (direction === 'LEFT') snakeX -= box;
  82.     if (direction === 'UP') snakeY -= box;
  83.     if (direction === 'RIGHT') snakeX += box;
  84.     if (direction === 'DOWN') snakeY += box;

  85.     if (snakeX === food.x && snakeY === food.y) {
  86.         score++;
  87.         updateHighScore();
  88.         food = generateFood();
  89.     } else {
  90.         snake.pop();
  91.     }

  92.     let newHead = { x: snakeX, y: snakeY };

  93.     if (snakeX < 0) snakeX = canvas.width - box;
  94.     if (snakeY < 0) snakeY = canvas.height - box;
  95.     if (snakeX >= canvas.width) snakeX = 0;
  96.     if (snakeY >= canvas.height) snakeY = 0;

  97.     if (collision(newHead, snake) || collision(newHead, obstacles)) {
  98.         clearInterval(game);
  99.         clearInterval(timeCounter);
  100.         alert('游戏结束');
  101.         return;
  102.     }

  103.     snake.unshift(newHead);

  104.     context.fillStyle = 'black';
  105.     context.font = '20px Arial';
  106.     context.fillText(`得分: ${score}`, 5, canvas.height - 5);
  107. }

  108. function collision(head, array) {
  109.     for (let i = 0; i < array.length; i++) {
  110.         if (head.x === array[i].x && head.y === array[i].y) {
  111.             return true;
  112.         }
  113.     }
  114.     return false;
  115. }

  116. function updateHighScore() {
  117.     if (score > highScore) {
  118.         highScore = score;
  119.         localStorage.setItem('highScore', highScore); // 保存最高得分到localStorage
  120.         document.getElementById('highScore').innerText = highScore;
  121.     }
  122. }

  123. function updateTime() {
  124.     timeElapsed++;
  125.     document.getElementById('time').innerText = timeElapsed;
  126. }

  127. function generateFood() {
  128.     let newFood;
  129.     do {
  130.         newFood = {
  131.             x: Math.floor(Math.random() * 19 + 1) * box,
  132.             y: Math.floor(Math.random() * 19 + 1) * box
  133.         };
  134.     } while (collision(newFood, snake) || collision(newFood, obstacles));
  135.     return newFood;
  136. }

  137. function loadMap() {
  138.     const selectedMap = document.getElementById('map').value;
  139.     obstacles = maps[selectedMap] ? [...maps[selectedMap]] : [];
  140. }

  141. function drawObstacles() {
  142.     context.fillStyle = 'grey';
  143.     for (let i = 0; i < obstacles.length; i++) {
  144.         context.fillRect(obstacles[i].x, obstacles[i].y, box, box);
  145.     }
  146. }
复制代码


### 总结

通过删除HTML和JavaScript中与音效相关的代码,你现在有了一个不带音效的贪吃蛇游戏。如果你有其他问题或需要进一步的帮助,请随时告诉我!享受编程的乐趣吧!




欢迎光临 科学教育 (http://www.sci-edu.net/) Powered by Discuz! X3.2