最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue.js實(shí)現(xiàn)數(shù)字拼圖游戲

 更新時間:2016年08月02日 09:01:30   投稿:hebedich  
為了進(jìn)一步讓大家了解Vue.js的神奇魅力,了解Vue.js的一種以數(shù)據(jù)為驅(qū)動的理念,本文主要利用Vue實(shí)現(xiàn)了一個數(shù)字拼圖游戲,其原理并不是很復(fù)雜,下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)。

先來看看效果圖:

功能分析

當(dāng)然玩歸玩,作為一名Vue愛好者,我們理應(yīng)深入游戲內(nèi)部,一探代碼的實(shí)現(xiàn)。接下來我們就先來分析一下要完成這樣的一個游戲,主要需要實(shí)現(xiàn)哪些功能。下面我就直接將此實(shí)例的功能點(diǎn)羅列在下了:

    1.隨機(jī)生成1~15的數(shù)字格子,每一個數(shù)字都必須出現(xiàn)且僅出現(xiàn)一次

    2.點(diǎn)擊一個數(shù)字方塊后,如其上下左右有一處為空,則兩者交換位置

    3.格子每移動一步,我們都需要校驗其是否闖關(guān)成功

    4.點(diǎn)擊重置游戲按鈕后需對拼圖進(jìn)行重新排序

以上便是本實(shí)例的主要功能點(diǎn),可見游戲功能并不復(fù)雜,我們只需一個個攻破就OK了,接下來我就來展示一下各個功能點(diǎn)的Vue代碼。

構(gòu)建游戲面板

作為一款以數(shù)據(jù)驅(qū)動的JS框架,Vue的HTML模板很多時候都應(yīng)該綁定數(shù)據(jù)的,比如此游戲的方塊格子,我們這里肯定是不能寫死的,代碼如下:

<template>
  <div class="box">
    <ul class="puzzle-wrap">
      <li 
        :class="{'puzzle': true, 'puzzle-empty': !puzzle}" 
        v-for="puzzle in puzzles" 
        v-text="puzzle"
      ></li>
    </ul>
  </div>
</template>

<script>
export default {
  data () {
    return {
      puzzles: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    }
  }
}
</script>

這里我省略了css樣式部分,大家可以先不用關(guān)心。以上代碼我們將1~15的數(shù)字寫死在了一個數(shù)組中,這顯然不是隨機(jī)排序的,那么我們就來實(shí)現(xiàn)隨機(jī)排序的功能。

隨機(jī)排序數(shù)字

<template>
  <div class="box">
    <ul class="puzzle-wrap">
      <li 
        :class="{'puzzle': true, 'puzzle-empty': !puzzle}" 
        v-for="puzzle in puzzles" 
        v-text="puzzle"
      ></li>
    </ul>
  </div>
</template>

<script>
export default {
  data () {
    return {
      puzzles: []
    }
  },
  methods: {

    // 重置渲染
    render () {
      let puzzleArr = [],
        i = 1

      // 生成包含1 ~ 15數(shù)字的數(shù)組
      for (i; i < 16; i++) {
        puzzleArr.push(i)
      }

      // 隨機(jī)打亂數(shù)組
      puzzleArr = puzzleArr.sort(() => {
        return Math.random() - 0.5
      });

      // 頁面顯示
      this.puzzles = puzzleArr
      this.puzzles.push('')
    },
  },
  ready () {
    this.render()
  }
}

以上代碼,我們利用for循環(huán)生成了一個1~15的有序數(shù)組,之后我們又利用原生JS的sort方法隨機(jī)打亂數(shù)字,這里還包含了一個知識點(diǎn)就是Math.random()方法。

利用sort()方法進(jìn)行自定義排序,我們需要提供一個比較函數(shù),然后返回一個用于說明這兩個值的相對順序的數(shù)字,其返回值如下:

    1.返回一個小于 0 的值,說明 a 小于 b

    2.返回 0,說明 a 等于 b

    3.返回一個大于 0 的值,說明 a 大于 b

這里利用Math.random()生成一個 0 ~ 1 之間的隨機(jī)數(shù),再減去0.5,這樣就會有一半概率返回一個小于 0 的值, 一半概率返回一個大于 0 的值,就保證了生成數(shù)組的隨機(jī)性,實(shí)現(xiàn)了動態(tài)隨機(jī)生成數(shù)字格子的功能。

需要注意的是,我們還在數(shù)組最后插了一個空字符串,用來生成唯一的空白格子。

交換方塊位置

<template>
  <div class="box">
    <ul class="puzzle-wrap">
      <li 
        :class="{'puzzle': true, 'puzzle-empty': !puzzle}" 
        v-for="puzzle in puzzles" 
        v-text="puzzle"
        @click="moveFn($index)"
      ></li>
    </ul>
  </div>
</template>

<script>
export default {
  data () {
    return {
      puzzles: []
    }
  },
  methods: {

    // 重置渲染
    render () {
      let puzzleArr = [],
        i = 1

      // 生成包含1 ~ 15數(shù)字的數(shù)組
      for (i; i < 16; i++) {
        puzzleArr.push(i)
      }

      // 隨機(jī)打亂數(shù)組
      puzzleArr = puzzleArr.sort(() => {
        return Math.random() - 0.5
      });

      // 頁面顯示
      this.puzzles = puzzleArr
      this.puzzles.push('')
    },

    // 點(diǎn)擊方塊
    moveFn (index) {

      // 獲取點(diǎn)擊位置及其上下左右的值
      let curNum = this.puzzles[index],
        leftNum = this.puzzles[index - 1],
        rightNum = this.puzzles[index + 1],
        topNum = this.puzzles[index - 4],
        bottomNum = this.puzzles[index + 4]

      // 和為空的位置交換數(shù)值
      if (leftNum === '') {
        this.puzzles.$set(index - 1, curNum)
        this.puzzles.$set(index, '')
      } else if (rightNum === '') {
        this.puzzles.$set(index + 1, curNum)
        this.puzzles.$set(index, '')
      } else if (topNum === '') {
        this.puzzles.$set(index - 4, curNum)
        this.puzzles.$set(index, '')
      } else if (bottomNum === '') {
        this.puzzles.$set(index + 4, curNum)
        this.puzzles.$set(index, '')
      }
    }
  },
  ready () {
    this.render()
  }
}
</script>

    1.這里我們首先在每個格子的li上添加了點(diǎn)擊事件@click="moveFn($index)",通過$index參數(shù)獲取點(diǎn)擊方塊在數(shù)組中的位置

    2.其次獲取其上下左右的數(shù)字在數(shù)組中的index值依次為index - 4、index + 4、index - 1、index + 1

    3.當(dāng)我們找到上下左右有一處為空的時候我們將空的位置賦值上當(dāng)前點(diǎn)擊格子的數(shù)字,將當(dāng)前點(diǎn)擊的位置置為空

備注:我們?yōu)槭裁匆褂?set方法,而不直接用等號賦值呢,這里包含了Vue響應(yīng)式原理的知識點(diǎn)。

// 因為 JavaScript 的限制,Vue.js 不能檢測到下面數(shù)組變化:

// 1.直接用索引設(shè)置元素,如 vm.items[0] = {};
// 2.修改數(shù)據(jù)的長度,如 vm.items.length = 0。
// 為了解決問題 (1),Vue.js 擴(kuò)展了觀察數(shù)組,為它添加了一個 $set() 方法:

// 與 `example1.items[0] = ...` 相同,但是能觸發(fā)視圖更新
example1.items.$set(0, { childMsg: 'Changed!'})

檢測是否闖關(guān)成功

<template>
  <div class="box">
    <ul class="puzzle-wrap">
      <li 
        :class="{'puzzle': true, 'puzzle-empty': !puzzle}" 
        v-for="puzzle in puzzles" 
        v-text="puzzle"
        @click="moveFn($index)"
      ></li>
    </ul>
  </div>
</template>

<script>
export default {
  data () {
    return {
      puzzles: []
    }
  },
  methods: {

    // 重置渲染
    render () {
      let puzzleArr = [],
        i = 1

      // 生成包含1 ~ 15數(shù)字的數(shù)組
      for (i; i < 16; i++) {
        puzzleArr.push(i)
      }

      // 隨機(jī)打亂數(shù)組
      puzzleArr = puzzleArr.sort(() => {
        return Math.random() - 0.5
      });

      // 頁面顯示
      this.puzzles = puzzleArr
      this.puzzles.push('')
    },

    // 點(diǎn)擊方塊
    moveFn (index) {

      // 獲取點(diǎn)擊位置及其上下左右的值
      let curNum = this.puzzles[index],
        leftNum = this.puzzles[index - 1],
        rightNum = this.puzzles[index + 1],
        topNum = this.puzzles[index - 4],
        bottomNum = this.puzzles[index + 4]

      // 和為空的位置交換數(shù)值
      if (leftNum === '') {
        this.puzzles.$set(index - 1, curNum)
        this.puzzles.$set(index, '')
      } else if (rightNum === '') {
        this.puzzles.$set(index + 1, curNum)
        this.puzzles.$set(index, '')
      } else if (topNum === '') {
        this.puzzles.$set(index - 4, curNum)
        this.puzzles.$set(index, '')
      } else if (bottomNum === '') {
        this.puzzles.$set(index + 4, curNum)
        this.puzzles.$set(index, '')
      }

      this.passFn()
    },

    // 校驗是否過關(guān)
    passFn () {
      if (this.puzzles[15] === '') {
        const newPuzzles = this.puzzles.slice(0, 15)

        const isPass = newPuzzles.every((e, i) => e === i + 1)

        if (isPass) {
          alert ('恭喜,闖關(guān)成功!')
        }
      }
    }
  },
  ready () {
    this.render()
  }
}
</script>

我們在moveFn方法里調(diào)用了passFn方法來進(jìn)行檢測,而passFn方法里又涉及了兩個知識點(diǎn):

(1)slice方法

通過slice方法我們截取數(shù)組的前15個元素生成一個新的數(shù)組,當(dāng)然前提了數(shù)組隨后一個元素為空

(2)every方法

通過every方法我們來循環(huán)截取后數(shù)組的每一個元素是否等于其index+1值,如果全部等于則返回true,只要有一個不等于則返回false

如果闖關(guān)成功那么isPass的值為true,就會alert "恭喜,闖關(guān)成功!"提示窗,如果沒有則不提示。

重置游戲

重置游戲其實(shí)很簡單,只需添加重置按鈕并在其上調(diào)用render方法就行了:

<template>
  <div class="box">
    <ul class="puzzle-wrap">
      <li 
        :class="{'puzzle': true, 'puzzle-empty': !puzzle}" 
        v-for="puzzle in puzzles" 
        v-text="puzzle"
        @click="moveFn($index)"
      ></li>
    </ul>
    <button class="btn btn-warning btn-block btn-reset" @click="render">重置游戲</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      puzzles: []
    }
  },
  methods: {

    // 重置渲染
    render () {
      let puzzleArr = [],
        i = 1

      // 生成包含1 ~ 15數(shù)字的數(shù)組
      for (i; i < 16; i++) {
        puzzleArr.push(i)
      }

      // 隨機(jī)打亂數(shù)組
      puzzleArr = puzzleArr.sort(() => {
        return Math.random() - 0.5
      });

      // 頁面顯示
      this.puzzles = puzzleArr
      this.puzzles.push('')
    },

    // 點(diǎn)擊方塊
    moveFn (index) {

      // 獲取點(diǎn)擊位置及其上下左右的值
      let curNum = this.puzzles[index],
        leftNum = this.puzzles[index - 1],
        rightNum = this.puzzles[index + 1],
        topNum = this.puzzles[index - 4],
        bottomNum = this.puzzles[index + 4]

      // 和為空的位置交換數(shù)值
      if (leftNum === '') {
        this.puzzles.$set(index - 1, curNum)
        this.puzzles.$set(index, '')
      } else if (rightNum === '') {
        this.puzzles.$set(index + 1, curNum)
        this.puzzles.$set(index, '')
      } else if (topNum === '') {
        this.puzzles.$set(index - 4, curNum)
        this.puzzles.$set(index, '')
      } else if (bottomNum === '') {
        this.puzzles.$set(index + 4, curNum)
        this.puzzles.$set(index, '')
      }

      this.passFn()
    },

    // 校驗是否過關(guān)
    passFn () {
      if (this.puzzles[15] === '') {
        const newPuzzles = this.puzzles.slice(0, 15)

        const isPass = newPuzzles.every((e, i) => e === i + 1)

        if (isPass) {
          alert ('恭喜,闖關(guān)成功!')
        }
      }
    }
  },
  ready () {
    this.render()
  }
}
</script>

<style>
@import url('./assets/css/bootstrap.min.css');

body {
  font-family: Arial, "Microsoft YaHei"; 
}

.box {
  width: 400px;
  margin: 50px auto 0;
}

.puzzle-wrap {
  width: 400px;
  height: 400px;
  margin-bottom: 40px;
  padding: 0;
  background: #ccc;
  list-style: none;
}

.puzzle {
  float: left;
  width: 100px;
  height: 100px;
  font-size: 20px;
  background: #f90;
  text-align: center;
  line-height: 100px;
  border: 1px solid #ccc;
  box-shadow: 1px 1px 4px;
  text-shadow: 1px 1px 1px #B9B4B4;
  cursor: pointer;
}

.puzzle-empty {
  background: #ccc;
  box-shadow: inset 2px 2px 18px;
}

.btn-reset {
  box-shadow: inset 2px 2px 18px;
}
</style>

這里我一并加上了css代碼。

總結(jié)

以上就是本文的全部內(nèi)容,其實(shí)本游戲的代碼量不多,功能點(diǎn)也不是很復(fù)雜,不過通過Vue來寫這樣的游戲,有助于我們了解Vue以數(shù)據(jù)驅(qū)動的響應(yīng)式原理,在簡化代碼量的同時也增加了代碼的可讀性。希望本文對大家學(xué)些Vue有所幫助。

相關(guān)文章

  • vue如何預(yù)覽后端傳來的二進(jìn)制圖片

    vue如何預(yù)覽后端傳來的二進(jìn)制圖片

    這篇文章主要介紹了vue如何預(yù)覽后端傳來的二進(jìn)制圖片,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Vue動態(tài)實(shí)現(xiàn)評分效果

    Vue動態(tài)實(shí)現(xiàn)評分效果

    這篇文章主要為大家詳細(xì)介紹了Vue動態(tài)實(shí)現(xiàn)評分效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • vuepress打包之后頁面樣式丟失問題的兩種解決方式

    vuepress打包之后頁面樣式丟失問題的兩種解決方式

    這篇文章主要介紹了vuepress打包之后頁面樣式丟失問題的兩種解決方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 如何使用yarn創(chuàng)建vite+vue3&&electron多端運(yùn)行

    如何使用yarn創(chuàng)建vite+vue3&&electron多端運(yùn)行

    這篇文章主要介紹了如何使用yarn創(chuàng)建vite+vue3&&electron多端運(yùn)行,本文分步驟給大家介紹的非常詳細(xì),包括使用yarn創(chuàng)建vite+vue3項目會遇到哪些問題,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • 解決vue v-for 遍歷循環(huán)時key值報錯的問題

    解決vue v-for 遍歷循環(huán)時key值報錯的問題

    今天小編就為大家分享一篇解決vue v-for 遍歷循環(huán)時key值報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue extend使用示例深入分析

    Vue extend使用示例深入分析

    這篇文章主要介紹了Vue.extend使用示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Vue之Watcher源碼解析(1)

    Vue之Watcher源碼解析(1)

    這篇文章主要為大家詳細(xì)介紹了Vue源碼之Watcher的基礎(chǔ)知識,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 一起來做一下Vue全局提示組件

    一起來做一下Vue全局提示組件

    前端開發(fā)的時候,在項目中引入組件以及使用是非常常見操作,下面這篇文章主要給大家介紹了關(guān)于Vue全局提示組件的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Vue組件通信中非父子組件傳值知識點(diǎn)總結(jié)

    Vue組件通信中非父子組件傳值知識點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于Vue組件通信中非父子組件傳值知識點(diǎn)總結(jié),有興趣的朋友們學(xué)習(xí)下。
    2019-12-12
  • 詳解使用mpvue開發(fā)github小程序總結(jié)

    詳解使用mpvue開發(fā)github小程序總結(jié)

    這篇文章主要介紹了詳解使用mpvue開發(fā)github小程序總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07

最新評論

兴仁县| 大同市| 禄丰县| 安新县| 灌南县| 尤溪县| 平原县| 江孜县| 田阳县| 合阳县| 镇宁| 鹤庆县| 百色市| 加查县| 尉氏县| 封开县| 金沙县| 龙游县| 杭州市| 阿克苏市| 措勤县| 柘荣县| 布尔津县| 来凤县| 宁安市| 清镇市| 邳州市| 博乐市| 望谟县| 富川| 青铜峡市| 荔波县| 大名县| 泰宁县| 小金县| 迁安市| 长泰县| 增城市| 沈阳市| 宜都市| 伊宁市|