利用Vue.js实现拼图游戏
之前写过一篇《基于 Vue.js 的表格分页组件》的文章,主要介绍了 Vue 组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5516065.html
前言
为了进一步让大家了解 Vue.js 的神奇魅力,了解 Vue.js 的一种以数据为驱动的理念,本文主要利用 Vue 实现了一个数字拼图游戏,其原理并不是很复杂,效果图如下:
demo 展示地址为:https://luozhihao.github.io/vue-puzzle/index.html#!/
有能力的可以玩玩,拼出来有赏哦 ~~
功能分析
当然玩归玩,作为一名 Vue 爱好者,我们理应深入游戏内部,一探代码的实现。接下来我们就先来分析一下要完成这样的一个游戏,主要需要实现哪些功能。下面我就直接将此实例的功能点罗列在下了:
-
随机生成 1~15 的数字格子,每一个数字都必须出现且仅出现一次
-
点击一个数字方块后,如其上下左右有一处为空,则两者交换位置
-
格子每移动一步,我们都需要校验其是否闯关成功
-
点击重置游戏按钮后需对拼图进行重新排序
以上便是本实例的主要功能点,可见游戏功能并不复杂,我们只需一个个攻破就 OK 了,接下来我就来展示一下各个功能点的 Vue 代码。
构建游戏面板
作为一款以数据驱动的 JS 框架,Vue 的 HTML 模板很多时候都应该绑定数据的,比如此游戏的方块格子,我们这里肯定是不能写死的,代码如下:
<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 样式部分,大家可以先不用关心。以上代码我们将 1~15 的数字写死在了一个数组中,这显然不是随机排序的,那么我们就来实现随机排序的功能。
随机排序数字
<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: {</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 重置渲染</span>
render () {
let puzzleArr = [],
i = 1<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成包含1 ~ 15数字的数组</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (i; i < 16; i++<span style="color: rgba(0, 0, 0, 1)">) { puzzleArr.push(i) } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机打乱数组</span> puzzleArr = puzzleArr.sort(() =><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.random() - 0.5<span style="color: rgba(0, 0, 0, 1)"> }); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 页面显示</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles =<span style="color: rgba(0, 0, 0, 1)"> puzzleArr </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.push(''<span style="color: rgba(0, 0, 0, 1)">) }, }, ready () { </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.render() }
}
以上代码,我们利用 for 循环生成了一个 1~15 的有序数组,之后我们又利用原生 JS 的 sort 方法随机打乱数字,这里还包含了一个知识点就是 Math.random() 方法。
利用 sort() 方法进行自定义排序,我们需要提供一个比较函数,然后返回一个用于说明这两个值的相对顺序的数字,其返回值如下:
-
返回一个小于 0 的值,说明 a 小于 b
-
返回 0,说明 a 等于 b
-
返回一个大于 0 的值,说明 a 大于 b
这里利用 Math.random() 生成一个 0 ~ 1 之间的随机数,再减去 0.5,这样就会有一半概率返回一个小于 0 的值, 一半概率返回一个大于 0 的值,就保证了生成数组的随机性,实现了动态随机生成数字格子的功能。
需要注意的是,我们还在数组最后插了一个空字符串,用来生成唯一的空白格子。
交换方块位置
<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: {</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 重置渲染</span>
render () {
let puzzleArr = [],
i = 1<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成包含1 ~ 15数字的数组</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (i; i < 16; i++<span style="color: rgba(0, 0, 0, 1)">) { puzzleArr.push(i) } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机打乱数组</span> puzzleArr = puzzleArr.sort(() =><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.random() - 0.5<span style="color: rgba(0, 0, 0, 1)"> }); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 页面显示</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles =<span style="color: rgba(0, 0, 0, 1)"> puzzleArr </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.push(''<span style="color: rgba(0, 0, 0, 1)">) }, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击方块</span>
moveFn (index) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取点击位置及其上下左右的值</span> let curNum = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.puzzles[index], leftNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 1<span style="color: rgba(0, 0, 0, 1)">], rightNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 1<span style="color: rgba(0, 0, 0, 1)">], topNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 4<span style="color: rgba(0, 0, 0, 1)">], bottomNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 4<span style="color: rgba(0, 0, 0, 1)">] </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 和为空的位置交换数值</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (leftNum === '' && index <span class="pl-k">% <span class="pl-c1">4</span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (rightNum === '' && <span class="pl-c1">3 <span class="pl-k">!== index <span class="pl-k">% <span class="pl-c1">4</span></span></span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (topNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (bottomNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } } }, ready () { </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.render() }
}
</script>
-
这里我们首先在每个格子的 li 上添加了点击事件 @click="moveFn($index)",通过 $index 参数获取点击方块在数组中的位置
-
其次获取其上下左右的数字在数组中的 index 值依次为 index - 4、index + 4、index - 1、index + 1
-
当我们找到上下左右有一处为空的时候我们将空的位置赋值上当前点击格子的数字,将当前点击的位置置为空
备注:我们为什么要使用 $set 方法,而不直接用等号赋值呢,这里包含了 Vue 响应式原理的知识点。
// 因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化:// 1. 直接用索引设置元素,如 vm.items[0] = {};
// 2. 修改数据的长度,如 vm.items.length = 0。
// 为了解决问题 (1),Vue.js 扩展了观察数组,为它添加了一个 $set() 方法:// 与
example1.items[0] = ...
相同,但是能触发视图更新
example1.items.$set(0, { childMsg: 'Changed!'})
详见:http://cn.vuejs.org/guide/list.html# 问题
检测是否闯关成功
<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: {</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 重置渲染</span>
render () {
let puzzleArr = [],
i = 1<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成包含1 ~ 15数字的数组</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (i; i < 16; i++<span style="color: rgba(0, 0, 0, 1)">) { puzzleArr.push(i) } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机打乱数组</span> puzzleArr = puzzleArr.sort(() =><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.random() - 0.5<span style="color: rgba(0, 0, 0, 1)"> }); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 页面显示</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles =<span style="color: rgba(0, 0, 0, 1)"> puzzleArr </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.push(''<span style="color: rgba(0, 0, 0, 1)">) }, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击方块</span>
moveFn (index) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取点击位置及其上下左右的值</span> let curNum = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.puzzles[index], leftNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 1<span style="color: rgba(0, 0, 0, 1)">], rightNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 1<span style="color: rgba(0, 0, 0, 1)">], topNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 4<span style="color: rgba(0, 0, 0, 1)">], bottomNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 4<span style="color: rgba(0, 0, 0, 1)">] </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 和为空的位置交换数值</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (leftNum === '' && index <span class="pl-k">% <span class="pl-c1">4</span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (rightNum === '' && <span class="pl-c1">3 <span class="pl-k">!== index <span class="pl-k">% <span class="pl-c1">4</span></span></span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (topNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (bottomNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.passFn() }, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 校验是否过关</span>
passFn () {
if (this.puzzles[15] === '') {
const newPuzzles = this.puzzles.slice(0, 15)const isPass </span>= newPuzzles.every((e, i) => e === i + 1<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isPass) { alert (</span>'恭喜,闯关成功!'<span style="color: rgba(0, 0, 0, 1)">) } } } }, ready () { </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.render() }
}
</script>
我们在 moveFn 方法里调用了 passFn 方法来进行检测,而 passFn 方法里又涉及了两个知识点:
(1)slice 方法
通过slice方法我们截取数组的前15个元素生成一个新的数组,当然前提是数组随后一个元素为空
(2)every 方法
通过every方法我们来循环截取后数组的每一个元素是否等于其index+1值,如果全部等于则返回true,只要有一个不等于则返回false
如果闯关成功那么 isPass 的值为 true,就会 alert "恭喜,闯关成功!" 提示窗,如果没有则不提示。
重置游戏
重置游戏其实很简单,只需添加重置按钮并在其上调用 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: {</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 重置渲染</span>
render () {
let puzzleArr = [],
i = 1<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成包含1 ~ 15数字的数组</span> <span style="color: rgba(0, 0, 255, 1)">for</span> (i; i < 16; i++<span style="color: rgba(0, 0, 0, 1)">) { puzzleArr.push(i) } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机打乱数组</span> puzzleArr = puzzleArr.sort(() =><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.random() - 0.5<span style="color: rgba(0, 0, 0, 1)"> }); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 页面显示</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles =<span style="color: rgba(0, 0, 0, 1)"> puzzleArr </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.push(''<span style="color: rgba(0, 0, 0, 1)">) }, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击方块</span>
moveFn (index) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取点击位置及其上下左右的值</span> let curNum = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.puzzles[index], leftNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 1<span style="color: rgba(0, 0, 0, 1)">], rightNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 1<span style="color: rgba(0, 0, 0, 1)">], topNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index - 4<span style="color: rgba(0, 0, 0, 1)">], bottomNum </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles[index + 4<span style="color: rgba(0, 0, 0, 1)">] </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 和为空的位置交换数值</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (leftNum === '' && index <span class="pl-k">% <span class="pl-c1">4</span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (rightNum === '' && <span class="pl-c1">3 <span class="pl-k">!== index <span class="pl-k">% <span class="pl-c1">4</span></span></span></span><span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 1<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (topNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index - 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (bottomNum === ''<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index + 4<span style="color: rgba(0, 0, 0, 1)">, curNum) </span><span style="color: rgba(0, 0, 255, 1)">this</span>.puzzles.$set(index, ''<span style="color: rgba(0, 0, 0, 1)">) } </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.passFn() }, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 校验是否过关</span>
passFn () {
if (this.puzzles[15] === '') {
const newPuzzles = this.puzzles.slice(0, 15)const isPass </span>= newPuzzles.every((e, i) => e === i + 1<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isPass) { alert (</span>'恭喜,闯关成功!'<span style="color: rgba(0, 0, 0, 1)">) } } } }, ready () { </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.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 代码。
总结
其实本游戏的代码量不多,功能点也不是很复杂,不过通过 Vue 来写这样的游戏,有助于我们了解 Vue 以数据驱动的响应式原理,在简化代码量的同时也增加了代码的可读性。
本实例的所有源码我已经上传至我的 github,地址为https://github.com/luozhihao/vue-puzzle 需要的童鞋可以自行下载运行。