把以下代码保存成Snake.html文件,使用Google或360浏览器打开

  1. <!DOCTYPE HTML>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="utf-8" />
  6. <title>Snake</title>
  7. <style>
  8. </style>
  9. </head>
  10.  
  11. <body>
  12. <div style="position: relative">
  13.  
  14. <div style="width: 400px; font-size: 22px; border: 3px solid black;">
  15. 分数:<span id="score"></span>
  16. </div>
  17.  
  18. <canvas id="myCanvas">your browser does not support the canvas</canvas>
  19.  
  20. <div id="help" style="position: absolute; left: 420px; top: 40px;">
  21. Esc: 重新开始</br>
  22. Enter: 开始/暂停/继续</br>
  23. 方向键: 改变蛇的移动方向</br>
  24. Ctrl: 切换控制模式(影响手感)</br>
  25. 数字1: 加速</br>
  26. 数字2: 减速</br>
  27. </div>
  28.  
  29. <div id="gameStates" style="position: absolute; left: 420px; top: 200px; color: red">
  30. 控制模式: <span id="controlMode"></span></br>
  31. 运动状态: <span id="pause"></span></br>
  32. 蛇的方向: <span id="snakeDir"></span></br>
  33. 蛇的速度: <span id="snakeSpeed"></span></br>
  34. 蛇的长度: <span id="snakeLength"></span></br>
  35. <span id="info"></span>
  36. </div>
  37.  
  38. </div>
  39. </body>
  40.  
  41. <script type="text/javascript">
  42. /*
  43. By Problue,2015.10.15
  44. */
  45. var KEY_L = 37;
  46. var KEY_U = 38;
  47. var KEY_R = 39;
  48. var KEY_D = 40;
  49. var KEY_RESET = 27
  50. var KEY_PAUSE = 13;
  51. var KEY_CHANGE_CONTROL_MODE = 17;
  52. var KEY_INC_SPEED = 49;
  53. var KEY_DEC_SPEED = 50;
  54. var MAP_R = 20;
  55. var MAP_C = 20;
  56. var SNAKE_LENGTH_MAX = MAP_R * MAP_C;
  57. var OBJ_SIZE = 20;
  58. var OBJ = {
  59. EMPTY: 0,
  60. SNAKE_HEAD: 1,
  61. SNAKE_BODY: 2,
  62. SNAKE_TAIL: 3,
  63. FOOD: 4,
  64. STONE: 5
  65. };
  66. var colors = ['white', 'midnightblue', 'darkblue', 'mediumblue', 'midnightblue', 'dimgray'];
  67.  
  68. var mapData = "\
  69. 00000000000000000000\
  70. 00000000000000000000\
  71. 00000000000000000000\
  72. 50000000500000055000\
  73. 00000000000000005000\
  74. 00055000000005500000\
  75. 00050000000000500000\
  76. 00000550000550000000\
  77. 00000500000050000000\
  78. 00000000000000000000\
  79. 00000000000000000000\
  80. 00000005000050000000\
  81. 00000005500550000000\
  82. 00000500000000500000\
  83. 00000550000005500000\
  84. 00050000000000000000\
  85. 00055000000000050005\
  86. 00000000000000000000\
  87. 00000000000000000000\
  88. 00000000000000000000";
  89.  
  90. var map = [];
  91.  
  92. var snake = new Snake();
  93. var food = new Point(0, 0);
  94. //var time;
  95.  
  96. var pause;
  97. var over;
  98. var controlQueueMode;
  99. var controlQueue = new Queue();
  100. var score;
  101.  
  102. function Snake() {
  103. this.nodes = [];
  104. this.dir = 0;
  105. this.msSpeed = 0;
  106. }
  107.  
  108. function Point(x, y) {
  109. this.x = x;
  110. this.y = y;
  111. }
  112.  
  113. Point.prototype.clone = function() {
  114. return new Point(this.x, this.y);
  115. }
  116.  
  117. Point.prototype.equals = function(other) {
  118. if(other === this)
  119. return true;
  120. if(!(other instanceof Point))
  121. return false;
  122. return this.x == other.x && this.y == other.y;
  123. }
  124.  
  125. function Queue() {
  126. this.arr = [];
  127. this.head = 0;
  128. this.tail = 0;
  129. }
  130.  
  131. Queue.prototype.enQueue = function(elem) {
  132. this.tail++;
  133. this.arr[this.tail] = elem;
  134. }
  135.  
  136. Queue.prototype.deQueue = function() {
  137. this.head++;
  138. return this.arr[this.head];
  139. }
  140.  
  141. Queue.prototype.empty = function() {
  142. return this.head >= this.tail;
  143. }
  144.  
  145. Queue.prototype.clear = function() {
  146. this.arr.length = 0;
  147. this.head = 0;
  148. this.tail = 0;
  149. }
  150.  
  151. start();
  152.  
  153. function start() {
  154. initGame();
  155. initMap();
  156. initSnake();
  157. drawMap();
  158. showGameStates();
  159. updateScore();
  160. drawSnake();
  161. randFood();
  162. drawObj(food, OBJ.FOOD);
  163. }
  164.  
  165. function initGame() {
  166. canvas = document.getElementById('myCanvas');
  167. cxt = canvas.getContext('2d');
  168. canvas.width = MAP_C * OBJ_SIZE;
  169. canvas.height = MAP_R * OBJ_SIZE;
  170. canvas.style.border = '3px solid black';
  171. document.onkeydown = keydown;
  172. //time = +new Date;
  173. pause = true;
  174. over = 0;
  175. controlQueueMode = true;
  176. score = 0;
  177. }
  178.  
  179. function initMap() {
  180. for(var r = 0; r < MAP_R; r++) {
  181. map.push([]);
  182. for(var c = 0; c < MAP_C; c++) {
  183. var obj = mapData[r * MAP_C + c] - 0;
  184. map[r][c] = obj;
  185. }
  186. }
  187. }
  188.  
  189. function initSnake() {
  190. snake.nodes.length = 0;
  191. snake.nodes.push(new Point(2, 0));
  192. snake.nodes.push(new Point(1, 0));
  193. snake.nodes.push(new Point(0, 0));
  194. snake.dir = KEY_R;
  195. snake.msSpeed = 150;
  196. }
  197.  
  198. function keydown(event) {
  199. var key = window.event ? event.keyCode : event.which;
  200. switch(key) {
  201. case KEY_U:
  202. if(snake.dir != KEY_D) {
  203. snake.dir = key;
  204. controlQueue.enQueue(snake.dir);
  205. }
  206. break;
  207. case KEY_D:
  208. if(snake.dir != KEY_U) {
  209. snake.dir = key;
  210. controlQueue.enQueue(snake.dir);
  211. }
  212. break;
  213. case KEY_L:
  214. if(snake.dir != KEY_R) {
  215. snake.dir = key;
  216. controlQueue.enQueue(snake.dir);
  217. }
  218. break;
  219. case KEY_R:
  220. if(snake.dir != KEY_L) {
  221. snake.dir = key;
  222. controlQueue.enQueue(snake.dir);
  223. }
  224. break;
  225. case KEY_RESET:
  226. start();
  227. break;
  228. case KEY_PAUSE:
  229. pause = !pause;
  230. if(!pause) {
  231. controlQueue.clear();
  232. move();
  233. }
  234. break;
  235. case KEY_CHANGE_CONTROL_MODE:
  236. controlQueueMode = !controlQueueMode;
  237. controlQueue.clear();
  238. break;
  239. case KEY_INC_SPEED:
  240. snake.msSpeed -= 10;
  241. break;
  242. case KEY_DEC_SPEED:
  243. snake.msSpeed += 10;
  244. break;
  245. default: ;
  246. }
  247. showGameStates();
  248. }
  249.  
  250. function moveStep() {
  251. showGameStates();
  252. var newHead = snake.nodes[0].clone();
  253. var oldTail = snake.nodes[snake.nodes.length - 1].clone();
  254.  
  255. switch(snake.dir) {
  256. case KEY_U:
  257. newHead.y--;
  258. break;
  259. case KEY_R:
  260. newHead.x++;
  261. break;
  262. case KEY_L:
  263. newHead.x--;
  264. break;
  265. case KEY_D:
  266. newHead.y++;
  267. break;
  268. }
  269.  
  270. var coord = '坐标(' + snake.nodes[0].x + ',' + snake.nodes[0].y + ')是';
  271. info(coord + '空');
  272. if((newHead.x > MAP_C - 1 || newHead.x < 0) ||
  273. (newHead.y > MAP_R - 1 || newHead.y < 0)) {
  274. info(coord + '墙壁');
  275. over = 1;
  276. return;
  277. }
  278.  
  279. if(isInSnake(newHead)) {
  280. info(coord + '自己');
  281. over = 2;
  282. return;
  283. }
  284.  
  285. var thing = map[newHead.y][newHead.x];
  286.  
  287. if(thing == OBJ.STONE) {
  288. info(coord + '石头');
  289. over = 3;
  290. return;
  291. }
  292.  
  293. if(thing == OBJ.FOOD) {
  294. info(coord + '食物');
  295. snake.nodes.push(new Point(0, 0));
  296. map[newHead.y][newHead.x] = OBJ.EMPTY;
  297. randFood();
  298. drawObj(food, OBJ.FOOD);
  299. updateScore();
  300. showGameStates();
  301. }
  302.  
  303. for(var i = snake.nodes.length - 1; i >= 1; i--)
  304. snake.nodes[i] = snake.nodes[i - 1].clone();
  305. snake.nodes[0] = newHead;
  306. drawObj(oldTail, OBJ.EMPTY);
  307. drawSnake();
  308. }
  309.  
  310. function move() {
  311. if(pause)
  312. return;
  313.  
  314. if(controlQueueMode && !controlQueue.empty())
  315. snake.dir = controlQueue.deQueue();
  316.  
  317. moveStep();
  318.  
  319. if(over) {
  320. over = 0;
  321. var turn = [];
  322. turn[KEY_U] = KEY_R;
  323. turn[KEY_D] = KEY_L;
  324. turn[KEY_L] = KEY_U;
  325. turn[KEY_R] = KEY_D;
  326. snake.dir = turn[snake.dir];
  327. }
  328.  
  329. setTimeout(move, snake.msSpeed);
  330. }
  331.  
  332. function isInSnake(point) {
  333. for(var i = 0; i < snake.nodes.length; i++)
  334. if(snake.nodes[i].equals(point))
  335. return true;
  336. return false;
  337. }
  338.  
  339. function randFood() {
  340. function randInt(n, m) {
  341. return Math.floor(Math.random() * (m - n)) + n;
  342. }
  343. function smart(pt) {
  344. if(pt.x == snake.nodes[0].x) {
  345. if(snake.dir == KEY_U)
  346. return pt.x - snake.nodes[0].x < 0;
  347. if(snake.dir == KEY_D)
  348. return pt.x - snake.nodes[0].x > 0;
  349. }
  350. if(pt.y == snake.nodes[0].y) {
  351. if(snake.dir == KEY_L)
  352. return pt.y - snake.nodes[0].y < 0;
  353. if(snake.dir == KEY_R)
  354. return pt.y - snake.nodes[0].y > 0;
  355. }
  356. return false;
  357. }
  358. do
  359. {
  360. food.x = randInt(0, MAP_C);
  361. food.y = randInt(0, MAP_R);
  362. } while(isInSnake(food) || smart(food) ||
  363. map[food.y][food.x] != OBJ.EMPTY);
  364. map[food.y][food.x] = OBJ.FOOD;
  365. }
  366.  
  367. function info(str) {
  368. $('info').innerHTML = str;
  369. }
  370.  
  371. function showGameStates() {
  372. $('pause').innerHTML = pause ? '静止' : '移动';
  373. $('controlMode').innerHTML = controlQueueMode ? '队列' : '普通';
  374. var toText = [];
  375. toText[KEY_L] = '左';
  376. toText[KEY_U] = '上';
  377. toText[KEY_R] = '右';
  378. toText[KEY_D] = '下';
  379. $('snakeDir').innerHTML = toText[snake.dir];
  380. $('snakeSpeed').innerHTML = snake.msSpeed + 'ms/' + OBJ_SIZE + 'px';
  381. $('snakeLength').innerHTML = snake.nodes.length;
  382. }
  383.  
  384. function updateScore() {
  385. $('score').innerHTML = score++;
  386. }
  387.  
  388. function drawMap() {
  389. var pt = new Point(0, 0);
  390. for(var r = 0; r < MAP_R; r++) {
  391. for(var c = 0; c < MAP_C; c++) {
  392. if(map[r][c] == OBJ.STONE) {
  393. pt.x = c;
  394. pt.y = r;
  395. drawObj(pt, OBJ.STONE);
  396. }
  397. }
  398. }
  399. }
  400.  
  401. function drawSnake() {
  402. drawObj(snake.nodes[0], OBJ.SNAKE_HEAD);
  403. for(var i = 1; i < snake.nodes.length - 1; i++)
  404. drawObj(snake.nodes[i], OBJ.SNAKE_BODY);
  405. drawObj(snake.nodes[snake.nodes.length - 1], OBJ.SNAKE_TAIL);
  406. }
  407.  
  408. function drawObj(point, type) {
  409. cxt.fillStyle = colors[type];
  410. cxt.fillRect(point.x * OBJ_SIZE, point.y * OBJ_SIZE,
  411. OBJ_SIZE, OBJ_SIZE);
  412. }
  413.  
  414. function $(id) {
  415. return document.getElementById(id);
  416. }
  417. </script>
  418.  
  419. </html>

出处:qq群--编程算法&思想 459909287

JS实现——贪吃蛇的更多相关文章

  1. js版贪吃蛇

    之前没有写博客的习惯,这是我的第一个博客,有些的不好的地方,希望大家多多提意见 js版的贪吃蛇相对比较简单,废话不多说直接上代码,有需要注意的地方我会标红,github源码地址https://gith ...

  2. 前端笔记之JavaScript面向对象(三)初识ES6&underscore.js&EChart.js&设计模式&贪吃蛇开发

    一.ES6语法 ES6中对数组新增了几个函数:map().filter().reduce() ES5新增的forEach(). 都是一些语法糖. 1.1 forEach()遍历数组 forEach() ...

  3. JS仿贪吃蛇:一串跟着鼠标的Div

    贪吃蛇是一款80后.90后比较熟悉的经典游戏,下面通过简单的JS代码来实现低仿版贪吃蛇效果:随着鼠标的移动,在页面中呈现所有Div块跟随鼠标依次移动,效果如下图所示. <!DOCTYPE htm ...

  4. 原生JS制作贪吃蛇小游戏

    感情都在代码里,来,干了!... <!doctype html> <html> <head> <meta http-equiv="Content-T ...

  5. 用Js写贪吃蛇

    使用Javascript做贪吃蛇小游戏, 1.自定义地图宽高,蛇的初始速度 2.食物随机出现 3.蛇的样式属性 4.贪吃蛇玩法(吃食物,碰到边界,吃食物后加速,计分,) <!DOCTYPE ht ...

  6. 用js实现贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. OC版贪吃蛇

    昨天写了一个js版贪吃蛇,今天突然想写一个OC版的,来对比一下两种语言的区别 oc版功能,适配所有尺寸iphone,可暂停,可设置地图和蛇的比例,可加速 对比一下会发现js版的相对OC版的会简单一些, ...

  8. 原生js写的贪吃蛇网页版游戏特效

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <bo ...

  9. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

随机推荐

  1. JAVA代码之斗地主发牌

    理解很好理解,关键是思路 按照斗地主的规则,完成洗牌发牌的动作: 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌. ...

  2. java 使用uuid生成唯一字符串

    UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.按照开放软件基金会(OSF)制定的标准计算, ...

  3. C++ string 类型提取字符串

    在某些情况下需要对输入的字符串进行处理,提取其中的需要的信息. 比如在linux中输入"mkdir test",新建test文件夹,就需要提取其中的test字符. 提取的方法需要b ...

  4. Protocol Buffer学习教程之语法手册(二)

    1.说明 此向导介绍如何使用protocol buffer language创建一个自己的protocolbuffer文件,包括语法与如何通过“.proto”文件生成数据访问的类,此处只介绍proto ...

  5. 通过CMD命令行创建和使用Android 模拟器 AVD

    进行Android APP测试时,若手持android手机设备稀少的情况下,我们可以通过创建Android模拟器AVD来代替模拟android手机设备,本文就具体介绍如何创建和使用AVD. 1.创建A ...

  6. xcode技巧

    1.统计ios开发代码,包括头文件的,终端命令进入项目目录下,命令如下 find . -name "*.m" -or -name "*.h" -or -name ...

  7. javaweb基础(16)_jsp指令

    一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...

  8. springmvc的第一个程序

    文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下. web.xml配置: <?xml version="1.0" encoding=" ...

  9. js完成打印功能

    最近在做项目要求实现打印功能,我采用js方式来实现 window.print();会弹出打印对话框,打印的是window.docunemt.body.innerHTML中的内容,可以局部打印,也可以全 ...

  10. lua 使用递归查找键值

    function cc.exports.findValueByTbl(tbl,key)--递归方法,用于查找tbl中对应的键值 for k,v in pairs(tbl) do if k == key ...