使用React制作一個貪吃蛇游戲的代碼詳解
在 React 中創(chuàng)建貪吃蛇游戲
Snake Game 使用 ReactJS 項目實現(xiàn)功能組件并相應地管理狀態(tài)。開發(fā)的游戲允許用戶使用箭頭鍵控制蛇或觸摸屏幕上顯示的按鈕來收集食物并增長長度。游戲的目標是在不與墻壁或蛇自己的身體碰撞的情況下吃盡可能多的食物。
最終輸出預覽: 讓我們看看我們的最終項目會是什么樣子。

創(chuàng)建貪吃蛇游戲的方法:
給定的代碼代表使用 ReactJS 的貪吃蛇游戲項目。它涉及設置蛇、食物、按鈕和菜單的組件。游戲以初始狀態(tài)初始化,處理蛇運動的用戶輸入,檢測碰撞,并相應地更新游戲板。渲染和用戶界面的實現(xiàn)是為了顯示游戲元素。游戲流程包括菜單和游戲玩法的過渡。
創(chuàng)建貪吃蛇游戲的步驟:
步驟 1: 在 VSCode IDE 中使用以下命令設置 React 項目。
?npx create-react-app snack_game
步驟 2: 執(zhí)行以下命令導航到新創(chuàng)建的項目文件夾。
?cd snack_game
步驟 3: 創(chuàng)建一個名為 Components 的文件夾。我們將在此組件文件夾中創(chuàng)建各種組件及其樣式文件,例如 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呈現(xiàn)菜單。它顯示一個“開始游戲”按鈕,并在單擊時觸發(fā)onRouteChange功能。菜單的樣式使用“menu.CSS”文件中的CSS
- Food.js 是一個React組件,它根據(jù)提供的坐標在游戲中呈現(xiàn)食物。
- Snake.js:Snake.js文件代碼是一個React組件,它在游戲中基于表示蛇點的坐標數(shù)組來渲染蛇。
//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: 在命令行執(zhí)行一下命令啟動項目程序
?npm start
Step 2: 在瀏覽器地址中打開一下地址
輸出:

以上就是使用React制作一個貪吃蛇游戲的代碼詳解的詳細內容,更多關于React貪吃蛇游戲的資料請關注腳本之家其它相關文章!
相關文章
reactjs學習解決unknown at rule @tailwind css
這篇文章主要介紹了reactjs學習解決unknown at rule @tailwind css問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
詳解使用WebPack搭建React開發(fā)環(huán)境
這篇文章主要介紹了詳解使用WebPack搭建React開發(fā)環(huán)境,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08
解決React報錯You provided a `checked` prop&n
這篇文章主要為大家介紹了React報錯You provided a `checked` prop to a form field的解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
React?Native?中處理?Android?手機吞字的解決方案
這篇文章主要介紹了React?Native?中處理?Android?手機吞字的解決方案,作者在 React Native 0.67.4 環(huán)境下,編寫了一個小 demo 來復現(xiàn)這個問題,需要的朋友可以參考下2022-08-08

