這是我第一次這么認真的去寫一個程序。今天老師布置的編程任務是實現一個貪吃蛇的小游戲,一開始感覺很茫然的,因為以前都沒有這么系統的去做過一個編程任務。后來理清思路去做,感覺問題也並不是那么的難。
首先,第一步肯定是要編寫出我們的的靜態頁面。
第二步,讓我們的貪吃蛇先從一個開始動起來。
第三步,讓我們通過鍵盤去控制他的運動方向。
第四步,讓我們去判斷我們的貪吃蛇有沒有撞牆,有沒有吃到自己,因為這已經犯規了。
第五步,給我們的貪吃蛇隨機生成一個‘食物’。
第六步,實現每當我們的貪吃蛇吃了一個食物,他都能長個。
下面就是我所寫的代碼,我為每一行代碼都添加上了我個人的理解,可能有一些理解偏差,請多多包涵,另外代碼也異常的臃腫,但是作為初學者的我來說,能實現就已經很滿足了,在以后慢慢的去實現代碼的精簡吧~
<!DOCTYPE html> <html> <head> <title>貪吃蛇</title> <meta charset="utf-8"> <script type="text/javascript" src='js/jquery-3.1.0.js'></script> <!-- 復制粘貼時記得引用Jquery庫喲! --> <style type="text/css"> div { width: 18px; height: 18px; float: left; border: 1px solid #eee; } .out { background: #f00; } .in { background: #0f0; } .snake { background: #00f; } .food { background: #f0f; } </style> </head> <body> <div style="width:300px; height: 300px;" id="demo"> </div> <script type="text/javascript"> var arryRoad = new Array();//創建一個可用方格的數組,這個數組存放的內容是貪吃蛇的“食物”可以出現的位置。 var arrSnake = new Array();//創建一個貪吃蛇數組,這里存放着貪吃蛇身體的數據。它每一格身體的位置。 function bulid(num, outStyle, inStyle) {//這個bulid函數用於創建我們的地圖(傳入的參數:num-->橫向個數和縱向個數;outStyle--->外牆樣式,inStyle-->內部方格樣式) for (var i = 1; i <= num * num; i++) {//使用for循環進行創建Div格子 if (i <= num - 1 || i > num * (num - 1)) {//這里我們做的判斷是創建的盒子是不是第一排或者最后一排的,因為他們是我們的外牆,需要單獨區分。 $('<div class="' + outStyle + '">' + i + '</div>').appendTo($('#demo'));//我們把外牆樣式加給我們創建的div,並且我們將它添加至#demo之中。 } else if (i % num == 0 || i % num == 1) {//這個判斷是進行處理兩邊的外牆的,我們判斷我們所要創建的div是不是每一橫排的第一個或者是最后一個, $('<div class="' + outStyle + '">' + i + '</div>').appendTo($('#demo'));//我們把外牆樣式加給我們創建的div,並且我們將它添加至#demo之中。 } else {//那么剩下的Div就是我們內部的方格啦!!! $('<div class="' + inStyle + '">' + i + '</div>').appendTo($('#demo'));//我們把內部方格樣式加給了我們創建的Div,並且我們將它添加至#demo之中。 arryRoad.push(i - 1);//然后我們把它的索引值添加到了一開始我們所創建的可用方格數組之中。 // 需要注意的是,我們為什么會采用i-1而不是i?我們可以回過去看我們for循環內的條件,我們在開頭聲明的i的初始值是1,並非為0。這么做的原因是為了方便我們計算出外牆。 //數組的索引值是從0開始的,所以我們需要進行i-1。 } } } bulid(15, 'out', 'in');//我們在這里調用bulid函數,並且將參數傳給了他。讓它按照我們一開始預定的想法去執行。 arrSnake = [17];//我們給蛇確定了他的身體部分,這里,我們可以隨意的添加它的長度,但是一定要注意數組的連續性。也不要超過我們的牆的范圍。 var snake = new Object();//我們進行實例化了一個snake對象。 snake.direction = 'right';//給snake創建了一個方向,讓他默認像右移動。 snake.timmer = null;//我們還給蛇創建了一個計時器。這個計時器肯定用來讓我們的貪吃蛇自己運動的啦! function move(direction) {//這里我們創建了一個移動函數,來使我們的貪吃蛇動起來~ var num = 0;//我們先定義一個變量,這變量是用來確定貪吃蛇移動的位置的。 switch (direction) {//我們用swich,case來進行判斷我們的方向 case 'left': num = -1;//向左是-1; break; case 'right': num = 1;//向右是+1; break; case 'up': num = -15;//向上是-15,為什么是-15呢?因為我們一橫排是15個div,那么在這個div的上面的一個div的索引就是當前div的索引-15。這里我偷了一個懶,這里的-15應當由一個變量來替代,會更加的恰當,和代碼的通用性,如果需要對我的代碼進行升級改編,這里肯定是不可省略的。 break; case 'down': num = 15;//向下是+15,同上~ break; } var zb = parseInt(arrSnake[0]) + num;//我們申明一個變量zb,這個坐標是移動的一下個點的位置 var itclassName = $('#demo').children().eq(zb).attr("class").toString();//我們去獲取下一個點的類名。 if (itclassName == "out" || itclassName == 'snake') {//在這里,我們判斷,下一個點是不是外牆,或者是貪吃蛇自己。 alert('You die');//如果是的話~ 那么你就GG啦~ clearInterval(snake.timmer);//別忘了清除計時器,讓我們的貪吃蛇停止運動~ return;//return,跳出函數,下面的代碼將不再執行 } else if (itclassName == 'food') {//我們來判斷下一個點是不是我們的貪吃蛇的‘食物’呢? $('#demo').children().eq(zb).removeClass(); //移除目標位置所有樣式 $('#demo').children().eq(zb).addClass('snake'); //為目標位置添加樣式snake,讓他變成我們的一部分 arrSnake.unshift(zb);//我們將這個點加入到我們貪吃蛇的身體中 console.log('蛇長度' + arrSnake.length);//這里的console是為了方便我們看到貪吃蛇的長度~,可有可無,也可以進行升級。放在我們的body中顯示或者放在網頁的title中 var indxofZb = arryRoad.indexOf(zb); //獲取目標位置在可用位置數組中的索引 arryRoad.splice(indxofZb, 1);//然后,我們將它刪除~,因為他現在已經不可用啦!他已經變成了貪吃蛇的一部分了~ food();//這里我們調用了food函數用來創建貪吃蛇的下一頓美食~ return;//跳出函數,下面的代碼將不再執行 } var lastzb = arrSnake[arrSnake.length - 1]; //同上 $('#demo').children().eq(zb).removeClass(); //同上** $('#demo').children().eq(zb).addClass('snake'); //同上** arrSnake.unshift(zb); //同上** var indxofZb = arryRoad.indexOf(zb); //同上** arryRoad.splice(indxofZb, 1); //同上** $('#demo').children().eq(lastzb).removeClass(); //刪除蛇尾的所有樣式** $('#demo').children().eq(lastzb).addClass('in'); //將原本是貪吃蛇的尾巴重新變成了可用位置。** arrSnake.splice(arrSnake.length - 1, 1); //然后我們將最后一個位置從我們的貪吃蛇數組中刪除~因為他已經不再屬於我們的貪吃蛇了** arryRoad.push(lastzb); //把最arrSnake中的最后一位添加到arryRoad中,因為它已經變成了一個可用位置 //這里我需要強調的一個思想,就是貪吃蛇位移的方法,有些人可能想到的是,將我們的頭的位置變成目標點,將其他的部分依次變成上一個的位置。這種方法雖然也能達到讓貪吃蛇運動的目的,但是這種方法增加了一些不必要的操作。如果我們細心觀察,會發現,貪吃蛇的每次運動,除了頭和尾部的變化,中間部分都沒有發生任何變化。 //那么,這就給了我們一個啟發:我們每次只要改變他的頭和尾部樣式不久可以了嗎?上面打上‘**’標記的正是我所說的方法。 //這種方法還有另外的一種應用,那就是鼠標移動跟隨的流星效果,下一次的博客中,我將分享這種方法的另一種應用。 } $(window).keydown(function(event) {//當鼠標按下時,傳入事件對象~ switch (event.keyCode) {//獲取鍵值碼 case 37://如果鍵值碼為37,代表着我的鍵盤上的左鍵 if (snake.direction != 'right') {//判斷是否當前的方向為右,因為,我們的貪吃蛇不能回頭~ snake.direction = 'left';//如果不是的話,我們將方向改為左 } break;//跳出swich //下面的case語句意思基本雷同,我將不做太多的解說 case 38: if (snake.direction != 'down') { snake.direction = 'up'; } break; case 39: if (snake.direction != 'left') { snake.direction = 'right'; } break; case 40: if (snake.direction != 'up') { snake.direction = 'down'; } break; } }) function autoMove() {//讓蛇自動移動的函數~ snake.timmer = setInterval(function() {//我們創建一個計時器~ move(snake.direction);//目的就是每隔200毫秒調用move函數讓貪吃蛇運動起來,並且我們將方向也傳遞給了他 }, 200) } function randomXY(arryRoad) {//產生隨機數函數~ var x = parseInt(Math.random() * arryRoad.length);//我們產生一個隨機數,這個隨機數的范圍為0~數組長度之間,保證了產生的隨機數對應的方格是可用的~ return arryRoad[x];//我們返回數組中的隨機位置的值 } function food() {//這就是我們之前看到的創建食物的函數 var num = randomXY(arryRoad);//我們聲明一個num變量去接收隨機數 $('#demo').children().eq(num).removeClass('in');//我們在#demo中去尋找隨機索引的div,我們移除它的內部方格樣式 $('#demo').children().eq(num).addClass('food');//並且給他添加了‘食物’樣式 } function init() {//初始化函數 for (var i = 0; i < arrSnake.length; i++) {//我們循環遍歷貪吃蛇數組。 $('#demo').children().eq(arrSnake[i]).removeClass('in');//移出對應的內部方格樣式 $('#demo').children().eq(arrSnake[i]).addClass('snake');//給每一個元素都添加上一個貪吃蛇樣式 } arryRoad.splice(0, arrSnake.length+1);//然后,我們刪除了可用數組中的屬於蛇的部分 food();//給我們的貪吃蛇生產出一個食物~ autoMove();//調用貪吃蛇自動運動函數 } init();//調用初始化函數 // 到這里我們的整個貪吃蛇的編程就已經完成了,我們可以來看看最終的效果 // 謝謝收看~ // by---->SuperZu </script> </body> </html>