简陋的前端贪吃蛇

绿色方块代表食物,红色代表蛇头,黄色代表蛇身

<template>
  <div class="main">
    <button @click="gameStart" class="startButtom">开始游戏</button>
    <div class="canvas">
      <div class="box" v-for="i in areaSize" :key="i" :id="i"/>
    </div>
  </div>
</template>

<script lang="ts">
import { nextTick,defineComponent,ref } from 'vue';

export default defineComponent({
  name: 'App',
  setup(){
    let htmlDivElement
    //贪吃蛇画布属性
    const attributes={
      //奇数
      widthGrid:7,
      //偶数  方便蛇初始化在地图中心
      heightGrid:8
    }
    let areaSize=attributes.widthGrid*attributes.heightGrid
    //贪吃蛇数组
    let sankeArry:{body:number[],direction:number}={
      body:[],
      //0上  1左  2右
      direction:0
    }
    //食物
    let food:number
    //画布初始化
    function canvasInitialization(widthGrid:number,heightGrid:number):void {
      htmlDivElement=document.getElementsByClassName('canvas')[0] as HTMLDivElement
      htmlDivElement.style.display='grid'
      htmlDivElement.style.gridTemplateColumns=`repeat(${widthGrid},20px)`
      htmlDivElement.style.gridTemplateRows=`repeat(${heightGrid},20px)`
      htmlDivElement.style.width=`${20*widthGrid}px`
      htmlDivElement.style.height=`${20*heightGrid}px`
      sankeInitialization(attributes.widthGrid,attributes.heightGrid)
      foodInitialization(areaSize)
    }
    //贪吃蛇身体初始化
    function sankeInitialization(widthGrid:number,heightGrid:number):void{
      let sankeInitializationId:number
      //蛇头
      sankeInitializationId=((heightGrid-2)/2*widthGrid)+(Math.floor(widthGrid/2)+1)
      sankeArry.body.push(sankeInitializationId)
      //蛇尾
      sankeInitializationId=((((heightGrid-2)/2)+1)*widthGrid)+(Math.floor(widthGrid/2)+1)
      sankeArry.body.push(sankeInitializationId)
      console.log(sankeArry.body)
    }
    //食物的初始化
    function foodInitialization(areaSize:number) {
      let control=1
      food=Math.floor(Math.random()*areaSize+1)
      while (control){
        if (sankeArry.body.includes(food)){
          food=Math.floor(Math.random()*areaSize)
        }else {
          control--
        }
      }
    }
    //蛇的绘制
    function sankeDraw(sankeBody:number[]):void{
      for (let i = 0;i<sankeBody.length;i++){
        htmlDivElement=document.getElementById(`${sankeBody[i]}`) as HTMLDivElement
        if (i===0){
          htmlDivElement.style.backgroundColor='red'
        }else{
          htmlDivElement.style.backgroundColor='yellow'
        }
      }
    }
    //食物的绘制
    function foodDraw() {
      htmlDivElement=document.getElementById(food.toString()) as HTMLDivElement
      htmlDivElement.style.backgroundColor='green'
    }
    //触碰食物
    function touchFood(sankeTopId:number):boolean{
      console.log(food)
      if (sankeTopId===food){
        foodInitialization(areaSize)
        foodDraw()
        return false
      }
      return true
    }
    //触碰蛇身 gameover
    function touchBody(sankeNextTopId:number,sankebody:number[]):boolean {
      console.log(sankeNextTopId)
      console.log(sankebody)
      if (sankebody.includes(sankeNextTopId)){
        //控制定时器结束
        stop=true
        console.log('触碰到了身体')
        alert('游戏结束,即将重开')
        location.reload()
      }
      return true
    }
    //根据蛇头方向来改变sanke数组 只改变蛇头
    function changeSankeArr(sankeArry:{body:number[],direction:number},widthGrid:number,heightGrid:number):{body:number[],direction:number}{
      let sankeNextTopId:number
      switch (sankeArry.direction) {
        case 0:
          //向上
          if (sankeArry.body[0]<widthGrid){
            //上边界
            console.log('上边界')
            sankeNextTopId=widthGrid*heightGrid-widthGrid+sankeArry.body[0]
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }else{
            sankeNextTopId=sankeArry.body[0]-widthGrid
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }
          if (touchFood(sankeArry.body[0]))
            sankeArry.body=sankeArry.body.filter((item,index)=>{return  index < sankeArry.body.length-1})
          return sankeArry
        case 1:
          //向左
          if (sankeArry.body[0]%widthGrid===1){
            //左边界
            console.log('左边界')
            sankeNextTopId=sankeArry.body[0]+widthGrid-1
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }else{
            sankeNextTopId=sankeArry.body[0]-1
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }
          if (touchFood(sankeArry.body[0]))
            sankeArry.body=sankeArry.body.filter((item,index)=>{return index < sankeArry.body.length-1})
          return sankeArry
        case 2:
          //向下
          if (sankeArry.body[0]<=(widthGrid*heightGrid)&&(sankeArry.body[0]>=(widthGrid*(heightGrid-1)+1))){
            //下边界
            console.log('下边界')
            sankeNextTopId=widthGrid-widthGrid*heightGrid+sankeArry.body[0]
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }else{
            sankeNextTopId=sankeArry.body[0]+widthGrid
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }
          if (touchFood(sankeArry.body[0]))
            sankeArry.body=sankeArry.body.filter((item,index)=>{return index < sankeArry.body.length-1})
          return sankeArry
        default:
          if (!(sankeArry.body[0]%widthGrid)){
            //右边界
            console.log("右边界")
            sankeNextTopId=sankeArry.body[0]-widthGrid+1
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }else {
            sankeNextTopId=sankeArry.body[0]+1
            if (touchBody(sankeNextTopId,sankeArry.body))
              sankeArry.body.unshift(sankeNextTopId)
          }
          if (touchFood(sankeArry.body[0]))
            sankeArry.body=sankeArry.body.filter((item,index)=>{return  index < sankeArry.body.length-1})
          //向右
          return sankeArry
      }
    }
    //蛇移动,还原画布,最后一位
    function reductionCanves(sankeBody:number[]){
      htmlDivElement=document.getElementById((sankeBody[sankeBody.length-1]).toString()) as HTMLDivElement
      htmlDivElement.style.backgroundColor='black'
    }
    //游戏初始化
    nextTick(()=>{
      canvasInitialization(attributes.widthGrid,attributes.heightGrid)
      sankeDraw(sankeArry.body)
      foodDraw()
    })
    //系统自动前进 1.6s间隔
    let reactionTime=0
    let stop=false
    function autoMove() {
      if (stop===true){
        return
      }
      let delay:number=1000+reactionTime
      let timer=setTimeout(()=>{
        reductionCanves(sankeArry.body)
        sankeArry=changeSankeArr(sankeArry,attributes.widthGrid,attributes.heightGrid)
        sankeDraw(sankeArry.body)
        delay+=300
        console.log(delay,`定时器时间`)
        autoMove()
        delay-=300
        if (reactionTime!=0)
          reactionTime=0
        clearTimeout(timer)
      },delay)
    }
    //点击开始
    //计时器只运行一次
    let workonly=true
    function gameStart() {
      console.log(sankeArry)
      //聚焦
      htmlDivElement=document.getElementsByClassName('canvas')[0] as HTMLDivElement
      htmlDivElement.focus()
      htmlDivElement=document.getElementsByClassName('startButtom')[0] as HTMLDivElement
      htmlDivElement.style.pointerEvents='none'
      document.onkeyup=function listenKey(event:any) {
        if (workonly===true){
          autoMove()
          workonly=false
        }
        console.log(event)
        let controlMath=sankeArry.body[0]-sankeArry.body[1]
        console.log(controlMath)
        //上 ArrowUp w
        if (event.key==='w'||event.key==='ArrowUp'){
          console.log('上')
          if (controlMath!==attributes.widthGrid){
            reductionCanves(sankeArry.body)
            sankeArry.direction=0
            sankeArry=changeSankeArr(sankeArry,attributes.widthGrid,attributes.heightGrid)
            console.log(sankeArry.body)
            sankeDraw(sankeArry.body)
          }
        }
        //左 ArrowLeft a
        if (event.key==='a'||event.key==='ArrowLeft'){
          console.log('左')
          if (controlMath!==1){
            reductionCanves(sankeArry.body)
            sankeArry.direction=1
            sankeArry=changeSankeArr(sankeArry,attributes.widthGrid,attributes.heightGrid)
            console.log(sankeArry.body)
            sankeDraw(sankeArry.body)
          }
        }
        //下 ArrowDown s
        if (event.key==='s'||event.key==='ArrowDown'){
          console.log('下')
          if (controlMath!==-attributes.widthGrid){
            reductionCanves(sankeArry.body)
            sankeArry.direction=2
            sankeArry=changeSankeArr(sankeArry,attributes.widthGrid,attributes.heightGrid)
            console.log(sankeArry.body)
            sankeDraw(sankeArry.body)
          }
        }
        //右 ArrowRight d
        if (event.key==='d'||event.key==='ArrowRight'){
          console.log('右')
          if (controlMath!==-1){
            reductionCanves(sankeArry.body)
            sankeArry.direction=3
            sankeArry=changeSankeArr(sankeArry,attributes.widthGrid,attributes.heightGrid)
            console.log(sankeArry.body)
            sankeDraw(sankeArry.body)
          }
        }
      }
    }
    return{
      areaSize,gameStart
    }
  }
});
</script>

<style>
  *{
    margin: 0;
    padding: 0;
  }
  .main{
    width: 100%;
    height: 100%;
  }
  .canvas{
    background-color: black;
    color: #40a9ff;
  }
  .box{
    width: 19px;
    height: 19px;
    border: 1px solid #999999;
  }
</style>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值