欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Vue3實(shí)現(xiàn)數(shù)字華容道游戲的示例代碼

 更新時(shí)間:2022年04月19日 11:08:19   作者:vagg  
這篇文章主要為大家詳細(xì)介紹了如何利用Vue編寫(xiě)一個(gè)數(shù)字華容道游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

恰逢春之四月,天氣忽熱忽涼,遇游戲大賽,以笨拙之技,書(shū)一篇小文。

游戲規(guī)則:存在n*n的格子,需要將它們按數(shù)字順序或圖片順序一一還原即可。

環(huán)境

主要環(huán)境:

vue3 version:3.2.4

vite version:2.5.0

vue-router version:4.0.14

注:這個(gè)游戲的路由使用的是自動(dòng)路由插件

主要插件:

windicss version:3.5.1

預(yù)覽地址

代碼地址

運(yùn)行如圖:

思路

  • 搭建環(huán)境,下載依賴
  • 運(yùn)行項(xiàng)目
  • 利用windicss主體兼容pc和移動(dòng)端

姑且認(rèn)為小于1024的是平板或者手機(jī) lg(1024px)

App.vue

<div class="relative w-full h-full lg:(w-750px h-800px)">
    <route-view
</div>

主體Game.vue設(shè)置4個(gè)主體組件:GameTool.vue游戲工具欄(返回、開(kāi)始和步數(shù)統(tǒng)計(jì))、GameCnt.vue游戲主體、Tip.vue開(kāi)局提示、GamePass.vue游戲通過(guò)

實(shí)現(xiàn)

GameCnt

布局

  • 先畫(huà)出3*3的格子,這里有多種方法,筆者這里采取最簡(jiǎn)單的動(dòng)態(tài)grid布局實(shí)現(xiàn),后來(lái)因?yàn)閏ss動(dòng)畫(huà)選取的是transform則不用gird布局了
  • 寬高獲取,這里要獲取,原因是使用了transform位移動(dòng)畫(huà),則需要平移距離和寬高了
  • 設(shè)置lazyShow,讓第一次渲染不會(huì)有transform動(dòng)畫(huà)
  • 隱藏最后一個(gè),利用數(shù)組對(duì)象value值+css實(shí)現(xiàn)
  • 添加其他css(windicss不好實(shí)現(xiàn)的css)
// 定義行個(gè)數(shù)
const rowLen = 3
// 定義cnt寬高和item的寬高
const cntWidth = ref(0)
const cntHeight = ref(0)
const itemWidth = ref(0)
const itemHeight = ref(0)

// 定義數(shù)組
const lists = ref([])

lists.value = new Array(rowLen.value * rowLen.value).fill(1).map((item, index) => ({
    key: index, // 存儲(chǔ)原序號(hào)
    value: item, // 1 代表不是空位
    moveIndex: index
  }))

// 設(shè)置最后一個(gè)為-1
  lists.value[lists.value.length - 1]['value'] = 0
  
//獲取dom和渲染
onMounted(() => {
   // 獲取cnt寬高和item的寬高
  getCntWidth()
  // 讓第一次渲染不會(huì)有transform動(dòng)畫(huà)
  lazyShow.value = false
})
<div v-show="!lazyShow" v-for="(item, index ) in lists" class="box rounded-md  overflow-hidden absolute"
      :class="[item.value ? 'origin' : 'opacity-0']" @click="boxClick(item)" :style="{
        transform: `translate(${(item.moveIndex % rowLen) * (1 / rowLen) * cntWidth}px, ${parseInt(item.moveIndex / rowLen) * (1 / rowLen) * cntHeight}px) `, width: itemWidth + 'px', height: itemHeight + 'px'
      }">
    <p class="absolute z-10 text-light-100 left-1/2 top-1/2" :class="hasImg ? 'opacity-60' : ''"
        :style="{ 'font-size': (180 / rowLen) + 'px' }">{{ item.key + 1 }}</p>
</div>

點(diǎn)擊元素的交換

核心代碼:

// 是否在一行
  const isInline = parseInt(index / rowLen.value) === parseInt(emptyIndex / rowLen.value)
 
 // 在一行是否相鄰
  Math.abs(emptyIndex - index) === 1
   
  // 不在一行是否是上下關(guān)系
  Math.abs(index - emptyIndex) === rowLen.value

點(diǎn)擊元素上下左右的交換

先判斷是否在一行,再判斷是否相鄰即可。

  • 先判斷是否在一行
  • 在一行是否相鄰或不在一行是否是上下關(guān)系
  • 看情況調(diào)用changeIndex
// 是否在一行
  if (isInline) {
    // 一行則判斷是否左右相鄰
    console.log('相差:' + (index - emptyIndex))
    // 是否相鄰
    if (Math.abs(emptyIndex - index) === 1) {
      // 改變對(duì)應(yīng)moveIndex
      changeIndex()
    } else {
      console.log('不相鄰')
      return
    }
  } else {
    //  不是則判斷是否上下相鄰
    console.log('相差:' + (index - emptyIndex))
    // 是否上或者下
    if (Math.abs(index - emptyIndex) === rowLen.value) {
      // 改變對(duì)應(yīng)moveIndex
      changeIndex()
    } else {
      console.log('不相鄰')
      return
    }
  }
  
  // 聲明改變的數(shù)組moveIndex的方法
  const changeIndex = () => {
    // 步數(shù)改變
    emit('stepChange');
    // 改變對(duì)應(yīng)數(shù)組里的moveIndex 注意不是 index和 moveIndex
    ([lists.value[item.key].moveIndex, lists.value[emptyItem.key].moveIndex] = [emptyIndex, index]);
  }

判斷游戲通過(guò)

這個(gè)地方很簡(jiǎn)單,主要判斷數(shù)組對(duì)象每一個(gè)是否原序號(hào)key是否都相等于移動(dòng)后的moveIndex

// 是否都成功
  const getIsAllOk = () => {
    // 
    return lists.value.some(item => item.moveIndex !== item.key)
  }
  // // 判斷是否都成功了
  const flag = getIsAllOk()
  console.log(flag)
  if (!flag) {
    // alert('成功')
    gamePass()
  }

注:這個(gè)gamePass需要在defineEmits里注冊(cè)

打亂數(shù)組

這個(gè)地方很有點(diǎn)麻煩,存在無(wú)解的情況,暫時(shí)沒(méi)想到更好的實(shí)現(xiàn)方法,這里使用的是排序打亂

// 打亂數(shù)據(jù)
const mixData = () => {
  const arr = new Array(rowLen.value * rowLen.value).fill(0).map((item, index) => index)
  // console.log(arr)
  arr.sort(() => {
    return Math.random() > 0.5 ? -1 : 1
  })
  arr.forEach((item, index) => {
    lists.value[index].moveIndex = item
  })

  // 如果直接是成功的則重新來(lái)一次排序
  const flag = getIsAllOk()
  if (!flag) {
    // alert('成功')
    mixData()
  }
}

注:有想法可以溝通下,一起提升!

動(dòng)態(tài)格子和寬高

const params = route.query
// 定義行個(gè)數(shù)
rowLen.value = +params.num || 3;

// 重新獲取item寬高
cnt.value && getCntWidth()

圖片華容道

圖片使用定位。然后超出截取即可展示出效果

<img v-if="hasImg" class="absolute" :src="Default" alt=""
        :style="{ width: cntWidth + 'px', maxWidth: cntWidth + 'px', height: cntHeight + 'px', left: -(item.key % rowLen) * (1 / rowLen) * cntWidth + 'px', top: -parseInt(item.key / rowLen) * (1 / rowLen) * cntHeight + 'px' }">
  
 // 是否渲染圖片
  hasImg.value = params.hasImg === '1' ? true : false;

GameTool

左側(cè)是返回按鈕,右側(cè)是重新開(kāi)始按鈕,中間是移動(dòng)步數(shù)

移動(dòng)步數(shù)后中間會(huì)調(diào)整為移動(dòng)多少次

注:圖標(biāo)從iconfont找的

GamePass

  • 先布局全屏遮罩
  • 設(shè)置中間div樣式
  • 設(shè)置通過(guò)成功提示和步數(shù)提示即可

GameTip

這個(gè)組件就是開(kāi)局的提示組件

Menu

這個(gè)組件就是菜單頁(yè) 設(shè)置了兩種入口

最后

GameCnt 可以寫(xiě)一些測(cè)試代碼,方便測(cè)試下通關(guān)后的情況

GameCnt 的塊級(jí)效果優(yōu)化過(guò),否則只有顏色,不太好看

GamePass 還有優(yōu)化空間,例如圖片通過(guò)可以有不同效果啊等等

整體難度不高,可以練習(xí)下vue3,以及游戲思維

到此這篇關(guān)于基于Vue3實(shí)現(xiàn)數(shù)字華容道游戲的示例代碼的文章就介紹到這了,更多相關(guān)Vue數(shù)字華容道內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深度剖析?Vue3?在瀏覽器的運(yùn)行原理

    深度剖析?Vue3?在瀏覽器的運(yùn)行原理

    這篇文章主要介紹了深度剖析Vue3在瀏覽器的運(yùn)行原理,文章通過(guò)圍繞主題展開(kāi)相關(guān)詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • vscode中vue-cli項(xiàng)目es-lint的配置方法

    vscode中vue-cli項(xiàng)目es-lint的配置方法

    本文主要介紹vscode中 vue項(xiàng)目es-lint的配置方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧
    2018-07-07
  • vue中$nexttick,$set,$forceupdate的區(qū)別

    vue中$nexttick,$set,$forceupdate的區(qū)別

    本文主要介紹了vue中$nexttick,$set,$forceupdate的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 前端Vue項(xiàng)目部署到服務(wù)器的全過(guò)程以及踩坑記錄

    前端Vue項(xiàng)目部署到服務(wù)器的全過(guò)程以及踩坑記錄

    使用Vue做前后端分離項(xiàng)目時(shí),通常前端是單獨(dú)部署,用戶訪問(wèn)的也是前端項(xiàng)目地址,因此前端開(kāi)發(fā)人員很有必要熟悉一下項(xiàng)目部署的流程,下面這篇文章主要給大家介紹了關(guān)于前端Vue項(xiàng)目部署到服務(wù)器的全過(guò)程以及踩坑記錄的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Django與Vue語(yǔ)法的沖突問(wèn)題完美解決方法

    Django與Vue語(yǔ)法的沖突問(wèn)題完美解決方法

    這篇文章主要介紹了Django與Vue語(yǔ)法的沖突問(wèn)題完美解決方法,本文給大家分享了兩種解決方法,需要的朋友參考下吧
    2017-12-12
  • vue項(xiàng)目中created()被調(diào)用多次的踩坑實(shí)戰(zhàn)

    vue項(xiàng)目中created()被調(diào)用多次的踩坑實(shí)戰(zhàn)

    在vue項(xiàng)目中我在created中調(diào)用了兩次get數(shù)據(jù)請(qǐng)求,所以下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目中created()被調(diào)用多次的踩坑實(shí)戰(zhàn),需要的朋友可以參考下
    2023-03-03
  • vue中手機(jī)號(hào),郵箱正則驗(yàn)證以及60s發(fā)送驗(yàn)證碼的實(shí)例

    vue中手機(jī)號(hào),郵箱正則驗(yàn)證以及60s發(fā)送驗(yàn)證碼的實(shí)例

    下面小編就為大家分享一篇vue中手機(jī)號(hào),郵箱正則驗(yàn)證以及60s發(fā)送驗(yàn)證碼的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • vue中form表單禁用專用組件介紹

    vue中form表單禁用專用組件介紹

    這篇文章主要介紹了vue中form表單禁用專用組件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • vue動(dòng)態(tài)組件之:is在組件中的使用場(chǎng)景

    vue動(dòng)態(tài)組件之:is在組件中的使用場(chǎng)景

    這篇文章主要介紹了vue動(dòng)態(tài)組件之:is在組件中的使用場(chǎng)景,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Vue之創(chuàng)建項(xiàng)目及目錄方式

    Vue之創(chuàng)建項(xiàng)目及目錄方式

    這篇文章主要介紹了Vue之創(chuàng)建項(xiàng)目及目錄方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11

最新評(píng)論