这个javascript版本的贪吃蛇是http://www.veryhuo.com/game/tanchishe.html 的学习笔记,实现的原理和C版本基本一样。
--------------------
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])
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 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 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
}
以前做的一个 部分注释 核心部分由注释 其实就是一个最后一个跟随前面一个位置的算法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
.body{width:600pxmargin:100px autotext-align:center}
#main{height:300pxborder:1px solid #f00position:relative}
#main div{width:20pxheight:20pxbackground-color:greenposition:absolute}
#main div.snake{background-color:#ff0}
.score{font-size:14px}
.score strong{color:Red}
</style>
<script type="text/javascript">
window.onload = function () {
var omain = document.getElementById("main")
var r = 15, c = 30
var asnake = []
var speed = 150
var odiv = document.createElement("div")
asnake.push({ l: Math.floor(Math.random() * c), t: Math.floor(Math.random() * r), div: odiv, d: "l" })
omain.appendChild(odiv)
setPosition(asnake[0])
//设置位置
function setPosition(obj) {
obj.div.style.left = obj.l * 20 + "px"
obj.div.style.top = obj.t * 20 + "px"
}
var aEat = null
var d = "l"
//创建吃的
function createEat() {
var l = Math.floor(Math.random() * c)
var t = Math.floor(Math.random() * r)
var isexist = false
//判断是否存在在设数组里面
for (var i = 0 i < asnake.length i++) {
if (l == asnake[i].l && t == asnake[i].t) {
isexist = true
break
}
}
//如果存在再创建一个蛇
if (isexist) {
createEat()
return
}
var onewdiv = document.createElement("div")
onewdiv.className = "snake"
aEat = { l: l, t: t, div: onewdiv, d: "l" }
omain.appendChild(onewdiv)
setPosition(aEat)
}
createEat()
var obtn = document.getElementById("btn")
var oscore = document.getElementById("score")
var oaddspeed = document.getElementById("addspeed")
var otimer = null
var isitem = true
oaddspeed.onclick = function () {
clearInterval(otimer)
speed = speed < 50 ? 50 : speed - 20
setasnke()
}
obtn.onclick = function () {
if (!isitem) {
clearInterval(otimer)
obtn.value = "继续游戏"
isitem = true
return false
}
obtn.value = "暂停游戏"
setasnke()
isitem = false
}
function setasnke() {
otimer = setInterval(function () {
for (var i = asnake.length - 1 i > 0 i--) {
asnake[i].l = asnake[i - 1].l
asnake[i].t = asnake[i - 1].t
asnake[i].d = asnake[i - 1].d
}
switch (d) {
case "l":
asnake[0].l--
break
case "r":
asnake[0].l++
break
case "t":
asnake[0].t--
break
case "b":
asnake[0].t++
break
}
//判断蛇是否撞墙了
if (asnake[0].l < 0 || asnake[0].l >= c || asnake[0].t < 0 || asnake[0].t >= r) {
alert("你死掉了")
clearInterval(otimer)
return
}
//判断蛇是否撞到自己了
for (var n = 1 n < asnake.length n++) {
if (asnake[0].l == asnake[n].l && asnake[0].t == asnake[n].t) {
alert("你已经死掉了")
clearInterval(otimer)
return
}
}
//判断蛇是否吃到东西了
if (asnake[0].l == aEat.l && asnake[0].t == aEat.t) {
aEat.div.className = ""
oscore.innerHTML = parseInt(oscore.innerHTML) + 1
asnake.push(aEat)
createEat()
}
//重新设置蛇的位置
for (var j = 0 j < asnake.length j++) {
setPosition(asnake[j])
}
}, speed)
}
//键盘改变蛇的方向
document.onkeydown = function (event) {
var oEn = event || window.event
var oCode = oEn.keyCode
switch (oCode) {
case 37:
d = "l"
break
case 38:
d = "t"
break
case 39:
d = "r"
break
case 40:
d = "b"
break
}
}
}
</script>
</head>
<body>
<div class="body">
<input type="button" value="加速" id="addspeed" /> <input type="button" id="btn" value="开始游戏" />&nbsp&nbsp<span class="score">积分:<strong id="score">0</strong></span>
<div id="main">
</div>
</div>
</body>
</html>