科学教育

标题: 贪吃蛇 [打印本页]

作者: 张复礼    时间: 2024-8-2 14:58
标题: 贪吃蛇
生成一段完整的贪吃蛇游戏

作者: kaia    时间: 2024-8-2 14:59
嘿,小朋友!咱们今天来做一个有趣的小游戏吧——贪吃蛇!这可是一个经典的游戏哦!我们会用到HTML、CSS和JavaScript来完成这个小项目。准备好了吗?让我们开始吧!

### 第一步:设置HTML结构
首先,我们需要一个简单的HTML文件来放置我们的游戏画布(canvas)。它就像是我们的“游戏舞台”。

创建一个新的HTML文件,命名为 `index.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.         canvas {
  9.             border: 1px solid black;
  10.             background-color: #f5f5f5;
  11.         }
  12.     </style>
  13. </head>
  14. <body>
  15.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  16.     <script src="script.js"></script>
  17. </body>
  18. </html>
复制代码


### 第二步:设置CSS样式
在上面的HTML文件中,我们已经加了简单的CSS样式,用来显示一个边框,并设置画布的背景颜色。

### 第三步:编写JavaScript
现在,我们要来写最重要的JavaScript部分。在HTML文件的最后一行,我们使用`<script>`标签引入了一个叫做 `script.js` 的文件。接下来,我们需要创建这个文件,并使用它来实现贪吃蛇游戏的逻辑。

新建一个文件,命名为 `script.js`,然后添加以下代码:

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

  3. let snake = [
  4.     { x: 150, y: 150 },
  5.     { x: 140, y: 150 },
  6.     { x: 130, y: 150 },
  7.     { x: 120, y: 150 },
  8.     { x: 110, y: 150 }
  9. ];

  10. let dx = 10;
  11. let dy = 0;

  12. function clearCanvas() {
  13.     ctx.fillStyle = "white";
  14.     ctx.strokeStyle = "black";
  15.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  16.     ctx.strokeRect(0, 0, canvas.width, canvas.height);
  17. }

  18. function drawSnake() {
  19.     snake.forEach(drawSnakePart);
  20. }

  21. function drawSnakePart(snakePart) {
  22.     ctx.fillStyle = 'lightgreen';
  23.     ctx.strokeStyle = 'darkgreen';

  24.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  25.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  26. }

  27. function moveSnake() {
  28.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };
  29.     snake.unshift(head);
  30.     snake.pop();
  31. }

  32. function main() {
  33.     setTimeout(function onTick() {
  34.         clearCanvas();
  35.         moveSnake();
  36.         drawSnake();
  37.         
  38.         main();
  39.     }, 100);
  40. }

  41. document.addEventListener("keydown", changeDirection);

  42. function changeDirection(event) {
  43.     const LEFT_KEY = 37;
  44.     const RIGHT_KEY = 39;
  45.     const UP_KEY = 38;
  46.     const DOWN_KEY = 40;

  47.     const keyPressed = event.keyCode;
  48.     const goingUp = dy === -10;
  49.     const goingDown = dy === 10;
  50.     const goingRight = dx === 10;
  51.     const goingLeft = dx === -10;

  52.     if (keyPressed === LEFT_KEY && !goingRight) {
  53.         dx = -10;
  54.         dy = 0;
  55.     }

  56.     if (keyPressed === UP_KEY && !goingDown) {
  57.         dx = 0;
  58.         dy = -10;
  59.     }

  60.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  61.         dx = 10;
  62.         dy = 0;
  63.     }

  64.     if (keyPressed === DOWN_KEY && !goingUp) {
  65.         dx = 0;
  66.         dy = 10;
  67.     }
  68. }

  69. main();
复制代码


### 解释一下代码:
1. **初始化贪吃蛇**:我们设定了初始的蛇身体位置,宽度和高度都为10个像素。
2. **画布清理函数**:每次更新蛇的位置前,我们需要清理画布。
3. **绘制蛇**:定义了如何绘制蛇的每一节。
4. **移动蛇**:蛇的每一节都会往前挪动一格。
5. **主循环(main)**:每100毫秒,我们会清理画布、移动蛇、再重新绘制。
6. **方向控制**:通过监听键盘事件,实现上下左右的控制。

这么一来,你就可以在浏览器中打开 `index.html` 文件,尽情享受你的贪吃蛇游戏了!加油,希望你玩得开心!
作者: 张复礼    时间: 2024-8-2 15:11
你好,我的游戏需要出现蛇的食物,蛇吃了食物之后变长,当蛇碰壁后显示“游戏结束”及得分,出现“开始游戏”的按钮。
作者: kaia    时间: 2024-8-2 15:12
张复礼 发表于 2024-08-02 15:11
你好,我的游戏需要出现蛇的食物,蛇吃了食物之后变长 ...


好的,小朋友!我们来为贪吃蛇游戏添加食物、增加得分和游戏结束的功能吧!这是一个非常有趣的部分。下面我们逐步修改 `script.js` 文件。

### 修改后的 JavaScript 代码

在之前的代码基础上添加以下内容:

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

  3. let snake = [{ x: 50, y: 50 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     // 检测碰壁
  35.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  36.         gameOver = true;
  37.         return;
  38.     }

  39.     snake.unshift(head);

  40.     // 检查是否吃到食物
  41.     if (head.x === food.x && head.y === food.y) {
  42.         score++;
  43.         food = randomFoodPosition();
  44.     } else {
  45.         snake.pop();
  46.     }
  47. }

  48. function collision(head) {
  49.     for (let i = 1; i < snake.length; i++) {
  50.         if (snake[i].x === head.x && snake[i].y === head.y) {
  51.             return true;
  52.         }
  53.     }
  54.     return false;
  55. }

  56. function main() {
  57.     if (gameOver) {
  58.         displayGameOver();
  59.         return;
  60.     }

  61.     setTimeout(function onTick() {
  62.         clearCanvas();
  63.         drawFood();
  64.         moveSnake();
  65.         drawSnake();
  66.         main();
  67.     }, 100);
  68. }

  69. function changeDirection(event) {
  70.     const LEFT_KEY = 37;
  71.     const RIGHT_KEY = 39;
  72.     const UP_KEY = 38;
  73.     const DOWN_KEY = 40;

  74.     const keyPressed = event.keyCode;
  75.     const goingUp = dy === -10;
  76.     const goingDown = dy === 10;
  77.     const goingRight = dx === 10;
  78.     const goingLeft = dx === -10;

  79.     if (keyPressed === LEFT_KEY && !goingRight) {
  80.         dx = -10;
  81.         dy = 0;
  82.     }

  83.     if (keyPressed === UP_KEY && !goingDown) {
  84.         dx = 0;
  85.         dy = -10;
  86.     }

  87.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  88.         dx = 10;
  89.         dy = 0;
  90.     }

  91.     if (keyPressed === DOWN_KEY && !goingUp) {
  92.         dx = 0;
  93.         dy = 10;
  94.     }
  95. }

  96. // 显示游戏结束
  97. function displayGameOver() {
  98.     ctx.fillStyle = "black";
  99.     ctx.font = "30px Arial";
  100.     ctx.fillText("游戏结束!得分: " + score, canvas.width / 4, canvas.height / 2);
  101.     document.getElementById("startButton").style.display = "block";
  102. }

  103. function startGame() {
  104.     snake = [{ x: 50, y: 50 }];
  105.     score = 0;
  106.     dx = 10;
  107.     dy = 0;
  108.     gameOver = false;
  109.     food = randomFoodPosition();
  110.     main();
  111. }

  112. food = randomFoodPosition();
  113. main();
复制代码


### 修改后的 HTML 代码

在原有的 `index.html` 文件中,添加一个开始游戏的按钮:

  1. <!DOCTYPE html>
  2. <html lang="zh">
  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.         canvas {
  9.             border: 1px solid black;
  10.             background-color: #f5f5f5;
  11.         }
  12.         #startButton {
  13.             display: none;
  14.             margin-top: 10px;
  15.         }
  16.     </style>
  17. </head>
  18. <body>
  19.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  20.     <button id="startButton" onclick="startGame()">开始游戏</button>
  21.     <script src="script.js"></script>
  22. </body>
  23. </html>
复制代码


### 解释修改的内容:

1. **生成食物**:使用 `randomFoodPosition()` 函数随机位置放置食物。
2. **增加得分**:每次蛇吃到食物时,得分加一,并重新生成食物。
3. **检测碰壁**:如果蛇的头部碰到边界或自己的身体,游戏结束。
4. **显示游戏结束信息**:当游戏结束时,显示得分和“开始游戏”按钮。
5. **重新开始游戏**:点击“开始游戏”按钮后,游戏会重置并开始。

现在你打开 `index.html` 文件,就可以玩这个完整的贪吃蛇游戏了!享受游戏吧!如果还有其他问题,随时问我哦!
作者: 张复礼    时间: 2024-8-2 15:34
为什么没有css文件
作者: kaia    时间: 2024-8-2 15:34
张复礼 发表于 2024-08-02 15:34
为什么没有css文件


抱歉忘记提到CSS文件了!来,我们为这个贪吃蛇游戏添加一些简单的样式,使它看起来更好。接下来,我们会创建一个 `style.css` 文件并添加相应的样式。

### 创建 CSS 文件

新建一个文件,命名为 `style.css`,然后添加以下内容:

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     background-color: #e0e0e0;
  8. }

  9. canvas {
  10.     border: 1px solid black;
  11.     background-color: #f5f5f5;
  12. }

  13. #startButton {
  14.     display: none; /* 默认隐藏 */
  15.     padding: 10px 20px;
  16.     font-size: 20px;
  17.     margin-top: 10px;
  18.     cursor: pointer;
  19.     background-color: #4CAF50; /* 绿色按钮 */
  20.     color: white;
  21.     border: none;
  22.     border-radius: 5px;
  23. }

  24. #startButton:hover {
  25.     background-color: #45a049; /* 更深的绿色 */
  26. }
复制代码


### 修改 HTML 文件以链接 CSS

确保在 `index.html` 文件的 `<head>` 部分连接这个 CSS 文件:

  1. <!DOCTYPE html>
  2. <html lang="zh">
  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.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  11.     <button id="startButton" onclick="startGame()">开始游戏</button>

  12.     <script src="script.js"></script>
  13. </body>
  14. </html>
复制代码


### 解释 CSS 样式:

1. **`body`**: 用 Flexbox 布局使画布和按钮居中,背景颜色为淡灰色。
2. **`canvas`**: 设置边框和背景颜色。
3. **`#startButton`**: 设置按钮的样式,包括颜色、大小以及鼠标悬停时的效果。

### 运行游戏

完成这些后,你可以在浏览器中打开 `index.html` 文件,使用“开始游戏”按钮来开始你的贪吃蛇游戏!希望你喜欢这些改动!如果还有其他问题,或者想进一步增加更多功能,随时告诉我哦!
作者: 张复礼    时间: 2024-8-6 14:17
游戏结束后,“开始游戏”的按钮出现在“游戏结束!”四个字下方。
作者: kaia    时间: 2024-8-6 14:18
张复礼 发表于 2024-08-06 14:17
游戏结束后,“开始游戏”的按钮出现在“游戏结束!” ...


好的,我们来调整一下按钮在“游戏结束!”文字下方的位置。为此,我们将进一步改进 HTML 和 CSS 代码,使布局更合理。

### 修改后的 HTML 代码

更新你的 `index.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.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  12.     <div id="gameOverText" class="hidden">游戏结束!</div>
  13.     <button id="startButton" onclick="startGame()">开始游戏</button>
  14.     <script src="script.js"></script>
  15. </body>
  16. </html>
复制代码


这里我们添加了一个 `<div>` 标签,用于显示“游戏结束!”的信息。

### 修改后的 CSS 代码

更新你的 `style.css` 文件,使其如下所示:

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     background-color: #e0e0e0;
  8.     margin: 0;
  9. }

  10. canvas {
  11.     border: 1px solid black;
  12.     background-color: #f5f5f5;
  13. }

  14. #startButton {
  15.     display: none; /* 默认隐藏 */
  16.     padding: 10px 20px;
  17.     font-size: 20px;
  18.     margin-top: 10px;
  19.     cursor: pointer;
  20.     background-color: #4CAF50; /* 绿色按钮 */
  21.     color: white;
  22.     border: none;
  23.     border-radius: 5px;
  24. }

  25. #startButton:hover {
  26.     background-color: #45a049; /* 更深的绿色 */
  27. }

  28. #gameOverText {
  29.     font-size: 24px;
  30.     color: red;
  31.     margin-top: 20px;
  32.     display: none; /* 默认隐藏 */
  33. }

  34. .hidden {
  35.     display: none;
  36. }
复制代码


### 修改后的 JavaScript 代码

接下来,更新 `script.js` 文件,使其如下所示:

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

  3. let snake = [{ x: 50, y: 50 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     // 检测碰壁
  35.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  36.         gameOver = true;
  37.         return;
  38.     }

  39.     snake.unshift(head);

  40.     // 检查是否吃到食物
  41.     if (head.x === food.x && head.y === food.y) {
  42.         score++;
  43.         food = randomFoodPosition();
  44.     } else {
  45.         snake.pop();
  46.     }
  47. }

  48. function collision(head) {
  49.     for (let i = 1; i < snake.length; i++) {
  50.         if (snake[i].x === head.x && snake[i].y === head.y) {
  51.             return true;
  52.         }
  53.     }
  54.     return false;
  55. }

  56. function main() {
  57.     if (gameOver) {
  58.         displayGameOver();
  59.         return;
  60.     }

  61.     setTimeout(function onTick() {
  62.         clearCanvas();
  63.         drawFood();
  64.         moveSnake();
  65.         drawSnake();
  66.         main();
  67.     }, 100);
  68. }

  69. function changeDirection(event) {
  70.     const LEFT_KEY = 37;
  71.     const RIGHT_KEY = 39;
  72.     const UP_KEY = 38;
  73.     const DOWN_KEY = 40;

  74.     const keyPressed = event.keyCode;
  75.     const goingUp = dy === -10;
  76.     const goingDown = dy === 10;
  77.     const goingRight = dx === 10;
  78.     const goingLeft = dx === -10;

  79.     if (keyPressed === LEFT_KEY && !goingRight) {
  80.         dx = -10;
  81.         dy = 0;
  82.     }

  83.     if (keyPressed === UP_KEY && !goingDown) {
  84.         dx = 0;
  85.         dy = -10;
  86.     }

  87.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  88.         dx = 10;
  89.         dy = 0;
  90.     }

  91.     if (keyPressed === DOWN_KEY && !goingUp) {
  92.         dx = 0;
  93.         dy = 10;
  94.     }
  95. }

  96. // 显示游戏结束
  97. function displayGameOver() {
  98.     document.getElementById('gameOverText').classList.remove('hidden');
  99.     document.getElementById('startButton').style.display = 'block';
  100. }

  101. function startGame() {
  102.     snake = [{ x: 50, y: 50 }];
  103.     score = 0;
  104.     dx = 10;
  105.     dy = 0;
  106.     gameOver = false;
  107.     food = randomFoodPosition();
  108.     document.getElementById('gameOverText').classList.add('hidden');
  109.     document.getElementById('startButton').style.display = 'none';
  110.     main();
  111. }

  112. food = randomFoodPosition();
  113. main();
复制代码


### 解释调整内容:

1. **HTML**:
    - 添加了一个 `<div id="gameOverText" class="hidden">` 用于显示“游戏结束!”信息。
    - 更新了按钮的点击事件为 `onclick="startGame()"`。
   
2. **CSS**:
    - 更新了 `#gameOverText` 样式,确保它默认隐藏,并在需要的时候显示。
    - 确保 `#startButton` 和 `#gameOverText` 在样式上有合理的间距。

3. **JavaScript**:
    - 添加了 `displayGameOver` 函数来显示“游戏结束!”信息和按钮。
    - 更新了 `startGame` 函数以重置游戏状态并隐藏“游戏结束!”信息和按钮。

现在,游戏结束后,“开始游戏”按钮将显示在“游戏结束!”文字的下方。希望这些修改能满足你的需求!如果还有其他问题,尽管问我哦!
作者: 张复礼    时间: 2024-8-6 14:21
游戏结束后,显示“很遗憾!游戏结束”,并显示得分
作者: kaia    时间: 2024-8-6 14:23
张复礼 发表于 2024-08-06 14:21
游戏结束后,显示“很遗憾!游戏结束”,并显示得分 ...


好的,让我们在游戏结束时更清晰地显示“很遗憾!游戏结束”,并显示得分。我们会在HTML中添加一个用于显示游戏结束信息的元素,并在JavaScript中更新其内容。

### 修改后的 HTML 代码

首先,更新你的 `index.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.     <canvas id="gameCanvas" width="400" height="400"></canvas>
  11.     <div id="gameOverText" class="hidden">很遗憾!游戏结束<br>得分: <span id="score"></span></div>
  12.     <button id="startButton" onclick="startGame()">开始游戏</button>
  13.     <script src="script.js"></script>
  14. </body>
  15. </html>
复制代码


这里我们使用了 `<span id="score"></span>` 来动态显示得分。

### 修改后的 CSS 代码

更新你的 `style.css` 文件,使其如下所示(没有太大变化,只是确保样式合理):

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     background-color: #e0e0e0;
  8.     margin: 0;
  9. }

  10. canvas {
  11.     border: 1px solid black;
  12.     background-color: #f5f5f5;
  13. }

  14. #startButton {
  15.     display: none; /* 默认隐藏 */
  16.     padding: 10px 20px;
  17.     font-size: 20px;
  18.     margin-top: 10px;
  19.     cursor: pointer;
  20.     background-color: #4CAF50; /* 绿色按钮 */
  21.     color: white;
  22.     border: none;
  23.     border-radius: 5px;
  24. }

  25. #startButton:hover {
  26.     background-color: #45a049; /* 更深的绿色 */
  27. }

  28. #gameOverText {
  29.     font-size: 24px;
  30.     color: red;
  31.     text-align: center;
  32.     margin-top: 20px;
  33.     display: none; /* 默认隐藏 */
  34. }
复制代码


### 修改后的 JavaScript 代码

接下来,更新 `script.js` 文件,使其如下所示:

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

  3. let snake = [{ x: 150, y: 150 }, { x: 140, y: 150 }, { x: 130, y: 150 }, { x: 120, y: 150 }, { x: 110, y: 150 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     // 检测碰壁
  35.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  36.         gameOver = true;
  37.         return;
  38.     }

  39.     snake.unshift(head);

  40.     // 检查是否吃到食物
  41.     if (head.x === food.x && head.y === food.y) {
  42.         score++;
  43.         food = randomFoodPosition();
  44.     } else {
  45.         snake.pop();
  46.     }
  47. }

  48. function collision(head) {
  49.     for (let i = 1; i < snake.length; i++) {
  50.         if (snake[i].x === head.x && snake[i].y === head.y) {
  51.             return true;
  52.         }
  53.     }
  54.     return false;
  55. }

  56. function main() {
  57.     if (gameOver) {
  58.         displayGameOver();
  59.         return;
  60.     }

  61.     setTimeout(function onTick() {
  62.         clearCanvas();
  63.         drawFood();
  64.         moveSnake();
  65.         drawSnake();
  66.         main();
  67.     }, 100);
  68. }

  69. function changeDirection(event) {
  70.     const LEFT_KEY = 37;
  71.     const RIGHT_KEY = 39;
  72.     const UP_KEY = 38;
  73.     const DOWN_KEY = 40;

  74.     const keyPressed = event.keyCode;
  75.     const goingUp = dy === -10;
  76.     const goingDown = dy === 10;
  77.     const goingRight = dx === 10;
  78.     const goingLeft = dx === -10;

  79.     if (keyPressed === LEFT_KEY && !goingRight) {
  80.         dx = -10;
  81.         dy = 0;
  82.     }

  83.     if (keyPressed === UP_KEY && !goingDown) {
  84.         dx = 0;
  85.         dy = -10;
  86.     }

  87.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  88.         dx = 10;
  89.         dy = 0;
  90.     }

  91.     if (keyPressed === DOWN_KEY && !goingUp) {
  92.         dx = 0;
  93.         dy = 10;
  94.     }
  95. }

  96. // 显示游戏结束
  97. function displayGameOver() {
  98.     document.getElementById('gameOverText').classList.remove('hidden');
  99.     document.getElementById('score').innerText = score;
  100.     document.getElementById('startButton').style.display = 'block';
  101. }

  102. function startGame() {
  103.     snake = [{ x: 150, y: 150 }, { x: 140, y: 150 }, { x: 130, y: 150 }, { x: 120, y: 150 }, { x: 110, y: 150 }];
  104.     score = 0;
  105.     dx = 10;
  106.     dy = 0;
  107.     gameOver = false;
  108.     food = randomFoodPosition();
  109.     document.getElementById('gameOverText').classList.add('hidden');
  110.     document.getElementById('startButton').style.display = 'none';
  111.     main();
  112. }

  113. food = randomFoodPosition();
  114. main();
复制代码


### 解释调整内容:

1. **HTML**:
    - 添加了一个用于显示“很遗憾!游戏结束”和得分信息的 `<span id="score"></span>`。
   
2. **CSS**:
    - 添加了 `#gameOverText` 的样式,确保它在需要的时候显示,并且居中显示文本。

3. **JavaScript**:
    - 在 `displayGameOver` 函数中更新了 `gameOverText` 的内容以包含得分。
    - 确保游戏结束时,“游戏结束!”信息和按钮一同显示。

现在,当游戏结束时,会显示“很遗憾!游戏结束”并显示得分,同时“开始游戏”按钮也会出现在下方。希望这些修改能满足你的需求!如果还有其他问题,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-6 14:54
如何修改这句代码,让“开始游戏”按钮出现在界面的中间。<button id="startButton" onclick="startGame()">开始游戏</button>
作者: kaia    时间: 2024-8-6 14:54
张复礼 发表于 2024-08-06 14:54
如何修改这句代码,让“开始游戏”按钮出现在界面的中 ...


要让“开始游戏”按钮出现在界面的中间,可以通过修改CSS样式来实现。我们将使用Flexbox布局,使按钮居中,同时确保其他元素也在正确的位置。

### 修改后的 HTML 代码

确保 `index.html` 文件如下所示:

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>贪吃蛇游戏</title>
  6.     <link rel="stylesheet" href="style.css">
  7. </head>
  8. <body>
  9.     <h1>贪吃蛇游戏</h1>
  10.     <div id="gameContainer">
  11.         <canvas id="gameCanvas" width="400" height="400"></canvas>
  12.         <div id="gameOverText" class="hidden">很遗憾!游戏结束<br>得分: <span id="score">0</span></div>
  13.         <button id="startButton" onclick="startGame()">开始游戏</button>
  14.     </div>
  15.     <script src="script.js"></script>
  16. </body>
  17. </html>
复制代码


### 修改后的 CSS 代码

更新 `style.css` 文件,使其如下所示:

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     background-color: #e0e0e0;
  8.     margin: 0;
  9. }

  10. h1 {
  11.     margin-bottom: 20px;
  12. }

  13. #gameContainer {
  14.     display: flex;
  15.     flex-direction: column;
  16.     align-items: center;
  17. }

  18. canvas {
  19.     border: 1px solid black;
  20.     background-color: #f5f5f5;
  21. }

  22. #startButton {
  23.     display: none; /* 默认隐藏 */
  24.     padding: 10px 20px;
  25.     font-size: 20px;
  26.     margin-top: 20px;
  27.     cursor: pointer;
  28.     background-color: #4CAF50; /* 绿色按钮 */
  29.     color: white;
  30.     border: none;
  31.     border-radius: 5px;
  32. }

  33. #startButton:hover {
  34.     background-color: #45a049; /* 更深的绿色 */
  35. }

  36. #gameOverText {
  37.     font-size: 24px;
  38.     color: red;
  39.     text-align: center;
  40.     margin-top: 20px;
  41.     display: none; /* 默认隐藏 */
  42. }

  43. .hidden {
  44.     display: none;
  45. }
复制代码


### 修改后的 JavaScript 代码

确保 `script.js` 文件如下所示:

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

  3. let snake = [{ x: 50, y: 50 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     // 检测碰壁
  35.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  36.         gameOver = true;
  37.         return;
  38.     }

  39.     snake.unshift(head);

  40.     // 检查是否吃到食物
  41.     if (head.x === food.x && head.y === food.y) {
  42.         score++;
  43.         food = randomFoodPosition();
  44.     } else {
  45.         snake.pop();
  46.     }
  47. }

  48. function collision(head) {
  49.     for (let i = 1; i < snake.length; i++) {
  50.         if (snake[i].x === head.x && snake[i].y === head.y) {
  51.             return true;
  52.         }
  53.     }
  54.     return false;
  55. }

  56. function main() {
  57.     if (gameOver) {
  58.         displayGameOver();
  59.         return;
  60.     }

  61.     setTimeout(function onTick() {
  62.         clearCanvas();
  63.         drawFood();
  64.         moveSnake();
  65.         drawSnake();
  66.         main();
  67.     }, 100);
  68. }

  69. function changeDirection(event) {
  70.     const LEFT_KEY = 37;
  71.     const RIGHT_KEY = 39;
  72.     const UP_KEY = 38;
  73.     const DOWN_KEY = 40;

  74.     const keyPressed = event.keyCode;
  75.     const goingUp = dy === -10;
  76.     const goingDown = dy === 10;
  77.     const goingRight = dx === 10;
  78.     const goingLeft = dx === -10;

  79.     if (keyPressed === LEFT_KEY && !goingRight) {
  80.         dx = -10;
  81.         dy = 0;
  82.     }

  83.     if (keyPressed === UP_KEY && !goingDown) {
  84.         dx = 0;
  85.         dy = -10;
  86.     }

  87.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  88.         dx = 10;
  89.         dy = 0;
  90.     }

  91.     if (keyPressed === DOWN_KEY && !goingUp) {
  92.         dx = 0;
  93.         dy = 10;
  94.     }
  95. }

  96. // 显示游戏结束
  97. function displayGameOver() {
  98.     document.getElementById('gameOverText').classList.remove('hidden');
  99.     document.getElementById('score').innerText = score;
  100.     document.getElementById('startButton').style.display = 'block';
  101. }

  102. function startGame() {
  103.     snake = [{ x: 50, y: 50 }];
  104.     score = 0;
  105.     dx = 10;
  106.     dy = 0;
  107.     gameOver = false;
  108.     food = randomFoodPosition();
  109.     document.getElementById('gameOverText').classList.add('hidden');
  110.     document.getElementById('startButton').style.display = 'none';
  111.     main();
  112. }

  113. food = randomFoodPosition();
  114. main();
复制代码


### 解释调整内容:

1. **HTML**:
    - 添加了一个 `div` 容器 (`#gameContainer`) 来包含 canvas、游戏结束信息和按钮。
   
2. **CSS**:
    - 使用 `#gameContainer` 居中排列元素。
    - 确保 canvas 和按钮等元素在布局上合理安排。

3. **JavaScript**:
    - 确保游戏结束时,更新和显示游戏结束信息以及按钮。
    - 确保重新开始游戏时,隐藏游戏结束信息和按钮。

这样,“开始游戏”按钮将会出现在界面的中间,并在游戏结束后显示,期待你满意这个版本的改动!如果还有任何问题,请随时告知哦!
作者: 张复礼    时间: 2024-8-6 14:59
修改这句代码 ctx.fillText("游戏结束!得分: " + score, canvas.width / 4, canvas.height / 2);
让“游戏结束!和”得分“分成两行显示。
作者: kaia    时间: 2024-8-6 15:00
张复礼 发表于 2024-08-06 14:59
修改这句代码 ctx.fillText("游戏结束!得分: " + sco ...


要让“游戏结束!”和“得分”分成两行显示,可以在canvas上绘制多行文本。我们可以通过调用 `ctx.fillText` 两次,分别绘制两行文本。但是为了更整齐,请确保计算好每行的位置。

以下是修改后的JavaScript代码:

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

  3. let snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. // 随机生成食物位置
  11. function randomFoodPosition() {
  12.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  13.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  14.     return { x, y };
  15. }

  16. // 清理画布
  17. function clearCanvas() {
  18.     ctx.fillStyle = "white";
  19.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  20. }

  21. // 绘制蛇
  22. function drawSnake() {
  23.     snake.forEach(drawSnakePart);
  24. }

  25. // 绘制蛇的部分
  26. function drawSnakePart(snakePart) {
  27.     ctx.fillStyle = 'lightgreen';
  28.     ctx.strokeStyle = 'darkgreen';
  29.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  30.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  31. }

  32. // 绘制食物
  33. function drawFood() {
  34.     ctx.fillStyle = 'red';
  35.     ctx.fillRect(food.x, food.y, 10, 10);
  36. }

  37. // 移动蛇
  38. function moveSnake() {
  39.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  40.     // 检测碰壁
  41.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  42.         gameOver = true;
  43.         return;
  44.     }

  45.     snake.unshift(head);

  46.     // 检查是否吃到食物
  47.     if (head.x === food.x && head.y === food.y) {
  48.         score++;
  49.         food = randomFoodPosition();
  50.     } else {
  51.         snake.pop();
  52.     }
  53. }

  54. // 检测自身碰撞
  55. function collision(head) {
  56.     for (let i = 1; i < snake.length; i++) {
  57.         if (snake[i].x === head.x && snake[i].y === head.y) {
  58.             return true;
  59.         }
  60.     }
  61.     return false;
  62. }

  63. // 主循环函数
  64. function main() {
  65.     if (gameOver) {
  66.         displayGameOver();
  67.         return;
  68.     }

  69.     setTimeout(function onTick() {
  70.         clearCanvas();
  71.         drawFood();
  72.         moveSnake();
  73.         drawSnake();
  74.         main();
  75.     }, 100);
  76. }

  77. // 方向控制函数
  78. function changeDirection(event) {
  79.     const LEFT_KEY = 37;
  80.     const RIGHT_KEY = 39;
  81.     const UP_KEY = 38;
  82.     const DOWN_KEY = 40;

  83.     const keyPressed = event.keyCode;
  84.     const goingUp = dy === -10;
  85.     const goingDown = dy === 10;
  86.     const goingRight = dx === 10;
  87.     const goingLeft = dx === -10;

  88.     if (keyPressed === LEFT_KEY && !goingRight) {
  89.         dx = -10;
  90.         dy = 0;
  91.     }

  92.     if (keyPressed === UP_KEY && !goingDown) {
  93.         dx = 0;
  94.         dy = -10;
  95.     }

  96.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  97.         dx = 10;
  98.         dy = 0;
  99.     }

  100.     if (keyPressed === DOWN_KEY && !goingUp) {
  101.         dx = 0;
  102.         dy = 10;
  103.     }
  104. }

  105. // 显示游戏结束
  106. function displayGameOver() {
  107.     ctx.fillStyle = "black";
  108.     ctx.font = "30px Arial";

  109.     // 绘制“游戏结束!”
  110.     ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);

  111.     // 绘制得分
  112.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);

  113.     document.getElementById('startButton').style.display = 'block';
  114. }

  115. function startGame() {
  116.     snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  117.     score = 0;
  118.     dx = 10;
  119.     dy = 0;
  120.     gameOver = false;
  121.     food = randomFoodPosition();
  122.     document.getElementById('gameOverText').classList.add('hidden');
  123.     document.getElementById('startButton').style.display = 'none';
  124.     main();
  125. }

  126. food = randomFoodPosition();
  127. main();
复制代码


### 解释修改内容:

1. **`displayGameOver`** 函数:
    - 增加了两个 `ctx.fillText` 调用,一个用于绘制“游戏结束!”,另一个用于绘制得分。
    - 调整了每个 `fillText` 的位置,使其分别对应canvas的中央(水平居中)并分成两行显示。

这种方式能让“游戏结束!”和“得分”分成两行显示,并且让“开始游戏”按钮显示在界面的中间。如果还有其他问题或需求,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-6 15:02
在js文件中修改这句代码 ctx.fillText("游戏结束!得分: " + score, canvas.width / 4, canvas.height / 2);
让“游戏结束!和”得分“分成两行显示。
作者: kaia    时间: 2024-8-6 15:02
张复礼 发表于 2024-08-06 15:02
在js文件中修改这句代码 ctx.fillText("游戏结束!得 ...


好的,为了让“游戏结束!”和“得分”分成两行显示,只需在 `ctx.fillText` 中调用两次,并调整它们的垂直位置。以下是如何修改代码:

### 修改后的代码

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

  3. let snake = [{ x: 150, y: 150 }, { x: 140, y: 150 }, { x: 130, y: 150 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  35.         gameOver = true;
  36.         return;
  37.     }

  38.     snake.unshift(head);

  39.     if (head.x === food.x && head.y === food.y) {
  40.         score++;
  41.         food = randomFoodPosition();
  42.     } else {
  43.         snake.pop();
  44.     }
  45. }

  46. function collision(head) {
  47.     for (let i = 1; i < snake.length; i++) {
  48.         if (snake[i].x === head.x && snake[i].y === head.y) {
  49.             return true;
  50.         }
  51.     }
  52.     return false;
  53. }

  54. function main() {
  55.     if (gameOver) {
  56.         displayGameOver();
  57.         return;
  58.     }

  59.     setTimeout(function onTick() {
  60.         clearCanvas();
  61.         drawFood();
  62.         moveSnake();
  63.         drawSnake();
  64.         main();
  65.     }, 100);
  66. }

  67. function changeDirection(event) {
  68.     const LEFT_KEY = 37;
  69.     const RIGHT_KEY = 39;
  70.     const UP_KEY = 38;
  71.     const DOWN_KEY = 40;

  72.     const keyPressed = event.keyCode;
  73.     const goingUp = dy === -10;
  74.     const goingDown = dy === 10;
  75.     const goingRight = dx === 10;
  76.     const goingLeft = dx === -10;

  77.     if (keyPressed === LEFT_KEY && !goingRight) {
  78.         dx = -10;
  79.         dy = 0;
  80.     }

  81.     if (keyPressed === UP_KEY && !goingDown) {
  82.         dx = 0;
  83.         dy = -10;
  84.     }

  85.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  86.         dx = 10;
  87.         dy = 0;
  88.     }

  89.     if (keyPressed === DOWN_KEY && !goingUp) {
  90.         dx = 0;
  91.         dy = 10;
  92.     }
  93. }

  94. // 显示游戏结束
  95. function displayGameOver() {
  96.     ctx.fillStyle = "black";
  97.     ctx.font = "30px Arial";

  98.     // 绘制“游戏结束!”位于中心稍上方
  99.     ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);

  100.     // 绘制得分位于中心稍下方
  101.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);

  102.     document.getElementById('startButton').style.display = 'block';
  103. }

  104. function startGame() {
  105.     snake = [{ x: 150, y: 150 }, { x: 140, y: 150 }, { x: 130, y: 150 }];
  106.     score = 0;
  107.     dx = 10;
  108.     dy = 0;
  109.     gameOver = false;
  110.     food = randomFoodPosition();
  111.     document.getElementById('startButton').style.display = 'none';
  112.     main();
  113. }

  114. food = randomFoodPosition();
  115. main();
复制代码


### 解释修改内容:

- **`ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);`**:这行代码绘制“游戏结束!”文本,位于画布的水平中央位置,稍微向上调整,使其在画布中央偏上的位置。
  
- **`ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);`**:这行代码绘制得分文本,位于画布的水平中央位置,稍微向下调整,使其在画布中央偏下的位置。

通过这种方法,“游戏结束!”和“得分”会显示在两行,并且在画布的中心位置。

希望这些修改能满足你的需求!如果你有其他问题或需要进一步的帮助,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-6 15:08
把background-color: #45a049;改成浅蓝色
作者: kaia    时间: 2024-8-6 15:08
张复礼 发表于 2024-08-06 15:08
把background-color: #45a049;改成浅蓝色


好的,我们可以把 `background-color` 改成浅蓝色。在CSS中,可以使用颜色名称或者16进制的颜色代码来实现。浅蓝色在16进制表示为 `#ADD8E6`,当然你也可以直接使用颜色名称 `lightblue`。

### 修改后的 CSS 代码:

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     background-color: #e0e0e0;
  8.     margin: 0;
  9. }

  10. h1 {
  11.     margin-bottom: 20px;
  12. }

  13. #gameContainer {
  14.     display: flex;
  15.     flex-direction: column;
  16.     align-items: center;
  17. }

  18. canvas {
  19.     border: 1px solid black;
  20.     background-color: #f5f5f5;
  21. }

  22. #startButton {
  23.     display: none; /* 默认隐藏 */
  24.     padding: 10px 20px;
  25.     font-size: 20px;
  26.     margin-top: 20px;
  27.     cursor: pointer;
  28.     background-color: #4CAF50; /* 绿色按钮 */
  29.     color: white;
  30.     border: none;
  31.     border-radius: 5px;
  32. }

  33. #startButton:hover {
  34.     background-color: #ADD8E6; /* 浅蓝色 */
  35. }

  36. #gameOverText {
  37.     font-size: 24px;
  38.     color: red;
  39.     text-align: center;
  40.     margin-top: 20px;
  41.     display: none; /* 默认隐藏 */
  42. }

  43. .hidden {
  44.     display: none;
  45. }
复制代码


### 整合的 HTML 和 JavaScript 代码:

为了确保所有代码正确,这里是整合后的HTML和JavaScript代码:

#### HTML (`index.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 id="gameContainer">
  12.         <canvas id="gameCanvas" width="400" height="400"></canvas>
  13.         <div id="gameOverText" class="hidden">
  14.             <p>很遗憾!游戏结束</p>
  15.             <p>得分: <span id="score">0</span></p>
  16.         </div>
  17.         <button id="startButton" onclick="startGame()">开始游戏</button>
  18.     </div>
  19.     <script src="script.js"></script>
  20. </body>
  21. </html>
复制代码


#### JavaScript (`script.js`):

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

  3. let snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. document.addEventListener("keydown", changeDirection);

  10. function randomFoodPosition() {
  11.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  12.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  13.     return { x, y };
  14. }

  15. function clearCanvas() {
  16.     ctx.fillStyle = "white";
  17.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  18. }

  19. function drawSnake() {
  20.     snake.forEach(drawSnakePart);
  21. }

  22. function drawSnakePart(snakePart) {
  23.     ctx.fillStyle = 'lightgreen';
  24.     ctx.strokeStyle = 'darkgreen';
  25.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  26.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  27. }

  28. function drawFood() {
  29.     ctx.fillStyle = 'red';
  30.     ctx.fillRect(food.x, food.y, 10, 10);
  31. }

  32. function moveSnake() {
  33.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  34.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  35.         gameOver = true;
  36.         return;
  37.     }

  38.     snake.unshift(head);

  39.     if (head.x === food.x && head.y === food.y) {
  40.         score++;
  41.         food = randomFoodPosition();
  42.     } else {
  43.         snake.pop();
  44.     }
  45. }

  46. function collision(head) {
  47.     for (let i = 1; i < snake.length; i++) {
  48.         if (snake[i].x === head.x && snake[i].y === head.y) {
  49.             return true;
  50.         }
  51.     }
  52.     return false;
  53. }

  54. function main() {
  55.     if (gameOver) {
  56.         displayGameOver();
  57.         return;
  58.     }

  59.     setTimeout(function onTick() {
  60.         clearCanvas();
  61.         drawFood();
  62.         moveSnake();
  63.         drawSnake();
  64.         main();
  65.     }, 100);
  66. }

  67. function changeDirection(event) {
  68.     const LEFT_KEY = 37;
  69.     const RIGHT_KEY = 39;
  70.     const UP_KEY = 38;
  71.     const DOWN_KEY = 40;

  72.     const keyPressed = event.keyCode;
  73.     const goingUp = dy === -10;
  74.     const goingDown = dy === 10;
  75.     const goingRight = dx === 10;
  76.     const goingLeft = dx === -10;

  77.     if (keyPressed === LEFT_KEY && !goingRight) {
  78.         dx = -10;
  79.         dy = 0;
  80.     }

  81.     if (keyPressed === UP_KEY && !goingDown) {
  82.         dx = 0;
  83.         dy = -10;
  84.     }

  85.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  86.         dx = 10;
  87.         dy = 0;
  88.     }

  89.     if (keyPressed === DOWN_KEY && !goingUp) {
  90.         dx = 0;
  91.         dy = 10;
  92.     }
  93. }

  94. function displayGameOver() {
  95.     ctx.fillStyle = "black";
  96.     ctx.font = "30px Arial";
  97.     ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);
  98.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
  99.     document.getElementById('startButton').style.display = 'block';
  100. }

  101. function startGame() {
  102.     snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  103.     score = 0;
  104.     dx = 10;
  105.     dy = 0;
  106.     gameOver = false;
  107.     food = randomFoodPosition();
  108.     document.getElementById('startButton').style.display = 'none';
  109.     main();
  110. }

  111. food = randomFoodPosition();
  112. main();
复制代码


这样,你的“开始游戏”按钮在鼠标悬停时会变成浅蓝色(`lightblue`或颜色代码 `#ADD8E6`)。如果需要进一步调整或有其他问题,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-7 19:15
你好,可以用函数来帮我实现蛇吃到食物之后出现音效吗?
作者: kaia    时间: 2024-8-7 19:15
张复礼 发表于 2024-08-07 19:15
你好,可以用函数来帮我实现蛇吃到食物之后出现音效吗 ...


好的,小朋友!我们可以用JavaScript在蛇吃到食物的时候播放音效。首先,你需要一段音效文件(比如一个 `.mp3` 或 `.wav` 文件),然后在合适的时机播放它。

假设你有一个叫做 `eat.mp3` 的音效文件,可以将其放置在与 `index.html` 和 `script.js` 同一个目录中。接下来,我们将使用一个函数来播放这个音效,并在蛇吃到食物的时候调用这个函数。

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

确保 `eat.mp3` 文件放置在项目目录中。

### 第二步:修改 JavaScript 代码

在你的 `script.js` 文件中,添加一个函数来播放音效,并在蛇吃到食物时调用这个函数。

#### 修改后的 `script.js` 文件:

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

  3. let snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. // 创建音效对象
  10. const eatSound = new Audio('eat.mp3');

  11. document.addEventListener("keydown", changeDirection);

  12. function randomFoodPosition() {
  13.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  14.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  15.     return { x, y };
  16. }

  17. function clearCanvas() {
  18.     ctx.fillStyle = "white";
  19.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  20. }

  21. function drawSnake() {
  22.     snake.forEach(drawSnakePart);
  23. }

  24. function drawSnakePart(snakePart) {
  25.     ctx.fillStyle = 'lightgreen';
  26.     ctx.strokeStyle = 'darkgreen';
  27.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  28.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  29. }

  30. function drawFood() {
  31.     ctx.fillStyle = 'red';
  32.     ctx.fillRect(food.x, food.y, 10, 10);
  33. }

  34. function moveSnake() {
  35.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  36.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  37.         gameOver = true;
  38.         return;
  39.     }

  40.     snake.unshift(head);

  41.     if (head.x === food.x && head.y === food.y) {
  42.         score++;
  43.         food = randomFoodPosition();
  44.         playEatSound(); // 播放音效
  45.     } else {
  46.         snake.pop();
  47.     }
  48. }

  49. function collision(head) {
  50.     for (let i = 1; i < snake.length; i++) {
  51.         if (snake[i].x === head.x && snake[i].y === head.y) {
  52.             return true;
  53.         }
  54.     }
  55.     return false;
  56. }

  57. // 播放吃食物的音效
  58. function playEatSound() {
  59.     eatSound.play();
  60. }

  61. function main() {
  62.     if (gameOver) {
  63.         displayGameOver();
  64.         return;
  65.     }

  66.     setTimeout(function onTick() {
  67.         clearCanvas();
  68.         drawFood();
  69.         moveSnake();
  70.         drawSnake();
  71.         main();
  72.     }, 100);
  73. }

  74. function changeDirection(event) {
  75.     const LEFT_KEY = 37;
  76.     const RIGHT_KEY = 39;
  77.     const UP_KEY = 38;
  78.     const DOWN_KEY = 40;

  79.     const keyPressed = event.keyCode;
  80.     const goingUp = dy === -10;
  81.     const goingDown = dy === 10;
  82.     const goingRight = dx === 10;
  83.     const goingLeft = dx === -10;

  84.     if (keyPressed === LEFT_KEY && !goingRight) {
  85.         dx = -10;
  86.         dy = 0;
  87.     }

  88.     if (keyPressed === UP_KEY && !goingDown) {
  89.         dx = 0;
  90.         dy = -10;
  91.     }

  92.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  93.         dx = 10;
  94.         dy = 0;
  95.     }

  96.     if (keyPressed === DOWN_KEY && !goingUp) {
  97.         dx = 0;
  98.         dy = 10;
  99.     }
  100. }

  101. function displayGameOver() {
  102.     ctx.fillStyle = "black";
  103.     ctx.font = "30px Arial";
  104.     ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);
  105.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
  106.     document.getElementById('startButton').style.display = 'block';
  107. }

  108. function startGame() {
  109.     snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  110.     score = 0;
  111.     dx = 10;
  112.     dy = 0;
  113.     gameOver = false;
  114.     food = randomFoodPosition();
  115.     document.getElementById('startButton').style.display = 'none';
  116.     main();
  117. }

  118. food = randomFoodPosition();
  119. main();
复制代码


这里是详细解释:

1. **音效对象创建**:
  
  1. const eatSound = new Audio('eat.mp3');
复制代码

   这行代码创建了一个新的音频对象,并载入 `eat.mp3` 文件。

2. **播放音效函数**:
  
  1. function playEatSound() {
  2.        eatSound.play();
  3.    }
复制代码

   这是一个简单的函数,用于播放音效。

3. **在蛇吃到食物时播放音效**:
  
  1. if (head.x === food.x && head.y === food.y) {
  2.        score++;
  3.        food = randomFoodPosition();
  4.        playEatSound(); // 播放音效
  5.    } else {
  6.        snake.pop();
  7.    }
复制代码

   在这段代码中,当蛇的头部位置与食物位置相同时,调用 `playEatSound()` 函数播放音效。

现在,当蛇吃到食物时,会播放 `eat.mp3` 音效。希望你喜欢这个新功能,如果还有任何问题或需要进一步的帮助,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-7 19:24
你好,可以用函数来帮我实现游戏过程中持续出现背景音乐吗?
作者: kaia    时间: 2024-8-7 19:25
张复礼 发表于 2024-08-07 19:24
你好,可以用函数来帮我实现游戏过程中持续出现背景音 ...


好的,小朋友!我们可以在游戏过程中添加背景音乐,让你的贪吃蛇游戏更有趣。我们将使用一个音频文件来作为背景音乐,并在游戏开始时播放它,游戏结束时暂停它。

假设你有一个叫做 `background.mp3` 的背景音乐文件,可以将其放置在与 `index.html` 和 `script.js` 同一个目录中。接下来,我们将使用一个函数来播放和控制这个背景音乐。

### 第一步:准备背景音乐文件

确保 `background.mp3` 文件放置在项目目录中。

### 第二步:修改 JavaScript 代码

在你的 `script.js` 文件中,添加一个函数来播放背景音乐,并在游戏开始和结束时进行相应的操作。

#### 修改后的 `script.js` 文件:

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

  3. let snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. // 创建音效对象
  10. const eatSound = new Audio('eat.mp3');

  11. // 创建背景音乐对象
  12. const backgroundMusic = new Audio('background.mp3');
  13. backgroundMusic.loop = true; // 设置循环播放

  14. document.addEventListener("keydown", changeDirection);

  15. function randomFoodPosition() {
  16.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  17.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  18.     return { x, y };
  19. }

  20. function clearCanvas() {
  21.     ctx.fillStyle = "white";
  22.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  23. }

  24. function drawSnake() {
  25.     snake.forEach(drawSnakePart);
  26. }

  27. function drawSnakePart(snakePart) {
  28.     ctx.fillStyle = 'lightgreen';
  29.     ctx.strokeStyle = 'darkgreen';
  30.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  31.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  32. }

  33. function drawFood() {
  34.     ctx.fillStyle = 'red';
  35.     ctx.fillRect(food.x, food.y, 10, 10);
  36. }

  37. function moveSnake() {
  38.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  39.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  40.         gameOver = true;
  41.         return;
  42.     }

  43.     snake.unshift(head);

  44.     if (head.x === food.x && head.y === food.y) {
  45.         score++;
  46.         food = randomFoodPosition();
  47.         playEatSound(); // 播放音效
  48.     } else {
  49.         snake.pop();
  50.     }
  51. }

  52. function collision(head) {
  53.     for (let i = 1; i < snake.length; i++) {
  54.         if (snake[i].x === head.x && snake[i].y === head.y) {
  55.             return true;
  56.         }
  57.     }
  58.     return false;
  59. }

  60. // 播放吃食物的音效
  61. function playEatSound() {
  62.     eatSound.play();
  63. }

  64. // 播放背景音乐
  65. function playBackgroundMusic() {
  66.     backgroundMusic.play();
  67. }

  68. // 停止背景音乐
  69. function stopBackgroundMusic() {
  70.     backgroundMusic.pause();
  71.     backgroundMusic.currentTime = 0; // 重置音乐到开头
  72. }

  73. function main() {
  74.     if (gameOver) {
  75.         displayGameOver();
  76.         return;
  77.     }

  78.     setTimeout(function onTick() {
  79.         clearCanvas();
  80.         drawFood();
  81.         moveSnake();
  82.         drawSnake();
  83.         main();
  84.     }, 100);
  85. }

  86. function changeDirection(event) {
  87.     const LEFT_KEY = 37;
  88.     const RIGHT_KEY = 39;
  89.     const UP_KEY = 38;
  90.     const DOWN_KEY = 40;

  91.     const keyPressed = event.keyCode;
  92.     const goingUp = dy === -10;
  93.     const goingDown = dy === 10;
  94.     const goingRight = dx === 10;
  95.     const goingLeft = dx === -10;

  96.     if (keyPressed === LEFT_KEY && !goingRight) {
  97.         dx = -10;
  98.         dy = 0;
  99.     }

  100.     if (keyPressed === UP_KEY && !goingDown) {
  101.         dx = 0;
  102.         dy = -10;
  103.     }

  104.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  105.         dx = 10;
  106.         dy = 0;
  107.     }

  108.     if (keyPressed === DOWN_KEY && !goingUp) {
  109.         dx = 0;
  110.         dy = 10;
  111.     }
  112. }

  113. function displayGameOver() {
  114.     ctx.fillStyle = "black";
  115.     ctx.font = "30px Arial";
  116.     ctx.fillText("游戏结束!", canvas.width / 2 - 75, canvas.height / 2 - 20);
  117.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
  118.     document.getElementById('startButton').style.display = 'block';
  119.     stopBackgroundMusic(); // 停止背景音乐
  120. }

  121. function startGame() {
  122.     snake = [{x: 150, y: 150}, {x: 140, y: 150}, {x: 130, y: 150}];
  123.     score = 0;
  124.     dx = 10;
  125.     dy = 0;
  126.     gameOver = false;
  127.     food = randomFoodPosition();
  128.     document.getElementById('startButton').style.display = 'none';
  129.     playBackgroundMusic(); // 播放背景音乐
  130.     main();
  131. }

  132. food = randomFoodPosition();
  133. main();
复制代码


### 第三步:修改 HTML 代码

如果你还没有一个 "开始游戏" 按钮,请确保在 `index.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.             align-items: center;
  11.             justify-content: center;
  12.             height: 100vh;
  13.             background-color: #e0e0e0;
  14.             margin: 0;
  15.         }
  16.         h1 {
  17.             margin-bottom: 20px;
  18.         }
  19.         #gameContainer {
  20.             display: flex;
  21.             flex-direction: column;
  22.             align-items: center;
  23.         }
  24.         canvas {
  25.             border: 1px solid black;
  26.             background-color: #f5f5f5;
  27.         }
  28.         #startButton {
  29.             display: none; /* 默认隐藏 */
  30.             padding: 10px 20px;
  31.             font-size: 20px;
  32.             margin-top: 20px;
  33.             cursor: pointer;
  34.             background-color: #4CAF50; /* 绿色按钮 */
  35.             color: white;
  36.             border: none;
  37.             border-radius: 5px;
  38.         }
  39.         #startButton:hover {
  40.             background-color: #ADD8E6; /* 浅蓝色 */
  41.         }
  42.         #gameOverText {
  43.             font-size: 24px;
  44.             color: red;
  45.             text-align: center;
  46.             margin-top: 20px;
  47.             display: none; /* 默认隐藏 */
  48.         }
  49.         .hidden {
  50.             display: none;
  51.         }
  52.     </style>
  53. </head>
  54. <body>
  55.     <h1>贪吃蛇游戏</h1>
  56.     <div id="gameContainer">
  57.         <canvas id="gameCanvas" width="400" height="400"></canvas>
  58.         <div id="gameOverText" class="hidden">
  59.             <p>很遗憾!游戏结束</p>
  60.             <p>得分: <span id="score">0</span></p>
  61.         </div>
  62.         <button id="startButton" onclick="startGame()">开始游戏</button>
  63.     </div>
  64.     <script src="script.js"></script>
  65. </body>
  66. </html>
复制代码


### 解释修改内容:

1. **创建背景音乐对象**:
  
  1. const backgroundMusic = new Audio('background.mp3');
  2.    backgroundMusic.loop = true; // 设置循环播放
复制代码

   这行代码创建了一个新的音频对象,并载入 `background.mp3` 文件,同时设置了循环播放。

2. **播放背景音乐函数**:
  
  1. function playBackgroundMusic() {
  2.        backgroundMusic.play();
  3.    }
复制代码


3. **停止背景音乐函数**:
  
  1. function stopBackgroundMusic() {
  2.        backgroundMusic.pause();
  3.        backgroundMusic.currentTime = 0; // 重置音乐到开头
  4.    }
复制代码


4. **在游戏开始时播放背景音乐**:
  
  1. function startGame() {
  2.        // ... 其他代码
  3.        playBackgroundMusic(); // 播放背景音乐
  4.        main();
  5.    }
复制代码


5. **在游戏结束时停止背景音乐**:
  
  1. function displayGameOver() {
  2.        // ... 其他代码
  3.        stopBackgroundMusic(); // 停止背景音乐
  4.    }
复制代码


通过这些修改,你的游戏在开始时会播放背景音乐,并在游戏结束时停止。如果有任何问题或需要进一步帮助,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-7 19:46
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

let snake = [{ x: 50, y: 50 }];
let food = { x: 0, y: 0 };
let dx = 10;
let dy = 0;
let score = 0;
let gameOver = false;

// 创建音效对象
const eatSound = new Audio('eat.mp3');

// 创建背景音乐对象
const backgroundMusic = new Audio('background.mp3');
backgroundMusic.loop = true; // 设置循环播放

document.addEventListener("keydown", changeDirection);

function randomFoodPosition() {
    const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
    const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
    return { x, y };
}

function clearCanvas() {
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function drawSnake() {
    snake.forEach(drawSnakePart);
}

function drawSnakePart(snakePart) {
    ctx.fillStyle = 'lightgreen';
    ctx.strokeStyle = 'darkgreen';
    ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
    ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
}

function drawFood() {
    ctx.fillStyle = 'lightpink';
    ctx.fillRect(food.x, food.y, 10, 10);
}

function moveSnake() {
    const head = { x: snake[0].x + dx, y: snake[0].y + dy };

    // 检测碰壁
    if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
        gameOver = true;
        return;
    }

    snake.unshift(head);

    // 检查是否吃到食物
    if (head.x === food.x && head.y === food.y) {
        score++;
        food = randomFoodPosition();
        playEatSound(); // 播放音效
    } else {
        snake.pop();
    }
}

function collision(head) {
    for (let i = 1; i < snake.length; i++) {
        if (snake[i].x === head.x && snake[i].y === head.y) {
            return true;
        }
    }
    return false;
}

// 播放吃食物的音效
function playEatSound() {
    eatSound.play();
}

// 播放背景音乐
function playBackgroundMusic() {
    backgroundMusic.play();
}

// 停止背景音乐
function stopBackgroundMusic() {
    backgroundMusic.pause();
    backgroundMusic.currentTime = 0; // 重置音乐到开头
}

function main() {
    if (gameOver) {
        displayGameOver();
        return;
    }

    setTimeout(function onTick() {
        clearCanvas();
        drawFood();
        moveSnake();
        drawSnake();
        main();
    }, 100);
}

function changeDirection(event) {
    const LEFT_KEY = 37;
    const RIGHT_KEY = 39;
    const UP_KEY = 38;
    const DOWN_KEY = 40;

    const keyPressed = event.keyCode;
    const goingUp = dy === -10;
    const goingDown = dy === 10;
    const goingRight = dx === 10;
    const goingLeft = dx === -10;

    if (keyPressed === LEFT_KEY && !goingRight) {
        dx = -10;
        dy = 0;
    }

    if (keyPressed === UP_KEY && !goingDown) {
        dx = 0;
        dy = -10;
    }

    if (keyPressed === RIGHT_KEY && !goingLeft) {
        dx = 10;
        dy = 0;
    }

    if (keyPressed === DOWN_KEY && !goingUp) {
        dx = 0;
        dy = 10;
    }
}

// 显示游戏结束
function displayGameOver() {
    ctx.fillStyle = "pink";
    ctx.font = "30px Arial";
     // 绘制“游戏结束!”位于中心稍上方
    ctx.fillText("很遗憾,游戏结束!", canvas.width / 2 - 115, canvas.height / 2 - 20);
    // 绘制得分位于中心稍下方
    ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
    document.getElementById("startButton").style.display = "block";
    stopBackgroundMusic(); // 停止背景音乐
}


function startGame() {
    snake = [{ x: 50, y: 50 }];
    score = 0;
    dx = 10;
    dy = 0;
    gameOver = false;
    food = randomFoodPosition();
    document.getElementById('startButton').style.display = 'none';
    playBackgroundMusic(); // 播放背景音乐
    main();
}

food = randomFoodPosition();
main();

以上是`script.js` 文件,请找一下无法播放背景音乐的原因是什么?
作者: kaia    时间: 2024-8-7 19:46
张复礼 发表于 2024-08-07 19:46
const canvas = document.getElementById('gameCanvas ...


好的,小朋友!我们来看看为什么背景音乐没有播放。

从代码上看,主要的部分都正确。不过有几个可能的原因会导致背景音乐无法播放:

1. **浏览器的自动播放策略**:有些浏览器默认禁止自动播放音频,除非用户与页面有过交互,比如点击按钮或按键。为了确保背景音乐能在游戏开始时播放,我们可以在用户点击“开始游戏”按钮时触发音乐播放。

2. **文件路径问题**:确保 `background.mp3` 文件确实在与 `index.html` 和 `script.js` 同一个目录中。

3. **音量问题**:确保背景音乐的音量设置为可听范围内。

我们将添加一些调试信息和确保在用户交互后播放背景音乐。

### 确保文件路径和音量

首先,确保你的 `background.mp3` 文件放在正确的位置,并且文件名没有错。同时,可以设置音量以检查是否是因为音量太低。

增加音量设置:
  1. const backgroundMusic = new Audio('background.mp3');
  2. backgroundMusic.loop = true; // 设置循环播放
  3. backgroundMusic.volume = 0.5; // 设置音量为50%
复制代码


### 修改 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.     <link rel="stylesheet" href="style.css">
  8. </head>
  9. <body>
  10.     <h1>贪吃蛇游戏</h1>
  11.     <div id="gameContainer">
  12.         <canvas id="gameCanvas" width="400" height="400"></canvas>
  13.         <div id="gameOverText" class="hidden"></div>
  14.         <button id="startButton" onclick="startGame()">开始游戏</button>
  15.     </div>
  16.     <script src="script.js"></script>
  17. </body>
  18. </html>
复制代码


### 修改 `script.js` 文件

确保在 `startGame` 函数中播放背景音乐,并添加一些调试信息:
  1. const canvas = document.getElementById('gameCanvas');
  2. const ctx = canvas.getContext('2d');

  3. let snake = [{ x: 150, y: 150 }];
  4. let food = { x: 0, y: 0 };
  5. let dx = 10;
  6. let dy = 0;
  7. let score = 0;
  8. let gameOver = false;

  9. // 创建音效对象
  10. const eatSound = new Audio('eat.mp3');

  11. // 创建背景音乐对象
  12. const backgroundMusic = new Audio('background.mp3');
  13. backgroundMusic.loop = true; // 设置循环播放
  14. backgroundMusic.volume = 0.5; // 设置音量为50%

  15. document.addEventListener("keydown", changeDirection);

  16. function randomFoodPosition() {
  17.     const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
  18.     const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
  19.     return { x, y };
  20. }

  21. function clearCanvas() {
  22.     ctx.fillStyle = "white";
  23.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  24. }

  25. function drawSnake() {
  26.     snake.forEach(drawSnakePart);
  27. }

  28. function drawSnakePart(snakePart) {
  29.     ctx.fillStyle = 'lightgreen';
  30.     ctx.strokeStyle = 'darkgreen';
  31.     ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  32.     ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
  33. }

  34. function drawFood() {
  35.     ctx.fillStyle = 'lightpink';
  36.     ctx.fillRect(food.x, food.y, 10, 10);
  37. }

  38. function moveSnake() {
  39.     const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  40.     // 检测碰壁
  41.     if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
  42.         gameOver = true;
  43.         return;
  44.     }

  45.     snake.unshift(head);

  46.     // 检查是否吃到食物
  47.     if (head.x === food.x && head.y === food.y) {
  48.         score++;
  49.         food = randomFoodPosition();
  50.         playEatSound(); // 播放音效
  51.     } else {
  52.         snake.pop();
  53.     }
  54. }

  55. function collision(head) {
  56.     for (let i = 1; i < snake.length; i++) {
  57.         if (snake[i].x === head.x && snake[i].y === head.y) {
  58.             return true;
  59.         }
  60.     }
  61.     return false;
  62. }

  63. // 播放吃食物的音效
  64. function playEatSound() {
  65.     eatSound.play();
  66. }

  67. // 播放背景音乐
  68. function playBackgroundMusic() {
  69.     console.log('播放背景音乐');
  70.     backgroundMusic.play();
  71. }

  72. // 停止背景音乐
  73. function stopBackgroundMusic() {
  74.     console.log('停止背景音乐');
  75.     backgroundMusic.pause();
  76.     backgroundMusic.currentTime = 0; // 重置音乐到开头
  77. }

  78. function main() {
  79.     if (gameOver) {
  80.         displayGameOver();
  81.         return;
  82.     }

  83.     setTimeout(function onTick() {
  84.         clearCanvas();
  85.         drawFood();
  86.         moveSnake();
  87.         drawSnake();
  88.         main();
  89.     }, 100);
  90. }

  91. function changeDirection(event) {
  92.     const LEFT_KEY = 37;
  93.     const RIGHT_KEY = 39;
  94.     const UP_KEY = 38;
  95.     const DOWN_KEY = 40;

  96.     const keyPressed = event.keyCode;
  97.     const goingUp = dy === -10;
  98.     const goingDown = dy === 10;
  99.     const goingRight = dx === 10;
  100.     const goingLeft = dx === -10;

  101.     if (keyPressed === LEFT_KEY && !goingRight) {
  102.         dx = -10;
  103.         dy = 0;
  104.     }

  105.     if (keyPressed === UP_KEY && !goingDown) {
  106.         dx = 0;
  107.         dy = -10;
  108.     }

  109.     if (keyPressed === RIGHT_KEY && !goingLeft) {
  110.         dx = 10;
  111.         dy = 0;
  112.     }

  113.     if (keyPressed === DOWN_KEY && !goingUp) {
  114.         dx = 0;
  115.         dy = 10;
  116.     }
  117. }

  118. // 显示游戏结束
  119. function displayGameOver() {
  120.     ctx.fillStyle = "pink";
  121.     ctx.font = "30px Arial";
  122.     // 绘制“游戏结束!”位于中心稍上方
  123.     ctx.fillText("很遗憾,游戏结束!", canvas.width / 2 - 115, canvas.height / 2 - 20);
  124.     // 绘制得分位于中心稍下方
  125.     ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
  126.     document.getElementById("startButton").style.display = "block";
  127.     stopBackgroundMusic(); // 停止背景音乐
  128. }

  129. function startGame() {
  130.     snake = [{ x: 150, y: 150 }];
  131.     score = 0;
  132.     dx = 10;
  133.     dy = 0;
  134.     gameOver = false;
  135.     food = randomFoodPosition();
  136.     document.getElementById('startButton').style.display = 'none';
  137.     playBackgroundMusic(); // 播放背景音乐
  138.     main();
  139. }

  140. food = randomFoodPosition();
  141. main();
复制代码


### 解释修改内容:
1. **音量设置**:确保背景音乐音量适中。
   
  1. backgroundMusic.volume = 0.5; // 设置音量为50%
复制代码


2. **调试信息**:在 `playBackgroundMusic()` 和 `stopBackgroundMusic()` 函数中添加日志信息,以确认函数是否被调用。
   
  1. function playBackgroundMusic() {
  2.         console.log('播放背景音乐');
  3.         backgroundMusic.play();
  4.     }

  5.     function stopBackgroundMusic() {
  6.         console.log('停止背景音乐');
  7.         backgroundMusic.pause();
  8.         backgroundMusic.currentTime = 0; // 重置音乐到开头
  9.     }
复制代码


3. **确保触发播放**:在用户点击开始游戏按钮时播放背景音乐。

这样,你应该能够在游戏开始时听到背景音乐并在游戏结束时停止播放。如果你仍然遇到问题,请通过开发者工具查看控制台中的日志信息来进行进一步调试。如果需要更多帮助,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-7 19:53
你好,请帮我生成一个火柴人左右躲避障碍物的网页游戏。
作者: kaia    时间: 2024-8-7 19:54
张复礼 发表于 2024-08-07 19:53
你好,请帮我生成一个火柴人左右躲避障碍物的网页游戏 ...


好的,小朋友!我们可以做一个简单的火柴人左右躲避障碍物的网页游戏。这个小游戏将使用HTML、CSS和JavaScript来实现。下面是一个基础的版本,你可以根据需要进一步扩展和美化。

### 第一步:创建 HTML 文件

首先,创建一个HTML文件,命名为 `index.html`,内容如下:

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>火柴人躲避障碍物</title>
  6.     <link rel="stylesheet" type="text/css" href="style.css">
  7. </head>
  8. <body>
  9.     <h1>火柴人躲避障碍物</h1>
  10.     <div id="gameContainer">
  11.         <canvas id="gameCanvas" width="400" height="600"></canvas>
  12.         <div id="gameOverText" class="hidden">游戏结束!</div>
  13.         <button id="restartButton" class="hidden" onclick="startGame()">重新开始</button>
  14.     </div>
  15.     <script src="script.js"></script>
  16. </body>
  17. </html>
复制代码


### 第二步:创建 CSS 文件

接下来,创建一个CSS文件,命名为 `style.css`,内容如下:

  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     justify-content: center;
  6.     height: 100vh;
  7.     margin: 0;
  8.     background-color: #f5f5f5;
  9. }

  10. h1 {
  11.     margin-bottom: 20px;
  12. }

  13. #gameContainer {
  14.     display: flex;
  15.     flex-direction: column;
  16.     align-items: center;
  17.     justify-content: center;
  18. }

  19. #gameCanvas {
  20.     border: 2px solid black;
  21.     background-color: white;
  22. }

  23. .hidden {
  24.     display: none;
  25. }

  26. #gameOverText {
  27.     font-size: 24px;
  28.     color: red;
  29.     margin-top: 20px;
  30. }

  31. #restartButton {
  32.     padding: 10px 20px;
  33.     font-size: 16px;
  34.     margin-top: 10px;
  35.     cursor: pointer;
  36.     background-color: #4CAF50;
  37.     color: white;
  38.     border: none;
  39.     border-radius: 5px;
  40. }

  41. #restartButton:hover {
  42.     background-color: #45a049;
  43. }
复制代码


### 第三步:创建 JavaScript 文件

最后,创建一个JavaScript文件,命名为 `script.js`,内容如下:

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

  3. let player = { x: canvas.width / 2 - 15, y: canvas.height - 60, width: 30, height: 30, dx: 5 };
  4. let obstacles = [];
  5. let gameInterval;
  6. let gameOver = false;

  7. document.addEventListener('keydown', movePlayer);

  8. function startGame() {
  9.     player.x = canvas.width / 2 - 15;
  10.     obstacles = [];
  11.     gameOver = false;
  12.     document.getElementById('gameOverText').classList.add('hidden');
  13.     document.getElementById('restartButton').classList.add('hidden');
  14.     gameInterval = setInterval(updateGame, 20);
  15. }

  16. function updateGame() {
  17.     clearCanvas();
  18.     drawPlayer();
  19.     updateObstacles();
  20.     checkCollision();
  21. }

  22. function clearCanvas() {
  23.     ctx.clearRect(0, 0, canvas.width, canvas.height);
  24. }

  25. function drawPlayer() {
  26.     ctx.fillStyle = 'black';
  27.     ctx.fillRect(player.x, player.y, player.width, player.height);
  28. }

  29. function movePlayer(event) {
  30.     if (event.key === 'ArrowLeft' && player.x > 0) {
  31.         player.x -= player.dx;
  32.     }
  33.     if (event.key === 'ArrowRight' && player.x < canvas.width - player.width) {
  34.         player.x += player.dx;
  35.     }
  36. }

  37. function updateObstacles() {
  38.     if (Math.random() < 0.02) {
  39.         let obstacleX = Math.random() * (canvas.width - 30);
  40.         obstacles.push({ x: obstacleX, y: 0, width: 30, height: 30, dy: 2 });
  41.     }

  42.     ctx.fillStyle = 'red';
  43.     for (let i = 0; i < obstacles.length; i++) {
  44.         let obs = obstacles[i];
  45.         obs.y += obs.dy;
  46.         ctx.fillRect(obs.x, obs.y, obs.width, obs.height);

  47.         if (obs.y > canvas.height) {
  48.             obstacles.splice(i, 1);
  49.             i--;
  50.         }
  51.     }
  52. }

  53. function checkCollision() {
  54.     for (let i = 0; i < obstacles.length; i++) {
  55.         let obs = obstacles[i];
  56.         if (
  57.             player.x < obs.x + obs.width &&
  58.             player.x + player.width > obs.x &&
  59.             player.y < obs.y + obs.height &&
  60.             player.y + player.height > obs.y
  61.         ) {
  62.             endGame();
  63.         }
  64.     }
  65. }

  66. function endGame() {
  67.     clearInterval(gameInterval);
  68.     gameOver = true;
  69.     document.getElementById('gameOverText').classList.remove('hidden');
  70.     document.getElementById('restartButton').classList.remove('hidden');
  71. }

  72. // 启动游戏
  73. startGame();
复制代码


### 代码解释

1. **HTML**:
    - 包含一个画布 (`<canvas>`) 用于绘制游戏,和一个按钮用于重新开始游戏。
   
2. **CSS**:
    - 设置了页面布局、样式以及按钮的外观。

3. **JavaScript**:
    - 初始化玩家(火柴人)和障碍物的位置及属性。
    - `movePlayer` 函数负责移动玩家。
    - `updateGame` 函数是主要的游戏循环,负责更新游戏状态。
    - `checkCollision` 函数检查玩家是否碰到了障碍物。
    - `endGame` 函数在检测到碰撞时停止游戏并显示“游戏结束”信息。

将上述三个文件保存好,然后在浏览器中打开 `index.html` 文件即可看到和玩这个火柴人躲避障碍物的小游戏。如果你有任何问题或需要进一步的帮助,请随时告诉我哦!
作者: 张复礼    时间: 2024-8-7 19:58
请完善躲避游戏:长按左键或右键可以持续向左或向右移动。
作者: 张复礼    时间: 2024-8-7 20:06
请修改代码,实现长按左键(或右键)可以持续使游戏对象左移(或右移)
作者: 张复礼    时间: 2024-8-12 14:07
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

let snake = [{ x: 50, y: 50 }];
let food = { x: 0, y: 0 };
let dx = 10;
let dy = 0;
let score = 0;
let gameOver = false;

// 创建音效对象
const eatSound = new Audio('eat.mp3');

// 创建背景音乐对象
const backgroundMusic = new Audio('background.mp3');
backgroundMusic.loop = true; // 设置循环播放

document.addEventListener("keydown", changeDirection);

function randomFoodPosition() {
    const x = Math.floor(Math.random() * (canvas.width / 10)) * 10;
    const y = Math.floor(Math.random() * (canvas.height / 10)) * 10;
    return { x, y };
}

function clearCanvas() {
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function drawSnake() {
    snake.forEach(drawSnakePart);
}

function drawSnakePart(snakePart) {
    ctx.fillStyle = 'lightgreen';
    ctx.strokeStyle = 'darkgreen';
    ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
    ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
}

function drawFood() {
    ctx.fillStyle = 'lightpink';
    ctx.fillRect(food.x, food.y, 10, 10);
}

function moveSnake() {
    const head = { x: snake[0].x + dx, y: snake[0].y + dy };

    // 检测碰壁
    if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || collision(head)) {
        gameOver = true;
        return;
    }

    snake.unshift(head);

    // 检查是否吃到食物
    if (head.x === food.x && head.y === food.y) {
        score++;
        food = randomFoodPosition();
        playEatSound(); // 播放音效
    } else {
        snake.pop();
    }
}

function collision(head) {
    for (let i = 1; i < snake.length; i++) {
        if (snake[i].x === head.x && snake[i].y === head.y) {
            return true;
        }
    }
    return false;
}

// 播放吃食物的音效
function playEatSound() {
    eatSound.play();
}

// 播放背景音乐
function playBackgroundMusic() {
    backgroundMusic.play();
}

// 停止背景音乐
function stopBackgroundMusic() {
    backgroundMusic.pause();
    backgroundMusic.currentTime = 0; // 重置音乐到开头
}

function main() {
    if (gameOver) {
        displayGameOver();
        return;
    }

    setTimeout(function onTick() {
        clearCanvas();
        drawFood();
        moveSnake();
        drawSnake();
        main();
    }, 100);
}

function changeDirection(event) {
    const LEFT_KEY = 37;
    const RIGHT_KEY = 39;
    const UP_KEY = 38;
    const DOWN_KEY = 40;

    const keyPressed = event.keyCode;
    const goingUp = dy === -10;
    const goingDown = dy === 10;
    const goingRight = dx === 10;
    const goingLeft = dx === -10;

    if (keyPressed === LEFT_KEY && !goingRight) {
        dx = -10;
        dy = 0;
    }

    if (keyPressed === UP_KEY && !goingDown) {
        dx = 0;
        dy = -10;
    }

    if (keyPressed === RIGHT_KEY && !goingLeft) {
        dx = 10;
        dy = 0;
    }

    if (keyPressed === DOWN_KEY && !goingUp) {
        dx = 0;
        dy = 10;
    }
}

// 显示游戏结束
function displayGameOver() {
    ctx.fillStyle = "pink";
    ctx.font = "30px Arial";
     // 绘制“游戏结束!”位于中心稍上方
    ctx.fillText("很遗憾,游戏结束!", canvas.width / 2 - 115, canvas.height / 2 - 20);
    // 绘制得分位于中心稍下方
    ctx.fillText("得分: " + score, canvas.width / 2 - 50, canvas.height / 2 + 20);
    document.getElementById("startButton").style.display = "block";
    stopBackgroundMusic(); // 停止背景音乐
}


function startGame() {
    snake = [{ x: 50, y: 50 }];
    score = 0;
    dx = 10;
    dy = 0;
    gameOver = false;
    food = randomFoodPosition();
    document.getElementById('startButton').style.display = 'none';
    playBackgroundMusic(); // 播放背景音乐
    main();
}

food = randomFoodPosition();
main();
你好,请修改我的贪吃蛇游戏代码,使游戏的右边出现“游戏规则”悬停按钮,鼠标移到按钮上出现游戏规则。




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