全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

20行js代码实现的贪吃蛇小游戏

前言

最近在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。

三目运算符?前边的判断语句又可分为两部分:

  1. snake[1] - snake[0]的值应该就是-direction,按理说此处写成-direction应该和原来是一个效果,那为什么没有这么做呢,因为如果这样写,玩家可能在一个函数周期中多次改变direction的值,最后使得direction和当前真正的运动方向不一致,导致游戏崩溃。
  2. 在==后边, [-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手写贪吃蛇游戏实例源码  # 是一个  # 的是  # 都是  # 运算符  # 您的  # 下次  # 贪吃蛇  # 吃到  # 蛇尾  # 这条  # 如果没有  # 不支持  # 这篇文章  # 方向键  # 再取  # 在这里  # 随机数  # 去了  # 出了  # 第一个 


相关文章: 网页设计网站制作软件,microsoft office哪个可以创建网页?  如何用PHP快速搭建高效网站?分步指南  建站之星安装后如何自定义网站颜色与字体?  如何用景安虚拟主机手机版绑定域名建站?  临沂网站制作企业,临沂第三中学官方网站?  建站主机助手选型指南:2025年热门推荐与高效部署技巧  为什么Go需要go mod文件_Go go mod文件作用说明  如何解决VPS建站LNMP环境配置常见问题?  建站之星安装失败:服务器环境不兼容?  手机网站制作与建设方案,手机网站如何建设?  Android使用GridView实现日历的简单功能  深圳网站制作平台,深圳市做网站好的公司有哪些?  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  建站主机如何选?高性价比方案全解析  建站之星如何快速解决建站难题?  建站ABC备案流程中有哪些关键注意事项?  如何自定义建站之星网站的导航菜单样式?  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  如何选择长沙网站建站模板?H5响应式与品牌定制哪个更优?  建站之星如何通过成品分离优化网站效率?  长沙做网站要多少钱,长沙国安网络怎么样?  TestNG的testng.xml配置文件怎么写  如何打造高效商业网站?建站目的决定转化率  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  如何注册花生壳免费域名并搭建个人网站?  制作营销网站公司,淘特是干什么用的?  沈阳制作网站公司排名,沈阳装饰协会官方网站?  IOS倒计时设置UIButton标题title的抖动问题  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  如何高效生成建站之星成品网站源码?  韩国服务器如何优化跨境访问实现高效连接?  公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  如何高效完成独享虚拟主机建站?  装修招标网站设计制作流程,装修招标流程?  道歉网站制作流程,世纪佳缘致歉小吴事件,相亲网站身份信息伪造该如何稽查?  如何构建满足综合性能需求的优质建站方案?  如何快速上传建站程序避免常见错误?  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  如何在Windows环境下新建FTP站点并设置权限?  常州企业建站如何选择最佳模板?  建站主机系统SEO优化与智能配置核心关键词操作指南  公司门户网站制作流程,华为官网怎么做?  常州自助建站工具推荐:低成本搭建与模板选择技巧  怎么用手机制作网站链接,dw怎么把手机适应页面变成网页?  C#如何序列化对象为XML XmlSerializer用法  建站之星北京办公室:智能建站系统与小程序生成方案解析  制作网站公司那家好,网络公司是做什么的?  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  如何获取免费开源的自助建站系统源码? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。