首页 > 建站教程 > JS、jQ、TS >  如何用javascript写一个贪吃蛇正文

如何用javascript写一个贪吃蛇

1.怎样表示一条snake

    用一个二维数组存snake的各个点(x,y),同时标记这些点(x,y)为“cover”,这是用于以后检查snake的头是否撞到了snake的body。
//初始化 snake
function 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”的元素上:
//初始化格子
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 position
    var 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 37
    up 38
    right 39
    down 40
//键盘事件侦听
function 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; //left
        case 38: headY -= 1; break; //up
        case 39: headX += 1; break  //right
        case 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; //right
        snake = new Array();
        initSnake();
        addObject("food");
        run_run_run();
         
        //让start按钮失效
        $("start").setAttribute("disabled",true);
        $("start").style.color = "#aaa";
    }
}
7.我们看下最终效果:

js贪吃蛇