简单版 2048

滑动

通过‘@touchstart=“onTouchStart” ’,‘@touchend=“onTouchEnd”’ 来判断滑动方向

<template>
  <view class="game-box" 
    @touchstart="onTouchStart" 
    @touchend="onTouchEnd">

    <div id="gameCnt" class="cnt h-full relative" ref="cnt" style="width : 80%; margin: 10%;">
        <view v-show="!data.lazyShow" v-for="(item, _index ) in arr" class="box rounded-md ">
            {{ item.value }}
        </view>
    </div>
  </view>
</template>

<script setup lang="ts">
import { reactive, onMounted, nextTick, watch, ref } from 'vue'

const data = reactive({
  lazyShow: false,
  numbers: [] as number[],
  size: 4 as number,  // 4x4 grid

  startX: 0,
  startY: 0,
  slideStatus: false, // 滑动状态
})


export interface arrType {
  index: number
  value: number
}

const arr = ref<Array<arrType>>([
  { index: 0, value: 0 },
  { index: 1, value: 0 },
  { index: 2, value: 0 },
  { index: 3, value: 0 },
  { index: 4, value: 0 },
  { index: 5, value: 0 },
  { index: 6, value: 0 },
  { index: 7, value: 0 },
  { index: 8, value: 0 },
  { index: 9, value: 0 },
  { index: 10, value: 0 },
  { index: 11, value: 0 },
  { index: 12, value: 0 },
  { index: 13, value: 0 },
  { index: 14, value: 0 },
  { index: 15, value: 0 }
])

const score = ref<number>(0)
let value0Arr: Array<arrType> = []

// 数组为0值的数组
watch(
  () => arr,
  () => {

    value0Arr = arr.value.filter((item) => {
      return item.value === 0
    })
  },
  {
    deep: true,
    immediate: true
  }
)

onMounted(() => {  
  init()
})

const init = () => {
  score.value = 0
  arr.value.forEach((item) => (item.value = 0))
  nextTick(() => {
    createRandomNumber(2)
  })
}

const onTouchStart = (e: TouchEvent) => {
  data.startX = e.touches[0].clientX
  data.startY = e.touches[0].clientY
}

const onTouchEnd = (e: TouchEvent) => {
  if (data.slideStatus === true) return
  data.slideStatus = true

  let endX = e.changedTouches[0].clientX
  let endY = e.changedTouches[0].clientY

  let deltaX = endX - data.startX
  let deltaY = endY - data.startY
  // 判断滑动距离
  if (Math.abs(deltaX) < 5 && Math.abs(deltaY) < 5) return

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    if (deltaX > 0) {
      moveItem('right')
    } else {
      moveItem('left')
    }
  } else {
    if (deltaY > 0) {
      moveItem('down')
    } else {
      moveItem('up')
    }
  }
  data.slideStatus = false
}

const moveItem = (direction: string) => {
  let isWin: Boolean = false
  if (direction == 'right' || direction == 'left') {
    for (let i = 0; i < 4; i++) {
      let itemArr: Array<number> = [
        arr.value[i * 4].value,
        arr.value[i * 4 + 1].value,
        arr.value[i * 4 + 2].value,
        arr.value[i * 4 + 3].value
      ].filter((item: number) => item != 0)

      const length = itemArr.length
      if (length > 1) {
        if (direction == 'right') {
          for (let j = length; j > 1; j--) {
            if (!itemArr[j - 1]) {
              continue
            }
            if (itemArr[j - 1] == itemArr[j - 2]) {
              itemArr[j - 1] = 2 * itemArr[j - 1]
              score.value += itemArr[j - 1]
              if (itemArr[j - 1] === 2048) isWin = true
              itemArr[j - 2] = 0
            }
          }
        } else {
          for (let j = 0; j < length - 1; j++) {
            if (!itemArr[j]) {
              continue
            }
            if (itemArr[j] == itemArr[j + 1]) {
              itemArr[j] = 2 * itemArr[j]
              score.value += itemArr[j]
              if (itemArr[j] === 2048) isWin = true
              itemArr[j + 1] = 0
            }
          }
        }
      }
      itemArr = itemArr.filter((item: number) => item != 0)
      const finalLength = itemArr.length
      if (finalLength != 4) {
        for (let k = 0; k < 4 - finalLength; k++) {
          if (direction == 'right') {
            itemArr.unshift(0)
          } else {
            itemArr.push(0)
          }
        }
      }
      arr.value[i * 4].value = itemArr[0]
      arr.value[i * 4 + 1].value = itemArr[1]
      arr.value[i * 4 + 2].value = itemArr[2]
      arr.value[i * 4 + 3].value = itemArr[3]
    }
  } else {
    for (let i = 0; i < 4; i++) {
      let itemArr = [
        arr.value[i + 0].value,
        arr.value[i + 4].value,
        arr.value[i + 8].value,
        arr.value[i + 12].value
      ].filter((item: number) => item != 0)
      const length = itemArr.length
      if (length > 1) {
        if (direction == 'down') {
          for (let j = length; j > 1; j--) {
            if (!itemArr[j - 1]) {
              continue
            }
            if (itemArr[j - 1] == itemArr[j - 2]) {
              itemArr[j - 1] = 2 * itemArr[j - 1]
              score.value += itemArr[j - 1]
              if (itemArr[j - 1] === 2048) isWin = true
              itemArr[j - 2] = 0
            }
          }
        } else {
          for (let j = 0; j < length - 1; j++) {
            if (!itemArr[j]) {
              continue
            }
            if (itemArr[j] == itemArr[j + 1]) {
              itemArr[j] = 2 * itemArr[j]
              score.value += itemArr[j]
              if (itemArr[j] === 2048) isWin = true
              itemArr[j + 1] = 0
            }
          }
        }
      }
      itemArr = itemArr.filter((item: number) => item != 0)
      const finalLength = itemArr.length
      if (finalLength != 4) {
        for (let k = 0; k < 4 - finalLength; k++) {
          if (direction == 'down') {
            itemArr.unshift(0)
          } else {
            itemArr.push(0)
          }
        }
      }
      arr.value[i + 0].value = itemArr[0]
      arr.value[i + 4].value = itemArr[1]
      arr.value[i + 8].value = itemArr[2]
      arr.value[i + 12].value = itemArr[3]
    }
  }

  nextTick(() => {
    if (value0Arr.length > 0) {
      nextTick(() => {
        createRandomNumber()
      })
    }
    if (isWin) {
      console.log('胜利!')
      return
    }
    if (value0Arr.length == 0) {
      const flag = isLoser()
      if (flag) {
        console.log('游戏结束!')
        return
      }
    }
  })
}

// 在值为0的地方,生成随机数
const createRandomNumber = (num?: number) => {
  let cellValue: number
  if (!num) {
    //获取2或者4,2出现改率为4两倍
    const randomNumber = Math.random()
    if (randomNumber < 0.67) {
      cellValue = 2
    } else {
      cellValue = 4
    }
  } else {
    cellValue = num
  }

  // 值随机放置在一个为0的cell
  const position = Math.floor(Math.random() * value0Arr.length)

  if (arr.value && value0Arr.length > 0) {
    arr.value[value0Arr[position].index].value = cellValue
  }
}

// 判断输赢
const isLoser = () => {
  let flag: Boolean = true
  // 竖向判断
  for (let i = 0; i < 12; i++) {
    if (arr.value[i].value === 0) continue
    if (arr.value[i].value === arr.value[i + 4].value) {
      flag = false
      break
    }
  }
  // 横向判断
  for (let i = 0; i < 15; i++) {
    if (arr.value[i].value === 0 || [3, 7, 11].includes(i)) continue
    if (arr.value[i].value === arr.value[i + 1].value) {
      flag = false
      break
    }
  }
  //   console.log(flag, 'flag')
  return flag
}
</script>

<style>

.relative {
  position: relative;
}

.absolute {
  position: absolute;
}

.flex {
  display: flex;
  justify-content: space-around;
}
.game-box {
  position: fixed;
  left: 0;
  right: 0;
  top: 100px;
  bottom: 0;
  z-index: 99;
}

.h-full { 
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

.box {
  box-shadow: 2px 2px 2px #999 inset, 3px 4px 4px #000;
  transition: all .3s;

  background-color: #f2f2f2;
  background-size: 100% 100%;
  /* padding: 60px; */
  width: 100px;
  height: 100px;  
  text-align: center;
  margin: 15px;
}
</style>
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值