博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20行代码的贪吃蛇
阅读量:6084 次
发布时间:2019-06-20

本文共 2273 字,大约阅读时间需要 7 分钟。

  在csdn上看到一位大神用20行代码就写出了一个贪吃蛇的小游戏,,感觉被惊艳到了,就试着读了一下这段代码,阅读过程中不断为作者写法的巧妙而叫绝,其中我发现自己对运算符优先级和一些js的技巧不是很清楚,所以看完之后决定把思路分享出来,和大家一起学习。可以,可能需要翻墙,你也可以在我的上直接查看源码。github上还有许多别的有趣的demo,喜欢可以顺手点个star

  我对代码稍稍做了些修改,并添加了一些注释,方便理解。

    
贪吃蛇重构
对不起,您的浏览器不支持canvas

  首先,我们要知道做一个贪吃蛇最主要的是什么,是做出蛇活动的场所和如何使蛇动起来。

  我们先看蛇活动的场所:

对不起,您的浏览器不支持canvas
box = document.getElementById('can').getContext('2d');

  这是一个400px*400pxcanvas,思路是以20px*20px为一个方格,组成2020列的方阵,总共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()差不多,可以用来截除小数,两者具体还有一些区别,可以去看《你不知道的js(中卷)》62页。

  回到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的值。

以上就是本篇的全部内容啦,虽然都是一些基础的东西,但是感觉还是挺好玩的。要是哪里理解的不对还希望指证出来,共同进步。以及,欢迎来访

转载地址:http://jhkwa.baihongyu.com/

你可能感兴趣的文章
Internet Message Access Protocol --- IMAP协议
查看>>
Linux 获取文件夹下的所有文件
查看>>
对 Sea.js 进行配置(一) seajs.config
查看>>
第六周
查看>>
解释一下 P/NP/NP-Complete/NP-Hard 等问题
查看>>
javafx for android or ios ?
查看>>
微软职位内部推荐-Senior Software Engineer II-Sharepoint
查看>>
sql 字符串操作
查看>>
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>
根据Uri获取文件的绝对路径
查看>>
Flutter 插件开发:以微信SDK为例
查看>>
.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何修复处理?...
查看>>
边缘控制平面Ambassador全解读
查看>>
Windows Phone 7 利用计时器DispatcherTimer创建时钟
查看>>
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>
MapReduce的模式,算法以及用例
查看>>
《Advanced Linux Programming》读书笔记(1)
查看>>