如何用javascript写一个贪吃蛇

我原来用C语言,借助curses库实现了linux 终端下的贪吃蛇游戏

这个javascript版本的贪吃蛇是http://www.veryhuo.com/game/tanchishe.html 的学习笔记,实现的原理和C版本基本一样。

这里最为重要的是用gridElems这个二维数组来表示20*20的格子(实际上是html的td元素),通过gridElems[x][y].className控制td元素的css. 再者就是snake运动中的判断。

--------------------

1.怎样表示一条snake

用一个二维数组存snake的各个点(x,y),同时标记这些点(x,y)为“cover”,这是用于以后检查snake的头是否撞到了snake的body。

//initialize 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]);
		gridElems[x][y].className = "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);  //这里很重要,通过一个二维数组的元素来表示td,通过className控制td的color
		}
		tbody.appendChild(col);  
	}
	table.appendChild(tbody);
	document.getElementById("snakewrap").appendChild(table);
}

部分CSS文件:

td {
	width:20px;
	height:20px;
	background:#f4f4f4/* td background color*/
}

/*snake body color*/
.cover {	background:#39c;}
/*food color*/
.food {background:#093}


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];
	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 listener
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的身体(即gridElems[headX][headY].className == "cover"时),如果碰到,则游戏结束。

3)判断“头”当前的位置是不是食物(即gridElems[headX][headY].className == "food"), 如果头元素的carrier不是食物,则让snake的尾巴pop出来;如果是,则让当前位置的携带信息gridElems[headX][headY].className = false

4 )向数组的开头添加一个元素-->从而实现了“视觉上”的snake移动(或吃食物body增长)的效果


function step() {
	//把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 || gridElems[headX][headY].className == "block" || gridElems[headX][headY].className == "cover") {
		$("say").innerText = "Game Over.";
		
		$("start").removeAttribute("disabled");
		$("start").style.color = "#000";
		
		window.clearInterval(snakeTimer);
		
		return;
	}
	
	var lastX = snake[snake.length-1][0], lastY = snake[snake.length-1][1];
	//如果头元素的carrier不是食物,则让snake的尾巴pop出来
	if(gridElems[headX][headY].className != "food") {
		gridElems[lastX][lastY].className = "";
		snake.pop();
	} 
	else {
		gridElems[lastX][lastY].className = "";
		addObject("food");
	}
	
	//向数组的开头添加一个元素-->从而实现了“视觉上”的snake移动(或吃食物body增长)的效果
	snake.unshift([headX,headY]); 
	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.参考: http://www.veryhuo.com/game/tanchishe.html

8.玩玩:我的simple and stupid snake game 

效果图(CSS我借用了下最近很火的2048):


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值