Vue.js Realization Puzzle Game
Previously wrote a "vue.js-based table pagination component" article, mainly introduced the Vue component writing method, interested can visit here to read: http://www.cnblogs.com/luozhihao/p/5516065.html
Objective
In order to further let everyone understand the magical charm of vue.js, understand the vue.js of a data-driven concept, the main use of Vue to achieve a digital puzzle game, the principle is not very complex, as follows:
Demo Display Address: https://luozhihao.github.io/vue-puzzle/index.html#!/
Have the ability to play, spell out a reward Oh ~ ~
Functional analysis
Of course, as a Vue enthusiast, we should go inside the game and explore the implementation of the Code. Let's start with an analysis of what is needed to accomplish a game like this. I will directly list the function points of this instance below:
Randomly generate 1~15 digital lattices, each number must appear and appear only once
After clicking on a number block, as if there is an empty space around it, the two exchange positions
We need to verify that the grid is successful in every step of the move.
Re-order puzzles after clicking the Reset Game button
The above is the main function point of this example, it can be seen that the game function is not complex, we just have to break down the OK, then I will show the various function points of the Vue code.
Build a game panel
As a data-driven JS framework, Vue's HTML template often should be bound to the data, than such a game of square lattice, we must not write dead here, the code is as follows:
<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, ten, one, one, and above, +] } }}</script>
Here I omitted the CSS style section, we can not care about first. The above code we have 1~15 the number of dead in an array, which is obviously not random ordering, then we have to implement the function of random sorting.
Randomly sort numbers
<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: { //reset render render () {let Puzzlearr = [], i = 1 //Generate an array with 1 ~ 15 digits fo R (i; i < i++) { Puzzlearr.push (i) } //random scrambling array Puzzlearr = Puzzlearr.sort (() + = { Retu RN Math.random ()-0.5 }); Page display this.puzzles = Puzzlearr this.puzzles.push (") }, }, Ready () { this.render () }}
The above code, we use the For loop to generate an ordered array of 1~15, and then we use the native JS sort method to randomly disrupt the numbers, here also contains a knowledge point is the Math.random () method.
Using the sort () method for custom sorting, we need to provide a comparison function and then return a number that describes the relative order of the two values, with the following return values:
Returns a value less than 0 that indicates a is less than B
Returns 0, indicating a equals b
Returns a value greater than 0 that indicates a is greater than B
Here, we use Math.random () to generate a random number between 0 ~ 1, minus 0.5, so that half of the probability returns a value less than 0, half the probability returns a value greater than 0, which guarantees the randomness of the generated array, and realizes the function of dynamically randomly generating the digital lattice.
Note that we are also inserting an empty string at the end of the array to generate a unique blank lattice.
Swap block position
<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><SCRI Pt>export default {data () {return {puzzles: []}}, methods: {//Reset Render Render () {Let Puzzlearr = [], i = 1//Generate an array containing 1 ~ 15 numbers for (i; I < ; 16; i++) {Puzzlearr.push (i)}//random scrambling array Puzzlearr = Puzzlearr.sort (() + = { Return Math.random ()-0.5}); Page display this.puzzles = Puzzlearr this.puzzles.push (")},//click on Block Movefn (index {//Get the click position and the value up or down 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]//and empty position exchange values 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> ;
Here we first add the Click event @click= "Movefn ($index)" on each lattice Li, and get the position of the clicked Block in the array by $index parameter.
Second, the index value of the number in the array is index-4, index + 4, index-1, index + 1, and so on.
When we find an empty space around the top and bottom, we assign the empty position to the number of the currently clicked Grid, and place the current clicked position empty
Note: Why should we use the $set method instead of assigning a value directly to the equals sign, which contains the knowledge points of the Vue response principle.
Because of JavaScript limitations, Vue.js cannot detect the following array changes://1. Set elements directly with an index, such as vm.items[0] = {};//2. Modify the length of the data, such as Vm.items.length = 0. To solve the problem (1), Vue.js expands the observation array, adding a $set () method to it://Same as ' example1.items[0 ' = ... ' but can trigger the view update example1.items. $set (0, {CHILDMS G: ' changed! '})
See: http://cn.vuejs.org/guide/list.html# Questions
Detect if the barrier is successful
<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><SCRI Pt>export default {data () {return {puzzles: []}}, methods: {//Reset Render Render () {Let Puzzlearr = [], i = 1//Generate an array containing 1 ~ 15 numbers for (i; I < ; 16; i++) {Puzzlearr.push (i)}//random scrambling array Puzzlearr = Puzzlearr.sort (() + = { Return Math.random ()-0.5}); Page display this.puzzles = Puzzlearr this.puzzles.push (")},//click on Block Movefn (index {//Get the click position and the value up or down 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]//and empty position exchange values 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 ()},//Check for clearance PASSFN () {if (this.puzzles[15] = = = ") {Const Newpuzzles = This.puzzles.slice (0, +) con St Ispass = NEWPUZZLES.EVery ((e, i) = = = = i + 1) if (ispass) {alert (' Congratulations, success! ')}}}, Ready () {This.render ()}}</script>
We call the Passfn method in the Movefn method for detection, and the PASSFN method involves two points of knowledge:
(1) Slice method
通过slice方法我们截取数组的前15个元素生成一个新的数组,当然前提了数组随后一个元素为空
(2) Every method
通过every方法我们来循环截取后数组的每一个元素是否等于其index+1值,如果全部等于则返回true,只要有一个不等于则返回false
If the threshold is successful then the value of Ispass is true and the alert "Congratulations, success!" The prompt is not prompted if it is not.
Reset Game
Resetting the game is really simple, just add the reset button and call the Render method on it:
<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 "> Reset Games </button> </div></template><script>export Default {data () {return {puzzles: []}}, methods: {//Reset render render () {Let Puzzlearr = [], i = 1//Generate an array containing 1 ~ 15 numbers for (i; i < i++) { Puzzlearr.push (i)}//random scrambling array Puzzlearr = Puzzlearr.sort (() + = { Return Math.random ()-0.5}); The page shows this.puzzles = Puzzlearr This.puzzles.push (")}, Click on the Block Movefn (index) {//Get the click position and its upper and lower values let Curnum = This.puzzles[index], Leftnum = This.puzzles[index-1], Rightnum = This.puzzles[index + 1], Topnum = This.puzzle S[index-4], Bottomnum = This.puzzles[index + 4]//and NULL position Exchange value if (leftnum = = =) { This.puzzles. $set (index-1, Curnum) this.puzzles. $set (Index, ')} else if (rig Htnum = = = ") {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.puzzl Es. $set (Index, ')} THIS.PASSFN ()},//Check whether PASSFN () {if (this . puzzles[15] = = = ") { Const Newpuzzles = This.puzzles.slice (0, +) const ISPASS = Newpuzzles.every ((e, i) = = = = i + 1) if (ispass) {alert (' Congratulations, success! ')}}}, Ready () {This.render ()}}</script><style> @impor T 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>
Here I have added CSS code.
Summarize
In fact, the game code is not much, the function point is not very complex, but through Vue to write such a game, help us understand VUE data-driven response principle, in simplifying the amount of code while also increasing the readability of the code.
All the source code of this example I have uploaded to my github, the address for Https://github.com/luozhihao/vue-puzzle need for children's shoes can be downloaded and run on their own.
Original articles, reproduced please note from a radish a pit-blog Park [Http://www.cnblogs.com/luozhihao]
This address: http://www.cnblogs.com/luozhihao/p/5726661.html
This article was posted synchronously at: 1190000006137236
Vue.js Realization Puzzle Game