我原來用C語言,藉助curses庫實現了linux 終端下的貪吃蛇遊戲。
這個javascript版本的貪吃蛇是http://www.veryhuo.com/game/tanchishe.html 的學習筆記,實現的原理和C版本基本一樣。
--------------------
1.怎樣表示一條snake
用一個二維數組存snake的各個點(x,y),同時標記這些點(x,y)為“cover”,這是用於以後檢查snake的頭是否撞到了snake的body。
//initialize snakefunction initSnake() {var pointer = randomPointer(len-1, len-1, WIDTH/2);for(var i = 0; i < len; i++) {var x = pointer[0] - i,y = pointer[1];snake.push([x,y]);carrier[x][y] = "cover"; //標記snake body}}
2.用js畫出格子
用document.createElent()方法建立出table->tr->td, 然後用document.appendChild()方法追加到id為“snakewrap”的元素上:
//initialize grid function initGrid() {var body = document.getElementsByTagName("body")[0];var table = document.createElement("table"),tbody = document.createElement("tbody")for(var j = 0; j < HEIGHT; j++) { var col = document.createElement("tr"); for(var i = 0; i < WIDTH; i++) { var row = document.createElement("td");gridElems[i][j] = col.appendChild(row); }tbody.appendChild(col); }table.appendChild(tbody);document.getElementById("snakewrap").appendChild(table);}
3.產生食物的隨機座標
function randomPointer(startX,startY,endX,endY) {startX = startX || 0;startY = startY || 0;endX = endX || WIDTH;endY = endY || HEIGHT;var p = [],x = Math.floor(Math.random()*(endX - startX)) + startX,y = Math.floor(Math.random()*(endY - startY)) + startY;//如果(x,y)有物體,則重建座標if(carrier[x][y]) {return randomPointer(startX,startY,endX,endY);}p[0] = x;p[1] = y;return p;}
添加新的食物:
//addObject("food")function addObject(name) {var p = randomPointer(); //get random positionvar x = p[0];var y = p[1];carrier[x][y] = name;gridElems[x][y].className = name;}
4.方向鍵按下動作事件監聽:
允許左上右下這4個按鍵來改變snake的運動方向,注意,如果方向相反的話,不生效。
對於鍵盤上的每一個按鍵,都有一個key cord,我的這篇部落格記錄了javascript的key cord,可看到:
| left arrow |
37 |
| up arrow |
38 |
| right arrow |
39 |
| down arrow |
40 |
//keyboard event listenerfunction attachEvents(e) {e = e || event;directkey = Math.abs(e.keyCode - directkey) != 2 && e.keyCode > 36 && e.keyCode < 41 ? e.keyCode : directkey; return false;}
5.貪吃蛇的核心--判斷
每次判斷(即judge()函數每運行一次-->這裡用到了setInterval()方法),都要先把snake的“頭”節點儲存下來,然後做判斷
1)判斷方向,根據方向調整“頭”的座標(由於有setInterval()方法,系統會每個若個毫秒就運行一次judge()函數,確保使用者按下方向鍵後能夠該表方向)
2)判斷“頭”是否撞到牆,或碰到snake的身體(即carrier[headX][headY] == "cover"時),如果碰到,則遊戲結束。
3)判斷“頭”當前的位置是不是食物(即carrier[headX][headY] == "food"), 如果頭元素的carrier不是食物,則讓snake的尾巴pop出來;如果是,則讓當前位置的攜帶資訊carrier[headX][headY] = false
4 )向數組的開頭添加一個元素-->從而實現了“視覺上”的snake移動(或吃食物body增長)的效果
function judge() {//把snake的“頭”位置暫存起來var headX = snake[0][0], headY = snake[0][1];switch(directkey) {case 37: headX -= 1; break; //leftcase 38: headY -= 1; break; //upcase 39: headX += 1; break //rightcase 40: headY += 1; break; //down}//碰到邊界(block),或頭碰到身體(cover),則結束遊戲if(headX >= WIDTH || headX < 0 || headY >= HEIGHT || headY < 0 || carrier[headX][headY] == "block" || carrier[headX][headY] == "cover" ) {$("say").innerText = "Game Over.";$("start").removeAttribute("disabled");$("start").style.color = "#000";window.clearInterval(snakeTimer);return;}//如果頭元素的carrier不是食物,則讓snake的尾巴pop出來if(carrier[headX][headY] != "food") {var lastX = snake[snake.length-1][0],lastY = snake[snake.length-1][1];carrier[lastX][lastY] = false;gridElems[lastX][lastY].className = "";snake.pop();} else {carrier[headX][headY] = false;addObject("food"); //吃掉食物,然後調用addObject("food"),重建食物}//向數組的開頭添加一個元素-->從而實現了“視覺上”的snake移動(或吃食物body增長)的效果snake.unshift([headX,headY]); carrier[headX][headY] = "cover";gridElems[headX][headY].className = "cover";len = snake.length;}
setInterval()函數(使得上面的judge()函數每隔300ms就運行一次):
function run_run_run() {if(snakeTimer) {window.clearInterval(snakeTimer);}snakeTimer = window.setInterval("judge()", Math.floor(300));}
6.onload 運行
onload 事件會在頁面或映像載入完成後立即發生:
window.onload = function(){initGrid(); document.onkeydown = attachEvents; //監聽keydown事件$("start").onclick = function (e) {len = 3; //snake的初始長度directkey = 39; //rightsnake = new Array();initSnake(); addObject("food");run_run_run();//讓start按鈕失效$("start").setAttribute("disabled",true);$("start").style.color = "#aaa";}}
7.參考:http://www.veryhuo.com/game/tanchishe.html
8.玩玩:我的simple and stupid snake game
(CSS我借用了下最近很火的2048):