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

使用vue3重構(gòu)拼圖游戲的實(shí)現(xiàn)示例

 更新時(shí)間:2021年01月25日 10:05:19   作者:劉小灰  
這篇文章主要介紹了使用vue3重構(gòu)拼圖游戲的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

花了兩天時(shí)間,重構(gòu)了項(xiàng)目中的一個(gè)拼圖小游戲(又名數(shù)字華容道),為了方便使用抽離成了獨(dú)立組件,效果如下:

線上體驗(yàn)

源碼地址在文章最后哦!

主要重構(gòu)點(diǎn)

原有拼圖游戲是通過(guò)開(kāi)源代碼加以改造,使用的是 vue2 。在實(shí)際項(xiàng)目使用一切正常,但還是存在以下痛點(diǎn)

  • 源代碼臃腫,暴露的配置項(xiàng)不足,特備是和項(xiàng)目現(xiàn)有邏輯結(jié)合時(shí)體現(xiàn)的更加明顯
  • 生成的游戲可能出現(xiàn)無(wú)解情況,為了避免無(wú)解,只好寫死幾種情況然后隨機(jī)生成
  • 源代碼是vue2版本,不支持vue3

最后決定使用 vue3 重新實(shí)現(xiàn)拼圖游戲,著重注意以下細(xì)節(jié)

  • 組件使用起來(lái)足夠簡(jiǎn)單
  • 可以自定義游戲難度
  • 支持圖片和數(shù)組兩種模式

實(shí)現(xiàn)思路

無(wú)論是拼圖片還是拼數(shù)字,其原理都是要把原本打亂的數(shù)組移動(dòng)成有序狀態(tài)。網(wǎng)上也有很多實(shí)現(xiàn)數(shù)字華容的的算法,算法主要需要解決的就是如何生成一組 隨機(jī)且有解 的數(shù)組,有的人可能有疑問(wèn),數(shù)組華容道還有可能無(wú)解嗎?

如果生成的游戲像上面這樣,那就是無(wú)解了。原理就像我們玩魔方一樣,正常情況下不管我們打亂的多亂都可以還原,但是如果我們把 某幾個(gè)塊摳出來(lái)?yè)Q換位置 ,那就可能還原不了了

網(wǎng)上也有很多算法可以避免生成無(wú)解的情況,但是寫的都比較高深,加上自己閱讀算法的能力有限,最后決定按照自己的思路實(shí)現(xiàn)。

我的思路其實(shí)比較簡(jiǎn)單,一句話總結(jié)就是逆向推理法,我們可以先從排列好的數(shù)組開(kāi)始,然后隨機(jī)的通過(guò) 移動(dòng) 打亂其順序,這樣肯定可以保證生成的題目有解,同時(shí)可以根據(jù)打亂的步數(shù)來(lái)控制游戲的難度,真是個(gè)一舉兩得的idear。

源碼實(shí)現(xiàn)

數(shù)據(jù)存放

首先我考慮的是使用一個(gè)一維數(shù)組來(lái)存放數(shù)據(jù)

let arr = [1,2,3,4,5,6,7,8,0] // 0 代表空白

但是這樣會(huì)出現(xiàn)一個(gè)問(wèn)題,就是移動(dòng)的時(shí)候邏輯變的相當(dāng)麻煩,因?yàn)橐痪S數(shù)組只能記錄數(shù)據(jù)并不能記錄豎直方向的位置,這個(gè)時(shí)候我們自然就想到使用二維數(shù)組了,比如,當(dāng)我們需要生成一個(gè)3*3的游戲時(shí)數(shù)據(jù)是這樣的:

let arr [
  [1,2,3],
  [4,5,6],
  [7,8,0]
]

這樣我們就可以通過(guò)下面來(lái)模擬x,y軸來(lái)表示每個(gè)數(shù)字的位置。比如0的位置是(2,2),6的位置是(1,2),如果我想移動(dòng)6和0的位置,只需要把他們的坐標(biāo)做調(diào)換即可。

移動(dòng)函數(shù)

數(shù)字華容道最關(guān)鍵的交互就是用戶點(diǎn)擊那個(gè)塊就移動(dòng)哪個(gè)塊,但是需要注意的是只有0附近的數(shù)組可以移動(dòng)。下面我們先完成移動(dòng)函數(shù)

 function move(x, y, moveX, moveY) {
  const num = state.arr[x][y];
  state.arr[x][y] = state.arr[moveX][moveY];
  state.arr[moveX][moveY] = num;
 }

是不是很簡(jiǎn)單,其實(shí)就是把要移動(dòng)的兩個(gè)數(shù)的下標(biāo)給交換下位置
有了移動(dòng)函數(shù),我們就可以實(shí)現(xiàn)上,下,左,右的移動(dòng)了

// 上移動(dòng)
 function moveTop(x, y) {
  if (x <= 0) return -1;
  //  開(kāi)始交換位置
  const okx = x - 1;
  move(x, y, okx, y);
  return {
   x: okx,
   y,
  };
 }
 //下移動(dòng)
 function moveDown(x, y) {
  if (x >= level - 1) return -1;
  const okx = x + 1;
  move(x, y, okx, y);
  return {
   x: okx,
   y,
  };
 }
 // 左移動(dòng)

 function moveLeft(x, y) {
  if (y <= 0) return -1;
  const oky = y - 1;
  move(x, y, x, oky);
  return {
   x,
   y: oky,
  };
 }

 // 右移動(dòng)
 function moveRight(x, y) {
  if (y >= level - 1) return -1;
  const oky = y + 1;
  move(x, y, x, oky);
  return {
   x,
   y: oky,
  };
 }

現(xiàn)在我們?cè)賹?shí)現(xiàn)一個(gè)判斷移動(dòng)方向的方法,如下所示:

 function shouldMove(x, y) {
  //  判斷向哪移動(dòng)
  const { emptyX, emptyY } = seekEmpty();
  if (x === emptyX && y !== emptyY && Math.abs(y - emptyY) === 1) {
   // 說(shuō)明在一個(gè)水平線上 可能是左右移動(dòng)
   if (y > emptyY) {
    moveLeft(x, y);
   } else {
    moveRight(x, y);
   }
  }
  if (y === emptyY && x !== emptyX && Math.abs(x - emptyX) === 1) {
   // 說(shuō)明需要上下移動(dòng)
   if (x > emptyX) {
    moveTop(x, y);
   } else {
    moveDown(x, y);
   }
  }
 }

if里面判斷的意思是如果我們點(diǎn)擊的塊是空白快或者不是和空白快挨著的那個(gè),那我們就不做任何處理

生成游戲面板

其實(shí)就是隨機(jī)調(diào)用上移,下移,左移,右移函數(shù),把數(shù)組打亂

 // 隨機(jī)打亂
 function moveInit(diffic) {
  state.arr = creatArr(level);
  const num = diffic ? diffic : state.diffec;
  const fns = [moveTop, moveDown, moveLeft, moveRight];
  let Index = null;
  let fn;
  for (let i = 0; i < num; i++) {
   Index = Math.floor(Math.random() * fns.length);
   //  moveConsole(Index);
   fn = fns[Index](startX, startY);
   if (fn != -1) {
    const { x, y } = fn;
    startX = x;
    startY = y;
   }
  }
 }

短短幾個(gè)函數(shù),就完成了核心邏輯,還有幾個(gè)函數(shù)沒(méi)有介紹到比如判斷游戲完成,尋找空白塊的位置,創(chuàng)建二維數(shù)組大家可自行閱讀源碼

使用vue3重構(gòu)

以上邏輯貌似和vue3沒(méi)什么關(guān)系,但是我們忽略了最重要的一點(diǎn),就是 改變數(shù)組后,視圖也就改變了 這不就是響應(yīng)式嗎,使用vue3后我們可以把關(guān)于游戲的所有邏輯放到一個(gè)js里面,大大減少了代碼的耦合度

const { arr, shouldMove, moveInit } = useCreateGame(
 gamedata.level,
 gamedata.difficulty,
 gameEndCallback
);

可能有的人會(huì)有疑問(wèn)?把所有邏輯抽離出來(lái)這不是很正常的操作嗎?難道用vue2的時(shí)候都不能抽離了?
但是大家不要忘記了,我們的這個(gè)數(shù)組需要是響應(yīng)式的,如果我們單獨(dú)把邏輯抽離出來(lái)那我們?cè)趈s文件里面改變數(shù)組還是響應(yīng)式的嗎

但當(dāng)我們使用vue3的composition-api時(shí)就可以再js文件中聲明一個(gè)響應(yīng)式變量,且在組件中使用時(shí)它還是響應(yīng)式的

export default function useCreateGame() {
//聲明一個(gè)響應(yīng)式變量
...
 const state = reactive({
  arr: [],
 });
...
 return {
 ...toRefs(state)
 ...
 }
 }
const { arr, shouldMove, moveInit } = useCreateGame(
 gamedata.level,
 gamedata.difficulty,
 gameEndCallback
);
// 這個(gè)時(shí)候 arr 還是響應(yīng)式的

這正是composition-api強(qiáng)大所在,有了composition-api我們可以任意組裝我們的邏輯代碼了

在vue2 如果要維護(hù)一個(gè)響應(yīng)式變量我們是不是就要使用vuex這種狀態(tài)管理器了,這樣就增加了代碼的耦合度

關(guān)于vite2

現(xiàn)在vite已經(jīng)到了vite2版本,并且官方還在飛快迭代中,使用vite2創(chuàng)建的項(xiàng)目默認(rèn)是可以使用setup新特性的,比如我們可以這樣寫:

<template>
 <div>
  {{ name }}
 </div>
</template>

<script setup>
import { ref } from "vue";
const name = ref('"公眾號(hào)碼不停息"');
</script>

等價(jià)于這樣寫

<template>
 <div>
  {{ name }}
 </div>
</template>
<script>
import { ref } from "vue";
export default {
 setup() {
  const name = ref("公眾號(hào)碼不停息");
  return {
   name,
  };
 },
};
</script>

看著就簡(jiǎn)單了很多,并且在setup版本中vue又出了幾個(gè)api,感興趣的可以去官網(wǎng)看下,個(gè)人感覺(jué)還是挺香的。因?yàn)樾抡Z(yǔ)法還是實(shí)驗(yàn)性質(zhì)的本次代碼重構(gòu)并未使用。

源碼地址

源碼地址:數(shù)字華容道拼圖游戲 歡迎start😍

最后

你可能感興趣:

基于vue-router思考🕓實(shí)現(xiàn)一個(gè)簡(jiǎn)易版vue-router
基于webpack打包多頁(yè)應(yīng)用,對(duì)前端工程化的思考

到此這篇關(guān)于使用vue3重構(gòu)拼圖游戲的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)vue3重構(gòu)拼圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue項(xiàng)目關(guān)閉eslint校驗(yàn)

    vue項(xiàng)目關(guān)閉eslint校驗(yàn)

    eslint是一個(gè)JavaScript的校驗(yàn)插件,通常用來(lái)校驗(yàn)語(yǔ)法或代碼的書(shū)寫風(fēng)格。這篇文章主要介紹了vue項(xiàng)目關(guān)閉eslint校驗(yàn),需要的朋友可以參考下
    2018-03-03
  • vue導(dǎo)入.md文件的步驟(markdown轉(zhuǎn)HTML)

    vue導(dǎo)入.md文件的步驟(markdown轉(zhuǎn)HTML)

    這篇文章主要介紹了vue導(dǎo)入.md文件的步驟(markdown轉(zhuǎn)HTML),幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下
    2020-12-12
  • 使用vue-cli搭建SPA項(xiàng)目的詳細(xì)過(guò)程

    使用vue-cli搭建SPA項(xiàng)目的詳細(xì)過(guò)程

    vue-cli是vue.js的腳手架,用于自動(dòng)生成vue.js+webpack的項(xiàng)目模板,本文通過(guò)實(shí)例代碼給大家介紹vue-cli搭建SPA項(xiàng)目的詳細(xì)過(guò)程,感興趣的朋友跟隨小編一起看看吧
    2022-09-09
  • Vue-cli項(xiàng)目部署到Nginx服務(wù)器的方法

    Vue-cli項(xiàng)目部署到Nginx服務(wù)器的方法

    這篇文章主要介紹了Vue-cli項(xiàng)目部署到Nginx服務(wù)器的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 深入理解Vue-cli4路由配置

    深入理解Vue-cli4路由配置

    Vue-router是Vue官方的路由插件,本文將結(jié)合實(shí)例代碼,介紹Vue-cli4路由配置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • ubuntu中利用nginx部署vue項(xiàng)目的完整步驟

    ubuntu中利用nginx部署vue項(xiàng)目的完整步驟

    Nginx是一款輕量級(jí)的Web服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器,在BSD-like 協(xié)議下發(fā)行,下面這篇文章主要給大家介紹了關(guān)于ubuntu中利用nginx部署vue項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • vue3實(shí)現(xiàn)無(wú)縫滾動(dòng)組件的示例代碼

    vue3實(shí)現(xiàn)無(wú)縫滾動(dòng)組件的示例代碼

    在日常開(kāi)發(fā)中,經(jīng)常遇到需要支持列表循環(huán)滾動(dòng)展示,特別是在數(shù)據(jù)化大屏開(kāi)發(fā)中,所以小編今天為大家介紹一下如何利用vue3實(shí)現(xiàn)一個(gè)無(wú)縫滾動(dòng)組件吧
    2023-09-09
  • TSX常見(jiàn)簡(jiǎn)單入門用法之Vue3+Vite

    TSX常見(jiàn)簡(jiǎn)單入門用法之Vue3+Vite

    Vue3的確可以直接使用tsx開(kāi)發(fā),唯一需要處理的就是children,而且處理起來(lái)還是比較不爽的,下面這篇文章主要給大家介紹了關(guān)于TSX常見(jiàn)簡(jiǎn)單入門用法之Vue3+Vite的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • Vue關(guān)閉當(dāng)前頁(yè)面的方法

    Vue關(guān)閉當(dāng)前頁(yè)面的方法

    Vue中關(guān)閉當(dāng)前頁(yè)面的方法與原生JavaScript類似,都是通過(guò)window對(duì)象的close方法實(shí)現(xiàn),這篇文章主要介紹了Vue關(guān)閉當(dāng)前頁(yè)面的方法,需要的朋友可以參考下
    2023-09-09
  • 深入理解vue-router之keep-alive

    深入理解vue-router之keep-alive

    本篇文章主要介紹了深入理解vue-router之keep-alive。keep-alive使被包含的組件保留狀態(tài),或避免重新渲染,有興趣的可以了解一下
    2017-08-08

最新評(píng)論