广州网站建设及推广,网站建设与管理相关工作岗位,四川高速建设公司网站,详情页模板psd〇、前言
贪吃蛇是一款经典的休闲游戏#xff0c;在诺基亚手机时代风靡全球。 作为编程入门者#xff0c;实现一个贪吃蛇游戏是学习Web前端技术的绝佳练习。 名人说#xff1a;博观而约取#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者#xff1a;Code_流苏(CSDN…〇、前言
贪吃蛇是一款经典的休闲游戏在诺基亚手机时代风靡全球。 作为编程入门者实现一个贪吃蛇游戏是学习Web前端技术的绝佳练习。 名人说博观而约取厚积而薄发。——苏轼《稼说送张琥》 创作者Code_流苏(CSDN)一个喜欢古诗词和编程的Coder 目录 〇、前言效果预览一、HTML结构二、CSS样式设计三、JavaScript游戏逻辑四、代码详解1. 游戏初始化2. 生成食物3. 移动蛇4. 碰撞检测5. 游戏控制 五、完整代码 很高兴你打开了这篇博客更多好用的软件工具请关注我、订阅专栏《项目探索实验室》内容持续更新中… 思维速览
本文将详细讲解如何使用HTML、CSS和JavaScript从零开始创建一个功能完整的贪吃蛇网页游戏更多功能可以根据个人开发需求拓展。
我们的贪吃蛇游戏将包含以下功能
基础的游戏逻辑移动、吃食物、碰撞检测分数记录和最高分保存游戏控制开始、暂停、继续自适应界面设计支持PC和移动设备逐步提高的游戏难度
效果预览
▍1️⃣静态展示 ▍2️⃣动态展示 完成后的游戏效果如下
一个20x20格子的游戏场地绿色的蛇红色的食物顶部显示当前分数和历史最高分底部有游戏控制按钮和移动设备专用的方向控制键
一、HTML结构
首先创建基本的HTML结构
!DOCTYPE html
html langzh
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title贪吃蛇小游戏/title!-- CSS将在这里添加 --
/head
bodyh1贪吃蛇小游戏/h1div classgame-containerdiv classgame-headerdiv分数: span idscore0/span/divdiv最高分: span idhigh-score0/span/div/divdiv idgame-board/divdiv classcontrolsbutton idstart-button开始游戏/buttondiv classmobile-controlsbutton classup↑/buttonbutton classleft←/buttonbutton classright→/buttonbutton classdown↓/button/div/div/div!-- JavaScript将在这里添加 --
/body
/html这个HTML结构包含了
游戏标题分数和最高分显示区域游戏主画布game-board游戏控制按钮移动设备的方向控制按钮
二、CSS样式设计
接下来我们需要添加CSS样式使游戏看起来更加美观
stylebody {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100vh;margin: 0;background-color: #f0f0f0;font-family: Arial, sans-serif;}.game-container {display: flex;flex-direction: column;align-items: center;}.game-header {display: flex;justify-content: space-between;width: 400px;margin-bottom: 10px;}#game-board {width: 400px;height: 400px;border: 2px solid #333;position: relative;background-color: #eee;}.snake-part {width: 20px;height: 20px;background-color: #4CAF50;position: absolute;border-radius: 2px;}.snake-head {background-color: #388E3C;}.food {width: 20px;height: 20px;background-color: #F44336;position: absolute;border-radius: 50%;}.controls {margin-top: 20px;display: flex;flex-direction: column;align-items: center;}button {padding: 10px 20px;margin: 5px;font-size: 16px;cursor: pointer;background-color: #2196F3;color: white;border: none;border-radius: 4px;}button:hover {background-color: #0b7dda;}.mobile-controls {display: grid;grid-template-columns: 1fr 1fr 1fr;grid-template-rows: 1fr 1fr 1fr;gap: 5px;margin-top: 15px;max-width: 200px;}.mobile-controls button {padding: 15px;margin: 0;}.up {grid-column: 2;grid-row: 1;}.left {grid-column: 1;grid-row: 2;}.right {grid-column: 3;grid-row: 2;}.down {grid-column: 2;grid-row: 3;}media (max-width: 500px) {#game-board {width: 300px;height: 300px;}.game-header {width: 300px;}}
/style这些CSS样式
使用Flexbox和Grid布局设计蛇和食物的外观美化按钮和控件添加响应式设计适应不同屏幕尺寸
三、JavaScript游戏逻辑
最后也是最重要的部分我们需要实现游戏的核心逻辑
scriptdocument.addEventListener(DOMContentLoaded, () {// 游戏变量const boardSize 20; // 20x20 格子const gridSize 20; // 每个格子的大小像素const board document.getElementById(game-board);const scoreElement document.getElementById(score);const highScoreElement document.getElementById(high-score);const startButton document.getElementById(start-button);let snake []; // 蛇的身体部分坐标let food null; // 食物坐标let direction right; // 初始方向let nextDirection right;let gameInterval null;let score 0;let highScore localStorage.getItem(snakeHighScore) || 0;let gameSpeed 150; // 游戏速度毫秒let gameStarted false;let gamePaused false;highScoreElement.textContent highScore;// 初始化游戏function initGame() {clearBoard();// 初始化蛇snake [{x: 5, y: 10}, // 头部{x: 4, y: 10},{x: 3, y: 10}];// 重置游戏状态direction right;nextDirection right;score 0;scoreElement.textContent score;// 生成第一个食物generateFood();// 渲染初始状态renderSnake();renderFood();}// 清空游戏板function clearBoard() {board.innerHTML ;}// 生成食物function generateFood() {let foodPosition;let onSnake;do {// 随机生成食物位置foodPosition {x: Math.floor(Math.random() * boardSize),y: Math.floor(Math.random() * boardSize)};// 检查食物是否与蛇重叠onSnake snake.some(part part.x foodPosition.x part.y foodPosition.y);} while (onSnake);food foodPosition;}// 渲染蛇function renderSnake() {snake.forEach((part, index) {const snakePart document.createElement(div);snakePart.className snake-part;if (index 0) {snakePart.classList.add(snake-head);}snakePart.style.left ${part.x * gridSize}px;snakePart.style.top ${part.y * gridSize}px;board.appendChild(snakePart);});}// 渲染食物function renderFood() {const foodElement document.createElement(div);foodElement.className food;foodElement.style.left ${food.x * gridSize}px;foodElement.style.top ${food.y * gridSize}px;board.appendChild(foodElement);}// 移动蛇function moveSnake() {// 更新方向direction nextDirection;// 获取蛇头的当前位置const head {...snake[0]};// 根据方向移动蛇头switch (direction) {case up:head.y - 1;break;case down:head.y 1;break;case left:head.x - 1;break;case right:head.x 1;break;}// 检查碰撞if (checkCollision(head)) {gameOver();return;}// 将新头部添加到蛇的开始snake.unshift(head);// 检查是否吃到食物if (head.x food.x head.y food.y) {// 吃到食物增加分数score 10;scoreElement.textContent score;// 更新最高分if (score highScore) {highScore score;highScoreElement.textContent highScore;localStorage.setItem(snakeHighScore, highScore);}// 生成新食物generateFood();// 增加游戏速度if (gameSpeed 50) {gameSpeed - 2;clearInterval(gameInterval);gameInterval setInterval(gameLoop, gameSpeed);}} else {// 没吃到食物移除蛇尾snake.pop();}// 重新渲染游戏clearBoard();renderSnake();renderFood();}// 检查碰撞function checkCollision(head) {// 检查墙壁碰撞if (head.x 0 || head.x boardSize || head.y 0 || head.y boardSize) {return true;}// 检查自身碰撞return snake.some((part, index) {// 跳过第一个元素因为它就是头部if (index 0) return false;return part.x head.x part.y head.y;});}// 游戏结束function gameOver() {clearInterval(gameInterval);alert(游戏结束! 你的得分: ${score});gameStarted false;startButton.textContent 开始游戏;}// 游戏循环function gameLoop() {moveSnake();}// 开始游戏function startGame() {if (gameStarted) {// 如果游戏已经开始暂停或继续if (gamePaused) {// 继续游戏gameInterval setInterval(gameLoop, gameSpeed);startButton.textContent 暂停游戏;gamePaused false;} else {// 暂停游戏clearInterval(gameInterval);startButton.textContent 继续游戏;gamePaused true;}} else {// 开始新游戏initGame();gameInterval setInterval(gameLoop, gameSpeed);gameStarted true;gamePaused false;startButton.textContent 暂停游戏;}}// 处理键盘输入document.addEventListener(keydown, e {if (!gameStarted || gamePaused) return;// 防止方向键引起页面滚动if([ArrowUp, ArrowDown, ArrowLeft, ArrowRight, ].includes(e.key)) {e.preventDefault();}// 更新方向switch (e.key) {case ArrowUp:if (direction ! down) nextDirection up;break;case ArrowDown:if (direction ! up) nextDirection down;break;case ArrowLeft:if (direction ! right) nextDirection left;break;case ArrowRight:if (direction ! left) nextDirection right;break;}});// 移动设备控制按钮document.querySelector(.up).addEventListener(click, () {if (direction ! down gameStarted !gamePaused) nextDirection up;});document.querySelector(.down).addEventListener(click, () {if (direction ! up gameStarted !gamePaused) nextDirection down;});document.querySelector(.left).addEventListener(click, () {if (direction ! right gameStarted !gamePaused) nextDirection left;});document.querySelector(.right).addEventListener(click, () {if (direction ! left gameStarted !gamePaused) nextDirection right;});// 开始游戏按钮startButton.addEventListener(click, startGame);// 初始化游戏initGame();});
/script四、代码详解
1. 游戏初始化
function initGame() {clearBoard();// 初始化蛇snake [{x: 5, y: 10}, // 头部{x: 4, y: 10},{x: 3, y: 10}];// 重置游戏状态direction right;nextDirection right;score 0;scoreElement.textContent score;// 生成第一个食物generateFood();// 渲染初始状态renderSnake();renderFood();
}这个函数负责
清空游戏板创建初始长度为3的蛇重置方向和分数生成食物渲染初始游戏状态
2. 生成食物
function generateFood() {let foodPosition;let onSnake;do {// 随机生成食物位置foodPosition {x: Math.floor(Math.random() * boardSize),y: Math.floor(Math.random() * boardSize)};// 检查食物是否与蛇重叠onSnake snake.some(part part.x foodPosition.x part.y foodPosition.y);} while (onSnake);food foodPosition;
}这个函数
随机生成食物的位置确保食物不会出现在蛇身上使用do-while循环直到找到合适的位置
3. 移动蛇
function moveSnake() {// 更新方向direction nextDirection;// 获取蛇头的当前位置const head {...snake[0]};// 根据方向移动蛇头switch (direction) {case up:head.y - 1;break;case down:head.y 1;break;case left:head.x - 1;break;case right:head.x 1;break;}// 检查碰撞if (checkCollision(head)) {gameOver();return;}// 将新头部添加到蛇的开始snake.unshift(head);// 检查是否吃到食物if (head.x food.x head.y food.y) {// 吃到食物增加分数score 10;scoreElement.textContent score;// 更新最高分if (score highScore) {highScore score;highScoreElement.textContent highScore;localStorage.setItem(snakeHighScore, highScore);}// 生成新食物generateFood();// 增加游戏速度if (gameSpeed 50) {gameSpeed - 2;clearInterval(gameInterval);gameInterval setInterval(gameLoop, gameSpeed);}} else {// 没吃到食物移除蛇尾snake.pop();}// 重新渲染游戏clearBoard();renderSnake();renderFood();
}这个函数是游戏的核心它
根据当前方向移动蛇头检查是否发生碰撞如果吃到食物增加分数生成新食物加快游戏速度如果没吃到食物移除蛇尾保持长度不变更新游戏界面
4. 碰撞检测
function checkCollision(head) {// 检查墙壁碰撞if (head.x 0 || head.x boardSize || head.y 0 || head.y boardSize) {return true;}// 检查自身碰撞return snake.some((part, index) {// 跳过第一个元素因为它就是头部if (index 0) return false;return part.x head.x part.y head.y;});
}这个函数检查两种碰撞情况
蛇头撞到墙壁超出游戏边界蛇头撞到自己的身体
5. 游戏控制
function startGame() {if (gameStarted) {// 如果游戏已经开始暂停或继续if (gamePaused) {// 继续游戏gameInterval setInterval(gameLoop, gameSpeed);startButton.textContent 暂停游戏;gamePaused false;} else {// 暂停游戏clearInterval(gameInterval);startButton.textContent 继续游戏;gamePaused true;}} else {// 开始新游戏initGame();gameInterval setInterval(gameLoop, gameSpeed);gameStarted true;gamePaused false;startButton.textContent 暂停游戏;}
}这个函数处理游戏的控制逻辑
开始新游戏暂停正在进行的游戏继续已暂停的游戏
五、完整代码
最后我们将上面的HTML、CSS和JavaScript代码合并得到完整的贪吃蛇游戏
!--创作者Code_流苏CSDN--
!DOCTYPE html
html langzh
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title贪吃蛇小游戏/titlestylebody {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100vh;margin: 0;background-color: #f0f0f0;font-family: Arial, sans-serif;}.game-container {display: flex;flex-direction: column;align-items: center;}.game-header {display: flex;justify-content: space-between;width: 400px;margin-bottom: 10px;}#game-board {width: 400px;height: 400px;border: 2px solid #333;position: relative;background-color: #eee;}.snake-part {width: 20px;height: 20px;background-color: #4CAF50;position: absolute;border-radius: 2px;}.snake-head {background-color: #388E3C;}.food {width: 20px;height: 20px;background-color: #F44336;position: absolute;border-radius: 50%;}.controls {margin-top: 20px;display: flex;flex-direction: column;align-items: center;}button {padding: 10px 20px;margin: 5px;font-size: 16px;cursor: pointer;background-color: #2196F3;color: white;border: none;border-radius: 4px;}button:hover {background-color: #0b7dda;}.mobile-controls {display: grid;grid-template-columns: 1fr 1fr 1fr;grid-template-rows: 1fr 1fr 1fr;gap: 5px;margin-top: 15px;max-width: 200px;}.mobile-controls button {padding: 15px;margin: 0;}.up {grid-column: 2;grid-row: 1;}.left {grid-column: 1;grid-row: 2;}.right {grid-column: 3;grid-row: 2;}.down {grid-column: 2;grid-row: 3;}media (max-width: 500px) {#game-board {width: 300px;height: 300px;}.game-header {width: 300px;}}/style
/head
bodyh1贪吃蛇小游戏/h1div classgame-containerdiv classgame-headerdiv分数: span idscore0/span/divdiv最高分: span idhigh-score0/span/div/divdiv idgame-board/divdiv classcontrolsbutton idstart-button开始游戏/buttondiv classmobile-controlsbutton classup↑/buttonbutton classleft←/buttonbutton classright→/buttonbutton classdown↓/button/div/div/divscriptdocument.addEventListener(DOMContentLoaded, () {// 游戏变量const boardSize 20; // 20x20 格子const gridSize 20; // 每个格子的大小像素const board document.getElementById(game-board);const scoreElement document.getElementById(score);const highScoreElement document.getElementById(high-score);const startButton document.getElementById(start-button);let snake []; // 蛇的身体部分坐标let food null; // 食物坐标let direction right; // 初始方向let nextDirection right;let gameInterval null;let score 0;let highScore localStorage.getItem(snakeHighScore) || 0;let gameSpeed 150; // 游戏速度毫秒let gameStarted false;let gamePaused false;highScoreElement.textContent highScore;// 初始化游戏function initGame() {clearBoard();// 初始化蛇snake [{x: 5, y: 10}, // 头部{x: 4, y: 10},{x: 3, y: 10}];// 重置游戏状态direction right;nextDirection right;score 0;scoreElement.textContent score;// 生成第一个食物generateFood();// 渲染初始状态renderSnake();renderFood();}// 清空游戏板function clearBoard() {board.innerHTML ;}// 生成食物function generateFood() {let foodPosition;let onSnake;do {// 随机生成食物位置foodPosition {x: Math.floor(Math.random() * boardSize),y: Math.floor(Math.random() * boardSize)};// 检查食物是否与蛇重叠onSnake snake.some(part part.x foodPosition.x part.y foodPosition.y);} while (onSnake);food foodPosition;}// 渲染蛇function renderSnake() {snake.forEach((part, index) {const snakePart document.createElement(div);snakePart.className snake-part;if (index 0) {snakePart.classList.add(snake-head);}snakePart.style.left ${part.x * gridSize}px;snakePart.style.top ${part.y * gridSize}px;board.appendChild(snakePart);});}// 渲染食物function renderFood() {const foodElement document.createElement(div);foodElement.className food;foodElement.style.left ${food.x * gridSize}px;foodElement.style.top ${food.y * gridSize}px;board.appendChild(foodElement);}// 移动蛇function moveSnake() {// 更新方向direction nextDirection;// 获取蛇头的当前位置const head {...snake[0]};// 根据方向移动蛇头switch (direction) {case up:head.y - 1;break;case down:head.y 1;break;case left:head.x - 1;break;case right:head.x 1;break;}// 检查碰撞if (checkCollision(head)) {gameOver();return;}// 将新头部添加到蛇的开始snake.unshift(head);// 检查是否吃到食物if (head.x food.x head.y food.y) {// 吃到食物增加分数score 10;scoreElement.textContent score;// 更新最高分if (score highScore) {highScore score;highScoreElement.textContent highScore;localStorage.setItem(snakeHighScore, highScore);}// 生成新食物generateFood();// 增加游戏速度if (gameSpeed 50) {gameSpeed - 2;clearInterval(gameInterval);gameInterval setInterval(gameLoop, gameSpeed);}} else {// 没吃到食物移除蛇尾snake.pop();}// 重新渲染游戏clearBoard();renderSnake();renderFood();}// 检查碰撞function checkCollision(head) {// 检查墙壁碰撞if (head.x 0 || head.x boardSize || head.y 0 || head.y boardSize) {return true;}// 检查自身碰撞return snake.some((part, index) {// 跳过第一个元素因为它就是头部if (index 0) return false;return part.x head.x part.y head.y;});}// 游戏结束function gameOver() {clearInterval(gameInterval);alert(游戏结束! 你的得分: ${score});gameStarted false;startButton.textContent 开始游戏;}// 游戏循环function gameLoop() {moveSnake();}// 开始游戏function startGame() {if (gameStarted) {// 如果游戏已经开始暂停或继续if (gamePaused) {// 继续游戏gameInterval setInterval(gameLoop, gameSpeed);startButton.textContent 暂停游戏;gamePaused false;} else {// 暂停游戏clearInterval(gameInterval);startButton.textContent 继续游戏;gamePaused true;}} else {// 开始新游戏initGame();gameInterval setInterval(gameLoop, gameSpeed);gameStarted true;gamePaused false;startButton.textContent 暂停游戏;}}// 处理键盘输入document.addEventListener(keydown, e {if (!gameStarted || gamePaused) return;// 防止方向键引起页面滚动if([ArrowUp, ArrowDown, ArrowLeft, ArrowRight, ].includes(e.key)) {e.preventDefault();}// 更新方向switch (e.key) {case ArrowUp:if (direction ! down) nextDirection up;break;case ArrowDown:if (direction ! up) nextDirection down;break;case ArrowLeft:if (direction ! right) nextDirection left;break;case ArrowRight:if (direction ! left) nextDirection right;break;}});// 移动设备控制按钮document.querySelector(.up).addEventListener(click, () {if (direction ! down gameStarted !gamePaused) nextDirection up;});document.querySelector(.down).addEventListener(click, () {if (direction ! up gameStarted !gamePaused) nextDirection down;});document.querySelector(.left).addEventListener(click, () {if (direction ! right gameStarted !gamePaused) nextDirection left;});document.querySelector(.right).addEventListener(click, () {if (direction ! left gameStarted !gamePaused) nextDirection right;});// 开始游戏按钮startButton.addEventListener(click, startGame);// 初始化游戏initGame();});/script
/body
/html很感谢你能看到这里如果你有哪些想学习的项目欢迎在评论区分享 创作者Code_流苏(CSDN)一个喜欢古诗词和编程的Coder