滑动
通过‘@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>