使用React制作一个贪吃蛇游戏的代码详解

 更新时间:2023年11月02日 08:24:37   作者:demo007x  
Snake Game 使用 ReactJS 项目实现功能组件并相应地管理状态,开发的游戏允许用户使用箭头键控制蛇或触摸屏幕上显示的按钮来收集食物并增长长度,本文给大家详细讲解了如何使用 React 制作一个贪吃蛇游戏,需要的朋友可以参考下

在 React 中创建贪吃蛇游戏

Snake Game 使用 ReactJS 项目实现功能组件并相应地管理状态。开发的游戏允许用户使用箭头键控制蛇或触摸屏幕上显示的按钮来收集食物并增长长度。游戏的目标是在不与墙壁或蛇自己的身体碰撞的情况下吃尽可能多的食物。

最终输出预览: 让我们看看我们的最终项目会是什么样子。

创建贪吃蛇游戏的方法:

给定的代码代表使用 ReactJS 的贪吃蛇游戏项目。它涉及设置蛇、食物、按钮和菜单的组件。游戏以初始状态初始化,处理蛇运动的用户输入,检测碰撞,并相应地更新游戏板。渲染和用户界面的实现是为了显示游戏元素。游戏流程包括菜单和游戏玩法的过渡。

创建贪吃蛇游戏的步骤:

步骤 1: 在 VSCode IDE 中使用以下命令设置 React 项目。

 npx create-react-app snack_game

步骤 2: 执行以下命令导航到新创建的项目文件夹。

 cd snack_game

步骤 3: 创建一个名为 Components 的文件夹。我们将在此组件文件夹中创建各种组件及其样式文件,例如 Button.js、Food.js、Menu.js、Snake.js、Menu.css 和 Button.css。

贪吃蛇游戏的项目结构:

package.json中更新后的依赖项将如下所示:

 "dependencies": {
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",
     "@testing-library/user-event": "^13.5.0",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-scripts": "5.0.1",
     "web-vitals": "^2.1.4"
 }

示例: 在上述目录结构中提到的App.js 和 index.css文件中插入以下代码

App.js

 // App.js 
 import React, { Component } from "react"; 
 import Snake from "./Components/Snake"; 
 import Food from "./Components/Food"; 
 import Button from "./Components/Button"; 
 import Menu from "./Components/Menu"; 
 import "./App.css"; 
 const getRandomFood = () => { 
   let min = 1; 
   let max = 98; 
   let x = Math.floor((Math.random() * (max - min + 1) + min) / 2) * 2; 
   let y = Math.floor((Math.random() * (max - min + 1) + min) / 2) * 2; 
   return [x, y]; 
 }; 
 ​
 const initialState = { 
   food: getRandomFood(), 
   direction: "RIGHT", 
   speed: 100, 
   route: "menu", 
   snakeDots: [ 
     [0, 0], 
     [0, 2], 
   ], 
 }; 
 ​
 class App extends Component { 
   constructor() { 
     super(); 
     this.state = initialState; 
   } 
 ​
   componentDidMount() { 
     setInterval(this.moveSnake, this.state.speed); 
     document.onkeydown = this.onKeyDown; 
   } 
 ​
   componentDidUpdate() { 
     this.onSnakeOutOfBounds(); 
     this.onSnakeCollapsed(); 
     this.onSnakeEats(); 
   } 
 ​
   onKeyDown = (e) => { 
     e.preventDefault(); 
     e = e || window.event; 
     switch (e.keyCode) { 
       case 37: 
         this.setState({ direction: "LEFT" }); 
         break; 
       case 38: 
         this.setState({ direction: "UP" }); 
         break; 
       case 39: 
         this.setState({ direction: "RIGHT" }); 
         break; 
       case 40: 
         this.setState({ direction: "DOWN" }); 
         break; 
     } 
   }; 
 ​
   moveSnake = () => { 
     let dots = [...this.state.snakeDots]; 
     let head = dots[dots.length - 1]; 
     if (this.state.route === "game") { 
       switch (this.state.direction) { 
         case "RIGHT": 
           head = [head[0] + 2, head[1]]; 
           break; 
         case "LEFT": 
           head = [head[0] - 2, head[1]]; 
           break; 
         case "DOWN": 
           head = [head[0], head[1] + 2]; 
           break; 
         case "UP": 
           head = [head[0], head[1] - 2]; 
           break; 
       } 
       dots.push(head); 
       dots.shift(); 
       this.setState({ 
         snakeDots: dots, 
       }); 
     } 
   }; 
 ​
   onSnakeOutOfBounds() { 
     let head = this.state.snakeDots[this.state.snakeDots.length - 1]; 
     if (this.state.route === "game") { 
       if ( 
         head[0] >= 100 || 
         head[1] >= 100 || 
         head[0] < 0 || 
         head[1] < 0 
       ) { 
         this.gameOver(); 
       } 
     } 
   } 
 ​
   onSnakeCollapsed() { 
     let snake = [...this.state.snakeDots]; 
     let head = snake[snake.length - 1]; 
     snake.pop(); 
     snake.forEach((dot) => { 
       if (head[0] == dot[0] && head[1] == dot[1]) { 
         this.gameOver(); 
       } 
     }); 
   } 
 ​
   onSnakeEats() { 
     let head = this.state.snakeDots[this.state.snakeDots.length - 1]; 
     let food = this.state.food; 
     if (head[0] == food[0] && head[1] == food[1]) { 
       this.setState({ 
         food: getRandomFood(), 
       }); 
       this.increaseSnake(); 
       this.increaseSpeed(); 
     } 
   } 
 ​
   increaseSnake() { 
     let newSnake = [...this.state.snakeDots]; 
     newSnake.unshift([]); 
     this.setState({ 
       snakeDots: newSnake, 
     }); 
   } 
 ​
   increaseSpeed() { 
     if (this.state.speed > 10) { 
       this.setState({ 
         speed: this.state.speed - 20, 
       }); 
     } 
   } 
 ​
   onRouteChange = () => { 
     this.setState({ 
       route: "game", 
     }); 
   }; 
 ​
   gameOver() { 
     alert(`GAME OVER, your score is ${this.state.snakeDots.length - 2}`); 
     this.setState(initialState); 
   } 
 ​
   onDown = () => { 
     let dots = [...this.state.snakeDots]; 
     let head = dots[dots.length - 1]; 
 ​
     head = [head[0], head[1] + 2]; 
     dots.push(head); 
     dots.shift(); 
     this.setState({ 
       direction: "DOWN", 
       snakeDots: dots, 
     }); 
   }; 
 ​
   onUp = () => { 
     let dots = [...this.state.snakeDots]; 
     let head = dots[dots.length - 1]; 
 ​
     head = [head[0], head[1] - 2]; 
     dots.push(head); 
     dots.shift(); 
     this.setState({ 
       direction: "UP", 
       snakeDots: dots, 
     }); 
   }; 
 ​
   onRight = () => { 
     let dots = [...this.state.snakeDots]; 
     let head = dots[dots.length - 1]; 
 ​
     head = [head[0] + 2, head[1]]; 
     dots.push(head); 
     dots.shift(); 
     this.setState({ 
       direction: "RIGHT", 
       snakeDots: dots, 
     }); 
   }; 
 ​
   onLeft = () => { 
     let dots = [...this.state.snakeDots]; 
     let head = dots[dots.length - 1]; 
 ​
     head = [head[0] - 2, head[1]]; 
     dots.push(head); 
     dots.shift(); 
     this.setState({ 
       direction: "LEFT", 
       snakeDots: dots, 
     }); 
   }; 
 ​
   render() { 
     const { route, snakeDots, food } = this.state; 
     return ( 
       <div> 
         {route === "menu" ? ( 
           <div> 
             <Menu onRouteChange={this.onRouteChange} /> 
           </div> 
         ) : ( 
           <div> 
             <div className="game-area"> 
               <Snake snakeDots={snakeDots} /> 
               <Food dot={food} /> 
             </div> 
             <Button 
               onDown={this.onDown} 
               onLeft={this.onLeft} 
               onRight={this.onRight} 
               onUp={this.onUp} 
             /> 
           </div> 
         )} 
       </div> 
     ); 
   } 
 } 
 ​
 export default App; 
 ​

index.css

 /* index.css */
 body { 
   background-color: #1e1e1e; 
 } 
 ​
 .game-area { 
   position: relative; 
   width: 600px; 
   height: 500px; 
   border: 2px solid #dc042c; 
   border-radius: 10px; 
   margin: 50px auto; 
   display: flex; 
   flex-wrap: wrap; 
   box-shadow: 0 0 10px #abbfc0; 
 } 
 ​
 @media only screen and (max-width: 800px) { 
   .game-area { 
     position: relative; 
     width: 350px; 
     height: 300px; 
   } 
 ​
   .snake { 
     width: 12px; 
     height: 12px; 
   } 
 } 
 ​
 .snake { 
   position: absolute; 
   width: 2%; 
   height: 2%; 
   background-color: #dc042c; 
   border: 1px solid white; 
   z-index: 2; 
 } 
 ​
 .food { 
   position: absolute; 
   width: 12px; 
   height: 12px; 
   background-color: white; 
   border-radius: 20px; 
   z-index: 1; 
 }
 ​

在不同的文件中编写以下提到的代码(每个代码块的第一行都提到了文件名)

  • Button.js: Button.js表示React功能组件,用于在snake游戏中渲染控制蛇移动的按钮。
  • Menu.js: Menu.js文件代码为Snake Game呈现菜单。它显示一个“开始游戏”按钮,并在单击时触发onRouteChange功能。菜单的样式使用“menu.CSS”文件中的CSS
  • Food.js 是一个React组件,它根据提供的坐标在游戏中呈现食物。
  • Snake.js:Snake.js文件代码是一个React组件,它在游戏中基于表示蛇点的坐标数组来渲染蛇。

//Button.js

 //Button.js 
 import React from "react"; 
 import "./Button.css"; 
 ​
 const Button = ({ onUp, onDown, onLeft, onRight }) => { 
   return ( 
     <div className="buttons"> 
       <div className="upwards"> 
         <input className="up" onClick={onUp} type="button" value="UP" /> 
       </div> 
       <div className="sideways"> 
         <input 
           className="left"
           onClick={onLeft} 
           type="button"
           value="LEFT"
         /> 
         <input 
           className="right"
           onClick={onRight} 
           type="button"
           value="RIGHT"
         /> 
       </div> 
       <div className="downwards"> 
         <input 
           className="down"
           onClick={onDown} 
           type="button"
           value="DOWN"
         /> 
       </div> 
     </div> 
   ); 
 }; 
 export default Button; 
 ​

Food.js

 //Food.js 
 import React from "react"; 
 ​
 const Food = (props) => { 
   const style = { 
     left: `${props.dot[0]}%`, 
     top: `${props.dot[1]}%`, 
   }; 
   return <div className="food" style={style} />; 
 }; 
 ​
 export default Food; 
 ​

Menu.js

 //Menu.js 
 import React from "react"; 
 import "./Menu.css"; 
 ​
 const Menu = ({ onRouteChange }) => { 
   return ( 
     <div className="wrapper"> 
       <div> 
         <input 
           onClick={onRouteChange} 
           className="start"
           type="button"
           value="start game"
         /> 
       </div> 
     </div> 
   ); 
 }; 
 ​
 export default Menu; 
 ​

Snake.js

 //Snake.js 
 import React from "react"; 
 ​
 const Snake = (props) => { 
   return ( 
     <div> 
       {props.snakeDots.map((dot, i) => { 
         const style = { 
           left: `${dot[0]}%`, 
           top: `${dot[1]}%`, 
         }; 
         return <div className="snake" key={i} style={style} />; 
       })} 
     </div> 
   ); 
 }; 
 export default Snake; 
 ​

Button.css

 /* Button.css */
 .upwards, 
 .downwards { 
   display: flex; 
   justify-content: center; 
 } 
 ​
 .sideways { 
   display: flex; 
   justify-content: center; 
   margin: 10px; 
 } 
 ​
 .left, 
 .right { 
   margin: 50px; 
   padding: 20px; 
   border: 0px solid; 
   border-radius: 20px; 
   border: 1px solid white; 
   color: #dc042c; 
   background: #1e1e1e; 
   box-shadow: 5px -5px 10px rgba(0, 0, 0, 0.6); 
 } 
 ​
 .up, 
 .down { 
   padding: 20px; 
   border: 0px solid; 
   border-radius: 20px; 
   border: 1px solid white; 
   color: #dc042c; 
   background: #1e1e1e; 
   box-shadow: 5px -5px 10px rgba(0, 0, 0, 0.6); 
 }
 ​

Menu.css

 /* Menu.css */
 .wrapper { 
   position: relative; 
   width: 200px; 
   height: 250px; 
   border: 2px solid #dc042c; 
   /* border-radius: 10px; */
   margin: 50px auto; 
   margin-top: 200px; 
   display: flex; 
   flex-wrap: wrap; 
   justify-content: center; 
   /* box-shadow: 0 0 10px #abbfc0; */
 } 
 ​
 .start { 
   margin: 100px; 
   background: #1e1e1e; 
   color: white; 
   border-radius: 7px; 
   border: 0px; 
   padding: 10px; 
   font-size: 1.2em; 
   box-shadow: 0 0 70px #abbfc0; 
   font-family: "Courier New", Courier, monospace; 
 }
 ​

启动我们的程序:

Step 1: 在命令行执行一下命令启动项目程序

 npm start

Step 2: 在浏览器地址中打开一下地址 

http://localhost:3000/

输出:

以上就是使用React制作一个贪吃蛇游戏的代码详解的详细内容,更多关于React贪吃蛇游戏的资料请关注脚本之家其它相关文章!

相关文章

  • react表单受控的实现方案

    react表单受控的实现方案

    数据的受控控制一直是react里的一个痛点,当我想要实现一个输入框的受控控制时,我需要定义一个onChange和value,手动去实现数据的绑定,本文小编给大家介绍了react表单受控的实现方案,需要的朋友可以参考下
    2023-12-12
  • react项目升级报错,babel报错,.babelrc配置兼容等问题及解决

    react项目升级报错,babel报错,.babelrc配置兼容等问题及解决

    这篇文章主要介绍了react项目升级报错,babel报错,.babelrc配置兼容等问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • react-router-dom 嵌套路由的实现

    react-router-dom 嵌套路由的实现

    这篇文章主要介绍了react-router-dom 嵌套路由的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • react-router-dom v6 使用详细示例

    react-router-dom v6 使用详细示例

    这篇文章主要介绍了react-router-dom v6使用详细示例,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-09-09
  • Taro React自定义TabBar使用useContext解决底部选中异常

    Taro React自定义TabBar使用useContext解决底部选中异常

    这篇文章主要为大家介绍了Taro React底部自定义TabBar使用React useContext解决底部选中异常(需要点两次才能选中的问题)示例详解,有需要的朋友可以借鉴参考下
    2023-08-08
  • React Redux使用配置详解

    React Redux使用配置详解

    react-redux是redux官方react绑定库,能够使react组件从redux store中读取数据,并且向store分发actions以此来更新数据,这篇文章主要介绍了react-redux的设置,需要的朋友可以参考下
    2022-08-08
  • React native ListView 增加顶部下拉刷新和底下点击刷新示例

    React native ListView 增加顶部下拉刷新和底下点击刷新示例

    这篇文章主要介绍了React native ListView 增加顶部下拉刷新和底下点击刷新示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • React forwardRef 用法案例分析

    React forwardRef 用法案例分析

    这篇文章主要介绍了React forwardRef用法,forwardRef允许你的组件使用ref将一个DOM节点暴露给父组件,本文结合案例分析给大家讲解的非常详细,需要的朋友可以参考下
    2023-06-06
  • react常见的ts类型实践解析

    react常见的ts类型实践解析

    这篇文章主要为大家介绍了react常见的ts类型实践解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • React实现预览展示docx和Excel文件

    React实现预览展示docx和Excel文件

    这篇文章主要为大家详细介绍了如何使用React实现预览展示docx和Excel文件,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-02-02

最新评论