代码改变世界

react 写一个贪吃蛇

2018-09-14 21:58  muamaker  阅读(525)  评论(0编辑  收藏  举报

示例:

 

全部代码如下:

 

snake.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { is, fromJS } from 'immutable';

import "./snake.less";


const TYP = {
    normal:1,
    head:2,
    body:3,
    food:4
};
const DIRCTION = {
    top:1,
    bottom:2,
    left:3,
    right:4
}

export default class Snake extends Component{
    constructor(props){
        super(props);
        this.state = {
            count:0
        }
    }
    componentWillMount(){
        var n = 20;
        var arr = [];
        for(var i = 0; i < n; i++ ){
            var temp = [];
            for(var j = 0; j < n; j++){
                temp[j] = TYP.normal;    
            }
            arr.push(temp);
        }
        var body = [
            {r:6,c:10},
            {r:7,c:10},
            {r:8,c:10},
            {r:9,c:10}
        ];
        var food = {r:14,c:14};    
        this.conf = {
            run:true,
            n:n,
            dirction:DIRCTION.top,
            arr:arr,
            body:body,
            food:food
        };
        
        this.renderSake();
        

        window.addEventListener("keydown",this.keydown.bind(this));

    }
    componentWillUnmount(){
        window.removeEventListener("keydown",this.keydown);
    }
    keydown=(event)=>{
        var key = event.key;
        if(!this.conf.run && this.conf.timer){
            return ;
        }
        if(key === "w" && this.conf.dirction !== DIRCTION.top){
             //上
             this.conf.dirction = DIRCTION.top;
        }else if(key === "s" && this.conf.dirction !== DIRCTION.bottom){
            //下
            this.conf.dirction = DIRCTION.bottom;
        }else if(key === "a" && this.conf.dirction !== DIRCTION.left){
            //左     
            this.conf.dirction = DIRCTION.left;
        }else if(key === "d" && this.conf.dirction !== DIRCTION.right){
            //右
            this.conf.dirction = DIRCTION.right;
        }
    }

    mainTimer =()=>{
        var me = this;
        if(me.conf.timer){
            return ;
        }
        

        me.conf.timer = setInterval(function(){
            if(me.conf.dirction === DIRCTION.top){
                //上
                me.move(-1,0);
            }else if(me.conf.dirction === DIRCTION.bottom){
                //下
                me.move(1,0);
            }else if(me.conf.dirction === DIRCTION.left ){
                //左     
                me.move(0,-1);
            }else if(me.conf.dirction === DIRCTION.right ){
                //右
                me.move(0,1);
            }
        },360);
    }
    moveCheck(r,c){
        //校验
        var body = this.conf.body;
        var head = body[0];
        var food = this.conf.food;
        var n = this.conf.n;
        
        var nextHead = {
            r:head.r + r,
            c:head.c + c 
        }

        //检查出界
        if((nextHead.r  >= n) || (nextHead.r < 0 ) || (nextHead.c >= n) || (nextHead.c < 0) ){
            return false;
        }

        //检查咬自己,没有咬到就运动
        for(var i = body.length-1; i  >= 1; i--){
            var item = body[i];
            if(item.r === nextHead.r && item.c === nextHead.c ){
                return false;
            }
            item.r = body[i-1].r;
            item.c = body[i-1].c;
        }

        //检查吃食物
        if(food.r === nextHead.r && food.c === nextHead.c){
            //吃东西
            body.push({
                r:food.r,
                c:food.c
            });

            //记录分数
            this.setState({
                count:this.state.count + 1    
            });

            //重新创建食物
            this.conf.food = this.createFood();
        }
        
        body[0] = nextHead;
        return true;
        
    }
    move(r,c){
        //上下
        if(this.moveCheck(r,c)){
            //可以下一步
            this.renderSake();
        }else{
            //游戏结束
            this.conf.run = false;
            clearInterval(this.conf.timer);
            this.conf.timer = null;
            alert("游戏结束");
        }
    }
    renderSake(){
        //渲染蛇的身体
        var config = JSON.parse(JSON.stringify(this.conf.arr));
        var body = this.conf.body;
        var food = this.conf.food; 
        this.setFood(config,food);
        this.setBody(config,body);
        this.setState({
            config:config
        });
    }
    createFood(){
        //创建食物
        var food = this.validFood();
        var max = 30;
        while(!food && max > 0){  //防止死循环和获取的食物坐标在蛇的身体上
            food = this.validFood();
            max--;
        }
        return food;
    }
    validFood(){
        //校验食物坐标是否可用
        var body = this.conf.body;
        var n = this.conf.n;
        var r = Math.floor(Math.random()* n);
        var c = Math.floor(Math.random()* n);
        for(var i = 0,len = body.length; i < len; i++){
            var item = body[i];
            if(item.r === r && item.c === c){
                return false; 
            }
        }
        return {r,c};
    }
    setBody(config,body){
        //设置蛇身体
        for(var i = 1,len = body.length; i < len; i++){
            var item = body[i];
           config[item.r][item.c] = TYP.body;  
        }
        config[body[0].r][body[0].c] = TYP.head;
    }
    setFood(config,food){
        //设置食物
        config[food.r][food.c] = TYP.food;
    }
    getClass=(item)=>{
        if(item === TYP.head){
            return "head";    
        }else if(item === TYP.body){
            return "body";
        }else if(item === TYP.food){
            return "food";
        }
    }

    render(){
        return (
            <div className="Snake">
                <button className="start" onClick={this.mainTimer}> 点击开始</button>
                <p>分数:{this.state.count}</p>
                <div className="box">
                {
                    this.state.config.map((item,index)=>{
                        return <div className="cols" key={index} >
                        {
                            item.map((itm,idx)=>{
                                return <div className={ this.getClass(itm) }  key={index + '-'+ idx} ></div>
                            })    
                        }</div>
                    })
                }
                </div>
            </div>
        );
    }

}

snake.less

#root{
    height: 100%;

}
.Snake{
    width: 100%;
    height: 100%;
    text-align: center;
    background: #fff;
    overflow: hidden;
    button{
        width: 100px;
        height: 30px;
    }
    .box{
        width: 400px;
        margin: 10px auto;
        div.cols{
            overflow: hidden;
            >div{
                float: left;
                width: 20px;
                height: 20px;
                box-sizing: border-box;
                border: 1px solid #dedede;
                border-inline-start-style: unset;
               
            }  
            div.body{
                background: blueviolet;
            } 
            div.head{
                background: red;    
            }
            div.food{
                background: gold;
            }
        }

    }
}