前言

最近在csdn上看到一位大神用20行代码就写出了一个贪吃蛇的小游戏,感觉被惊艳到了,就试着读了一下这段代码,阅读过程中不断为作者写法的巧妙而叫绝,其中我发现自己对运算符优先级和一些js的技巧不是很清楚,所以看完之后决定把思路分享出来,方便和我一样的小白学习。
我对代码稍稍做了些修改,并添加了一些注释,方便理解。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>贪吃蛇重构</title>
<style>
body {
display: flex;
height: 100vh;
margin: 0;
padding: 0;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<canvas id="can" width="400" height="400" style="background-color: black">对不起,您的浏览器不支持canvas</canvas>
<script>
var snake = [41, 40], //snake队列表示蛇身,初始节点存在但不显示
direction = 1, //1表示向右,-1表示向左,20表示向下,-20表示向上
food = 43, //食物的位置
n, //与下次移动的位置有关
box = document.getElementById('can').getContext('2d');
//从0到399表示box里[0~19]*[0~19]的所有节点,每20px一个节点
function draw(seat, color) {
box.fillStyle = color;
box.fillRect(seat % 20 *20 + 1, ~~(seat / 20) * 20 + 1, 18, 18);
//用color填充一个矩形,以前两个参数为x,y坐标,后两个参数为宽和高。
}
document.onkeydown = function(evt) {
//当键盘上下左右键摁下的时候改变direction
direction = snake[1] - snake[0] == (n = [-1, -20, 1, 20][(evt || event).keyCode - 37] || direction) ? direction : n;
};
!function() {
snake.unshift(n = snake[0] + direction);
//此时的n为下次蛇头出现的位置,n进入队列
if(snake.indexOf(n, 1) > 0 || n < 0 || n > 399 || direction == 1 && n % 20 == 0 || direction == -1 && n % 20 == 19) {
//if语句判断贪吃蛇是否撞到自己或者墙壁,碰到时返回,结束程序
return alert("GAME OVER!");
}
draw(n, "lime"); //画出蛇头下次出现的位置
if(n == food) { //如果吃到食物时,产生一个蛇身以外的随机的点,不会去掉蛇尾
while (snake.indexOf(food = ~~(Math.random() * 400)) > 0);
draw(food, "yellow");
} else { //没有吃到食物时正常移动,蛇尾出队列
draw(snake.pop(),"black");
}
setTimeout(arguments.callee, 150);
//每隔0.15秒执行函数一次,可以调节蛇的速度
}();
</script>
</body>
</html>
首先,我们要知道做一个贪吃蛇最主要的是什么,是做出蛇活动的场所和如何使蛇动起来。
我们先看蛇活动的场所:
<!-- html -->
<canvas id="can" width="400" height="400" style="background-color: black">
对不起,您的浏览器不支持canvas
</canvas>
<!-- js -->
box = document.getElementById('can').getContext('2d');
这是一个400px*400px的canvas,思路是以20px*20px为一个方格,组成20行20列的方阵,总共400格,然后绿色填充的格子表示蛇身,用黄色表示食物。这400个格子和数字0~399一一对应,对应的方式就是以20作为基数,n / 20再取整表示第几行,n % 20表示第几列。行数和列数都用0~19表示。
蛇用一个一维数组表示,每个值都是这400个数中的一个,用var snake = [41, 40];初始化这条蛇,索引0为蛇头。food表示食物的位置,direction表示蛇头下一次运动的转向。蛇的运动就用添加和删除数组元素来实现,每次执行绘制蛇头,去掉蛇尾,循环执行使蛇运动。
下边从函数运行的起始处(39行)开始看:
!function() {}();
什么鬼?这其实是立即执行函数IIFE的另一种写法。关于IIFE,这篇文章讲的挺不错的。继续往下看,给蛇头添加一个节点n,其值为当前蛇头的值加direction的值,如此一来就能理解为什么要用20表示向下,-20表示向上了。再下一行是一个if语句,其中值得提醒的是&&的优先级高于||,这个语句就是判断即将出现的蛇头是不是属于蛇身,或者跑到box外边去了。如果没有死亡,就把这个蛇头绘制出来,下边就看看绘制的代码:
function draw(seat, color) {
box.fillStyle = color;
box.fillRect(seat % 20 *20 + 1, ~~(seat / 20) * 20 + 1, 18, 18);
}
填充时填充18*18的像素,留1px边框。 .fillRect()中第一个参数就是要绘制的矩形的x坐标seat % 20 *20 + 1,即先得到所要绘制的矩形块在方阵中的位置:第~~(seat / 20)行,第seat % 20列,再* 20 + 1具体到像素点。可能这个~~有点难理解,我感觉在这里的用处应该和Math.floor()差不多,对一个浮点型的数取反再取反,得到的数就是去掉小数位的整数了。
回到47行,又是一个判断语句,判断下次蛇头出现的位置是不是和当前的食物的位置相同,如果相同,生成下一个食物,食物的位置为一个随机数,但是要判断这个点不是出现在当前的蛇身上,绘制食物。如果没有吃到食物,即蛇在正常运动时,每向前一次,将蛇尾弹出,并利用其返回值将这个点重新绘制为黑色。
最后的setTimeout,循环执行当前函数,设置执行周期来调蛇的移动速度。
到了这里,我们发现这条蛇已经可以动了,加上键盘的操作就完成了:
document.onkeydown = function(evt) {
direction = snake[1] - snake[0] == (n = [-1, -20, 1, 20][(evt || event).keyCode - 37] || direction) ? direction : n;
};
将这个函数绑定到键盘事件上,evt || event用法的原因这里有详细的解释,是为了兼容ie。
三目运算符?前边的判断语句又可分为两部分:
snake[1] - snake[0]的值应该就是-direction,按理说此处写成-direction应该和原来是一个效果,那为什么没有这么做呢,因为如果这样写,玩家可能在一个函数周期中多次改变direction的值,最后使得direction和当前真正的运动方向不一致,导致游戏崩溃。 [-1, -20, 1, 20][(evt || event).keyCode - 37]中前边的[]是一个数组,后边的[]是取索引,左上右下四个键的keyCode分别为37, 38, 39, 40,计算后的索引为0, 1, 2, 3,使方向键与direction的取值对应起来。这里的巧妙之处在于如果按下的按键不是方向键,在数组中将得不到对应的值,返回undefine。此时,由于之后的||运算符,n会取到direction原来的值。再用三目运算符来判断,如果按键方向不是反方向,就更新direction的值。
以上就是本篇的全部内容啦,虽然都是一些基础的东西,但是感觉还是挺好玩的。要是哪里理解的不对还希望指证出来,共同进步。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# js贪吃蛇代码
# 贪吃蛇20行代码
# 贪吃蛇js源代码
# JS写的贪吃蛇游戏(个人练习)
# javascript贪吃蛇完整版(源码)
# JS实现的贪吃蛇游戏完整实例
# js实现贪吃蛇小游戏(容易理解)
# js编写贪吃蛇的小游戏
# js贪吃蛇游戏实现思路和源码
# javascript 贪吃蛇实现代码
# javascript实现简单的贪吃蛇游戏
# 原生js实现的贪吃蛇网页版游戏完整实例
# js手写贪吃蛇游戏实例源码
# 是一个
# 的是
# 都是
# 运算符
# 您的
# 下次
# 贪吃蛇
# 吃到
# 蛇尾
# 这条
# 如果没有
# 不支持
# 这篇文章
# 方向键
# 再取
# 在这里
# 随机数
# 去了
# 出了
# 第一个
相关文章:
C++用Dijkstra(迪杰斯特拉)算法求最短路径
早安海报制作网站推荐大全,企业早安海报怎么每天更换?
高防服务器租用首荐平台,企业级优惠套餐快速部署
如何解决ASP生成WAP建站中文乱码问题?
海南网站制作公司有哪些,海口网是哪家的?
如何高效利用亚马逊云主机搭建企业网站?
天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?
如何通过FTP空间快速搭建安全高效网站?
建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略
道歉网站制作流程,世纪佳缘致歉小吴事件,相亲网站身份信息伪造该如何稽查?
在线教育网站制作平台,山西立德教育官网?
制作农业网站的软件,比较好的农业网站推荐一下?
网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?
建站之星后台密码遗忘?如何快速找回?
c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】
如何快速生成凡客建站的专业级图册?
网站建设设计制作营销公司南阳,如何策划设计和建设网站?
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
Thinkphp 中 distinct 的用法解析
广州建站公司哪家好?十大优质服务商推荐
网站制作价目表怎么做,珍爱网婚介费用多少?
创业网站制作流程,创业网站可靠吗?
建站之星安装失败:服务器环境不兼容?
如何通过免费商城建站系统源码自定义网站主题与功能?
如何登录建站主机?访问步骤全解析
宁波自助建站系统如何快速打造专业企业网站?
建站之星云端配置指南:模板选择与SEO优化一键生成
香港网站服务器数量如何影响SEO优化效果?
公司网站制作费用多少,为公司建立一个网站需要哪些费用?
如何快速搭建自助建站会员专属系统?
如何确保西部建站助手FTP传输的安全性?
Python多线程使用规范_线程安全解析【教程】
建站之星×万网:智能建站系统+自助建站平台一键生成
如何在阿里云部署织梦网站?
网站制作话术技巧,网站推广做的好怎么话术?
如何用5美元大硬盘VPS安全高效搭建个人网站?
股票网站制作软件,网上股票怎么开户?
如何零成本快速生成个人自助网站?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
建站主机与服务器功能差异如何区分?
如何快速使用云服务器搭建个人网站?
打鱼网站制作软件,波克捕鱼官方号怎么注册?
建设网站制作价格,怎样建立自己的公司网站?
深圳网站制作费用多少钱,读秀,深圳文献港这样的网站很多只提供网上试读,但有些人只要提供试读的文章就能全篇下载,这个是怎么弄的?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
C#如何使用XPathNavigator高效查询XML
合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?
如何在阿里云完成域名注册与建站?
建站之星如何通过成品分离优化网站效率?
*请认真填写需求信息,我们会在24小时内与您取得联系。