基于Vue.js实现数字拼图游戏
先来看看效果图
功能分析
玩归玩,作为一名Vue爱好者,我们理应深入游戏内部,一探代码的实现。接下来我们就先来分析一下要完成这样的一个游戏,主要需要实现哪些功能。狼蚁网站SEO优化我就直接将此实例的功能点罗列在下了
1.随机生成1~15的数字格子,每一个数字都必须出现且仅出现一次
2.点击一个数字方块后,如其上下左右有一处为空,则两者交换位置
3.格子每移动一步,我们都需要校验其是否闯关成功
4.点击重置游戏按钮后需对拼图进行重新排序
以上便是本实例的主要功能点,可见游戏功能并不复杂,我们只需一个个攻破就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: { // 重置渲染 render () { let puzzleArr = [], i = 1 // 生成包含1 ~ 15数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, }, ready () { this.render() } }
以上代码,我们利用for循环生成了一个1~15的有序数组,之后我们又利用原生JS的sort方法随机打乱数字,这里还包含了一个知识点就是Math.random()
方法。
利用sort()
方法进行自定义排序,我们需要提供一个比较函数,然后返回一个用于说明这两个值的相对顺序的数字,其返回值如下
1.返回一个小于 0 的值,说明 a 小于 b
2.返回 0,说明 a 等于 b
3.返回一个大于 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: { // 重置渲染 render () { let puzzleArr = [], i = 1 // 生成包含1 ~ 15数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, // 点击方块 moveFn (index) { // 获取点击位置及其上下左右的值 let curNum = this.puzzles[index], leftNum = this.puzzles[index - 1], rightNum = this.puzzles[index + 1], Num = this.puzzles[index - 4], bottomNum = this.puzzles[index + 4] // 和为空的位置交换数值 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 (Num === '') { 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上添加了点击事件@click="moveFn($index)",通过$index参数获取点击方块在数组中的位置
2.获取其上下左右的数字在数组中的index值依次为index - 4、index + 4、index - 1、index + 1
3.当我们找到上下左右有一处为空的时候我们将空的位置赋值上当前点击格子的数字,将当前点击的位置置为空
备注我们为什么要使用$set方法,而不直接用等号赋值呢,这里包含了Vue响应式原理的知识点。
// 因为 JavaScript 的限制,Vue.js 不能检测到狼蚁网站SEO优化数组变化 // 1.直接用索引设置元素,如 vm.items[0] = {}; // 2.修改数据的长度,如 vm.items.length = 0。 // 为了解决问题 (1),Vue.js 扩展了观察数组,为它添加了一个 $set() 方法 // 与 `example1.items[0] = ...` 相同,能触发视图更新 example1.items.$set(0, { childMsg: 'Changed!'})
检测是否闯关成功
<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数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, // 点击方块 moveFn (index) { // 获取点击位置及其上下左右的值 let curNum = this.puzzles[index], leftNum = this.puzzles[index - 1], rightNum = this.puzzles[index + 1], Num = this.puzzles[index - 4], bottomNum = this.puzzles[index + 4] // 和为空的位置交换数值 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 (Num === '') { 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() }, // 校验是否过关 passFn () { if (this.puzzles[15] === '') { const newPuzzles = this.puzzles.slice(0, 15) const isPass = newPuzzles.every((e, i) => e === i + 1) if (isPass) { alert ('恭喜,闯关成功!') } } } }, ready () { this.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: { // 重置渲染 render () { let puzzleArr = [], i = 1 // 生成包含1 ~ 15数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, // 点击方块 moveFn (index) { // 获取点击位置及其上下左右的值 let curNum = this.puzzles[index], leftNum = this.puzzles[index - 1], rightNum = this.puzzles[index + 1], Num = this.puzzles[index - 4], bottomNum = this.puzzles[index + 4] // 和为空的位置交换数值 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 (Num === '') { 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() }, // 校验是否过关 passFn () { if (this.puzzles[15] === '') { const newPuzzles = this.puzzles.slice(0, 15) const isPass = newPuzzles.every((e, i) => e === i + 1) if (isPass) { alert ('恭喜,闯关成功!') } } } }, 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: #c; list-style: none; } .puzzle { float: left; width: 100px; height: 100px; font-size: 20px; background: #f90; text-align: center; line-height: 100px; border: 1px solid #c; box-shadow: 1px 1px 4px; text-shadow: 1px 1px 1px #B9B4B4; cursor: pointer; } .puzzle-empty { background: #c; box-shadow: inset 2px 2px 18px; } .btn-reset { box-shadow: inset 2px 2px 18px; } </style>
这里我一并加上了css代码。
以上就是本文的全部内容,其实本游戏的代码量不多,功能点也不是很复杂,不过通过Vue来写这样的游戏,有助于我们了解Vue以数据驱动的响应式原理,在简化代码量的也增加了代码的可读性。希望本文对大家学些Vue有所帮助。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程