vue3+ts开发贪吃蛇

93 阅读1分钟

首先定义一个Target的接口来定义坐标点

interface Target{
  x: number,
  y: number
}

定义一个Snake的接口存在所需要的变量

interface Snake {
  arr: Target[],//存放所有的数组
  activeArr: Target[],//存放蛇位置的数组
  target:Target,//目标点坐标
  direction:number,//方向 上下左右
  timer:number//蛇移动速度
}

初始化一个reactive

const count = reactive<Snake>({
  arr: [],
  activeArr:[],
  target:{x:random(0,50),y:random(0,50)},
  timer:1000,
  direction:random(0,4)  // 随机一个方向 0 1 2 3 4 5 6 7 上下左右  只写了0-4 后边想写能斜着移动呢
})

生成随机数

const random=(min:number,max:number):number=>{
  return Math.floor(Math.random() * max+min)
}

初始化

const init=():void=>{
  handleKeyDown()
  //生成表格
  for (let i = 0; i < 50; i++) {
    for (let j = 0; j < 50; j++) {
      count.arr.push({
        x:j,
        y:i
      })
    }
  }
  // 初始化时不让它在最边上 默认长度是 4
  let x=random(4,45)
  let y=random(4,45)
  count.activeArr.push({x,y})
  switch (count.direction) {
    case 0:
      count.activeArr.push({x,y:y+1},{x,y:y+2},{x,y:y+3})
      break;
    case 1:
      count.activeArr.push({x,y:y-1},{x,y:y-2},{x,y:y-3})
      break;
    case 2:
      count.activeArr.push({x:x+1,y},{x:x+2,y},{x:x+3,y})
      break;
    default:
      count.activeArr.push({x:x-1,y},{x:x-2,y},{x:x-3,y})
      break;
  }
  //生成目标点
  count.target=targetFn()
  // 检测键盘方向键

  //开启定时器
  const timer=setInterval(()=>{
    let x=count.activeArr[0].x
    let y=count.activeArr[0].y
    switch (count.direction) {
      case 0:
        y--
        break;
      case 1:
        y++
        break;
      case 2:
        x--
        break;
      default:
        x++
        break;
    }
    if(y<0||y>49||x<0||y>49){
      alert('Game Over');
      clearInterval(timer)
      return
    }
    let endSpot=count.activeArr.pop()
    count.activeArr.unshift({x,y})
    // 吃到了 重新生成目标点
    console.log(count.target,x,y);
    
    if(count.target.x==x&&count.target.y==y){
      console.log('进来');
      
      count.target=targetFn()
      count.activeArr.push(endSpot as Target)
    }
  },count.timer)
    }

生成目标点 以及监听键盘事件

const targetFn=():Target=>{
  let target:Target={x:random(0,50),y:random(0,50)}
  return count.activeArr.some(item1 => item1.x === target.x && item1.y === target.y)?targetFn():target
}
const handleKeyDown=()=>{
  document.onkeydown=event=>{
    switch(event.key) {
      case 'ArrowUp':
        if(count.direction==0)return
        count.direction = 0;
        break;
      case 'ArrowDown':
        if(count.direction==1)return
        count.direction = 1;
        break;
      case 'ArrowLeft':
        if(count.direction==2)return
        count.direction = 2;
        break;
      case 'ArrowRight':
        if(count.direction==3)return
        count.direction = 3;
        break;
      default:
        break;
    }
    console.log(event.key);
  }
}

最后 执行初始化方法

onMounted(init)

其他代码

<template>
  <div id="div">
    <div v-for="item in count.arr" :class="{active:count.activeArr.some(item1 => item1.x === item.x && item1.y === item.y),target:item.x==count.target.x&&item.y==count.target.y}"></div>
  </div>
</template>

<style scoped>
#div {
  width: 500px;
  height: 500px;
  margin: auto;
  display: flex;
  border: 1px solid #ccc;
  flex-wrap: wrap
}

#div>div {
  width: 10px;
  height: 10px;
  border: 1px solid #ccc;
  box-sizing: border-box;
}
.active{
  background:#ccc;
}
.target{
  background:red;
}
</style>

QQ截图20230516142947.png 另外提出一个问题,箭头所指这里 是不是要用断言?