【React-Redux】自制简易贪吃蛇小游戏

componentDidMount() {

// 监听键盘按下事件

document.onkeydown = this.onkeydown;

// 每隔200ms前进一步

setInterval(this.onMove, this.state.speed);

}

onkeydown = (e) => {

// 根据按下的键盘键更新direction

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;

default:

this.setState({ direction: “RIGHT” });

}

}

onMove = () => {

// 根据direction指示的方向前进

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

switch (this.state.direction) {

case “UP”:

header = [header[0], header[1] - 2];

break;

case “DOWN”:

header = [header[0], header[1] + 2];

break;

case “LEFT”:

header = [header[0] - 2, header[1]];

break;

case “RIGHT”:

header = [header[0] + 2, header[1]];

break;

default:

header = [header[0] + 2, header[1]];

}

// 删去第一个小黑块,并在direction方向上新增新小黑块,更新snakeDots

newSnakeDots.shift();

newSnakeDots.push(header);

this.setState({ snakeDots: newSnakeDots })

}

效果:

在这里插入图片描述

边界限制与得分计算


当触碰边界或者撞击到自身时,游戏结束,弹窗提示,分数为贪吃蛇的长度-2(初始长度为2,其余均是吃到食物后变长的,吃一个食物长长1格)

componentDidUpdate() {

this.checkIfBordered();

}

checkIfBordered = () => {

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

if (header[0] < 0 || header[0] > 98 || header[1] < 0 || header[1] > 98) {

alert(触碰边界,游戏结束,你的得分是:${newSnakeDots.length - 2});

this.setState(initState);

}

}

食物随机出现


由于我们规定,贪吃蛇触碰到边界时算游戏结束,因此,食物不能出现在边界上,否则,一吃到食物就代表触壁结束游戏(可以改进为:贪吃蛇每次前进1%,当食物被触碰比例达50%时可以当作贪吃蛇吃掉该食物,马上掉头避免触壁,以后再改吧~)

因此,食物出现的范围在top:2%~96%,left的范围也是如此

在这里插入图片描述

const getRandomFood = ()=>{

// 食物出现的范围是:[2, 96] 推算过程:[0,95)->[2, 97)->[1, 48.5]->[1,48]->[2,96]

let max = 95;

let min = 2;

let x = Math.floor((Math.random() * max + min) / 2) * 2;

let y = Math.floor((Math.random() * max + min) / 2) * 2;

return [x,y]

}

const initState = {

snakeDots: [

[0, 0],

[2, 0]

],

direction: “RIGHT”,

speed: 200,

food:getRandomFood() // 随机生成食物的位置

}

食物的展示:

import { Food } from ‘./components/Food’;

render() {

return (

);

}

import React from ‘react’

export const Food = ({food}) => {

let foodStyle = {

left:${food[0]}%,

top:${food[1]}%

}

return (

)

}

食物的样式:

.food {

height: 2%;

width: 2%;

background-color: red;

border: 1px solid #fff;

position: absolute;

}

判断是否吃到食物


贪吃蛇的头(head)和食物重叠时,代表吃到

贪吃蛇变长,食物的位置变成新的head,重新放置食物

componentDidUpdate() {

// 每次更新都判断一下

this.checkIfBordered();

this.checkIfEated();

}

checkIfEated = ()=>{

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

// head与食物重叠时,代表吃到食物

if(header[0]==this.state.food[0] && header[1]==this.state.food[1]){

console.log(“吃到了”)

newSnakeDots.unshift([]);

this.setState({snakeDots:newSnakeDots});

this.setState({food:getRandomFood()});

}

}

效果:

在这里插入图片描述

完整代码:

新建文件夹component存放组件:

在这里插入图片描述

App.js

import React, { Component } from ‘react’

import { Snake } from ‘./components/Snake’;

import { Food } from ‘./components/Food’;

// 随机获取食物位置

const getRandomFood = ()=>{

// [2, 96]: [0,95)->[2, 97)->[1, 48.5]->[1,48]->[2,96]

let max = 95;

let min = 2;

let x = Math.floor((Math.random() * max + min) / 2) * 2;

let y = Math.floor((Math.random() * max + min) / 2) * 2;

console.log(“food-position”,x,y)

return [x,y]

}

// 另存state以便重新初始化

const initState = {

snakeDots: [

[0, 0],

[2, 0]

],

direction: “RIGHT”,

speed: 200,

food:getRandomFood()

}

class App extends Component {

state = initState;

// 监听与计时器

componentDidMount() {

document.onkeydown = this.onkeydown;

setInterval(this.onMove, this.state.speed);

}

// 更新时检测是否出界或吃到食物

componentDidUpdate() {

this.checkIfBordered();

this.checkIfEated();

}

// 判断键盘按键,更新direction

onkeydown = (e) => {

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;

default:

this.setState({ direction: “RIGHT” });

}

}

// 根据direction移动

onMove = () => {

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

switch (this.state.direction) {

case “UP”:

header = [header[0], header[1] - 2];

break;

case “DOWN”:

header = [header[0], header[1] + 2];

break;

case “LEFT”:

header = [header[0] - 2, header[1]];

break;

case “RIGHT”:

header = [header[0] + 2, header[1]];

break;

default:

header = [header[0] + 2, header[1]];

}

newSnakeDots.shift();

newSnakeDots.push(header);

this.setState({ snakeDots: newSnakeDots })

// console.log(this.state.snakeDots)

}

// 判断是否出界

checkIfBordered = () => {

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

if (header[0] < 0 || header[0] > 98 || header[1] < 0 || header[1] > 98) {

alert(触碰边界,游戏结束,你的得分是:${newSnakeDots.length - 2});

this.setState(initState);

}

}

// 判断是否吃到食物

checkIfEated = ()=>{

let newSnakeDots = […this.state.snakeDots];

let header = newSnakeDots[newSnakeDots.length - 1];

if(header[0]==this.state.food[0] && header[1]==this.state.food[1]){

console.log(“吃到了”)

newSnakeDots.unshift([]);

this.setState({snakeDots:newSnakeDots});

this.setState({food:getRandomFood()});

}

}

render() {

return (

);

}

}

export default App;

Snake.js:

import React from ‘react’

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值