仍是用的vue,原本覺得不合適,但想法錯了。貪吃蛇並非經過操做dom來完成移動的,而是經過記錄貪吃蛇的路徑來將身體渲染出來。css
通常移動元素,咱們都是變更它的css達到目的,但我在寫貪吃蛇的時候發現這樣很難以實現,參考了網上的資源,發現大部分人是經過記錄貪吃蛇的路徑,保存進數組,經過數組變更來表示貪吃蛇的下一步,主要是增長頭部位置,去除尾部位置,再動態添加css樣式,這樣就達到移動的效果。html
連接描述vue
<div id="snake"> <table> <tr v-for="(col,y) in cols"><td v-for="(row,x) in rows" :class="body(x,y)||showfood(x,y)?'active':''"></td></tr> </table> <button @click="start()">開始</button> </div> data(){ return{ rows:'',//橫框 cols:'',//豎框 position:[[0,0],[1,0],[2,0],[3,0]],//蛇的初始位置 direction:1,//方向 food:[]//食物的位置 } },
methods:{ background(){//生成橫框和豎框的函數 this.rows=Array(30) this.cols=Array(30) }, keyboard(){//鍵盤事件 let _this = this; document.onkeydown = function(e){ if(e.keyCode===37){ _this.change(-1) }else if(e.keyCode===38){ _this.change(-2) }else if(e.keyCode===39){ _this.change(1) }else{ _this.change(2) } } }, creatfood(){//創造食物 this.food[0]=Math.floor(Math.random()*30) this.food[1]=Math.floor(Math.random()*30) }, showfood(x,y){//顯示食物 if(this.food[0]===x&&this.food[1]===y){ return true } }, body(x,y){//顯示身體 for(i=0;i<this.position.length;i++){//循環身體函數,利用索引和身體位置作畢竟,若是索引和身體數組重合就會添加active樣式 if(this.position[i][0]===x&&this.position[i][1]===y){ return true } } },
前期準備就是這麼多,接下來就是跑起來,先聲明一個計時器git
let timer=''
接着就用定時器開始跑github
start(){//開始按鈕 timer=setInterval(()=>this.autorun(),300) }
這裏的autorun就是咱們要寫的跑動函數數組
autorun(){ let direction=this.direction//目前方向 let headX,headY// headX=this.position[this.position.length-1][0]//複製蛇頭的X座標 headY=this.position[this.position.length-1][1]//複製蛇頭的Y座標 if(direction===1||direction===-1){//若是方向是在左右跑動 direction>0?headX++:headX--//往右跑X座標+1,往左跑X座標-1 }else{ direction>0?headY++:headY--//若是方向是在上下跑動,Y座標作對應處理 } //此時蛇頭的下一個座標位置就是[headX,headY],接下來就能夠判斷是否結束遊戲,若是結束了,蛇頭就不必添加了 if(headX<0||headX>29||headY<0||headY>29||this.body(headX,headY)){//當蛇頭下一個位置出了邊界或者這個位置是符合身體函數(即蛇頭撞上了身體) alert('Game Over')//結束 clearInterval(timer)//清除定時器 this.position=[[0,0],[1,0],[2,0],[3,0]]//還原身體 this.creatfood()//從新創造食物 this.direction=1//還原方向 }else{//若是蛇頭下一個位置是符合規則的 this.position.push([headX,headY])//將下一個位置添加進數組,頭部長一節 if(headX!==this.food[0]||headY!==this.food[1]){//若是下一個頭部位置不是食物的位置,即吃食物開始 this.position.shift()//咱們將尾部去掉,一長一短實現了蛇的走動 }else{//若是下一個頭部位置是食物 this.creatfood()//不去除尾部,再次建立食物(這裏有個小bug,隨機的食物有概率與身體重合) } } }, change(dir){//改變方向 if(Math.abs(dir)===Math.abs(this.direction)){//若是方向相同或者想法,不作任何操做 return }else{ this.direction=dir//不然把方向改動 } },
就是這個樣子,貪吃蛇就寫完了,邏輯方面並非太複雜,可是對於數組的操做有不少,這裏提下我遇見的幾個問題:dom
let po=[[0,0],[1,0],[2,0],[3,0]] let qo=[[0,0]] let oo=[0,0] console.log(po[0]==qo[0])//false console.log(qo[0]==oo)//false
這大概就是最大的收穫,我還太年輕。
由於JavaScript裏面Array是對象,==或===操做符只能比較兩個對象是不是同一個實例,也就是是不是同一個對象引用。目前JavaScript沒有內置的操做符判斷對象的內容是否相同。
可是慣性思惟讓人覺得數組也是值,是能夠比較的。(這段是複製的,別人總結的,和我想法如出一轍)但願能給同爲小白的朋友們提個醒函數
https://github.com/yuyeqianxu...
但願能幫助到和我同樣的小白朋友們,有bug麻煩反饋,謝謝!this