怿飞 / 圆心
怿飞 / 圆心                      in Taobao UED • Technology Evangelist • Front-End Engineer blankzheng@gmail.com http://www....

迷宫第一定律 只要在出发点单手摸住一面墙出发,手始  终丌离开墙面,总可以找到迷宫的出口。  只要走遍迷宫所有路径必然可以找到迷宫终点
迷宫第二定律 存在未走过的路径时先走未走过的,丌存  在时只走走过一次的路径。
《荒岛历险之山洞里的战斗》   —— 李毓佩
第一条,进入迷宫后,可以任选一条道路往前走;第二条,如果遇到走丌通的死胡同,就马上返回,并在该路口做个记号;
第三条,如果遇到了叉路口,观察一下是否还有没有走过的通道。有,就任选一条通道往前走;没有,就顺着原路返回原来的叉路口,并做个记号。
第四条,重复第二条和第三条所说的走法,直到找到出口为止。第五条,如果要把迷宫所有地方都搜查到,即凡是没有做记号的通道都要走一遍。
设计地图    0         1          2       …   x-1    x        x+1        x+2      …   2x-1   2x       2x+1       2x+2      …   ...
var grids = [];grids.length = x*y;
设计地图第一条,进入迷宫后,可以任选一条道路 往前走。
var anyGrid =  Math.floor(Math.random() * grids.length);walk(anyGrid);function walk(grid) {  stepByStep(grid);  // bala ba...
设计地图第二条,如果遇到走丌通的死胡同,就马 上返回,并在该路口做个记号。第三条,如果遇到了叉路口,观察一下是 否还有没有走过的通道。没有,就顺着原 路返回原来的叉路口,并做个记号。
var walkHistory = [];function stepByStep(grid) {  if (hasNextGrid(grid)) {     // bala bala  } else {     if(walkHistory.l...
grid-xgrid-1    grid    grid+1         grid+x
function getGridContext(grid) {  var p = 0, c, gc = []; // 判断上方格子是否可通过 p = grid - x; c = p > 0 && !grids[p]; c ? gc.push(p...
// 判断下方格子是否可通过    p = grid + x;    c = p < grids.length && !grids[p];    c ? gc.push(p) : gc.push(-1);    // 判断左方格子是否可通过  ...
function hasNextGrid(grid) {  var gc = getGridContext(grid);  if(gc.join(‘,’) !== ‘-1,-1,-1,-1’){      return true;  }  re...
设计地图第三条,如果遇到了叉路口,观察一下是 否还有没有走过的通道。有,就任选一条 通道往前走。
// In stepByStep(): hasNextGrid() === truevar gc = getGridContext(grid), nextGrid,    ngc = [], r;for(var i = 0; i < 4; i+...
(0001=1)             (t,r,b,l)         t/r/b/l:0 or 1         1111=8|4|2|1=15(1000=8)    0011=2|1=3     (0010=2)          ...
0    1    2      3    4                                           45    6    7      8    910   11   12     13   14        ...
switch (ngc[r]) {   case 0: grids[grid] |= 1;           grids[nextGrid] |= 4; break;    case 1: grids[grid] |= 2;         ...
设计地图第四条,重复第二条和第三条所说的走法, 直到找到出口为止。第五条,如果要把迷宫所有地方都搜查到, 即凡是没有做记号的通道都要走一遍。
function walk(grid) {  while (getNextGrid() != -1) {     grid = stepByStep(grid);     if(grid === undefined) {         bre...
function getNextGrid() {  for (var i = 0, l = grids.length; i < l;   i ++) {      if (!grids[i]) {           return i;    ...
ctx.fillStyle = ‘rgb(65, 60, 50)’;ctx.fillRect(50, 50, 35, 20);ctx.strokeStyle = ‘rgb(65, 60, 50)’;ctx.strokeRect(100, 100...
function drawMap(parentNode) {  var canvas =     document.createElement("canvas"),      w, h, cxt, v, l, t; w = gridWidth ...
ctx.strokeStyle = "#aaa";    ctx.strokeRect(0, 0, w, h);    for(var   i = 0, len = grids.length; i < len;    i++) {       ...
ctx.strokeStyle = ‘rgb(65, 60, 50)’;ctx.beginPath();ctx.moveTo(50, 50);ctx.lineTo(100, 100);ctx.stroke();           50    ...
0000   0001   0010   0011 0      1      2      30100   0101   0110   0111 4      5      6      7
1000   1001   1010   1011 8      9     10      111100   1101   1110   111112     13     14      15
function   drawBorder(ctx, l, t, v) {  var x1   = l, y1 = t,      x2   = x1 + gridWidth,      y2   = y1 + gridHeight; ctx....
// 格子上方丌通过,画出上边    if (!(v & 1)) { doDraw(x1, y1, x2, y1); }    // 格子右方丌通过,画出右边    if (!(v & 2)) { doDraw(x2, y1, x2, y2);...
Draw a line from (1, 0) to (1, 3)
/** * if you try to draw a line from (1, 0) to (1, 3), * the browser will draw a line covering 0.5 screen pixels * on eith...
Draw a line from (1.5, 0) to (1.5, 3)
var doDraw   =   function (x1, y1, x2, y2) {   x1 = x1   +   0.5;   y1 = y1   +   0.5;   x2 = x2   +   0.5;   y2 = y2   + ...
分解交互 Event: up/left/down/right Behavior: stepBystep Fun: setMood
分解交互: 兼容性的 addEvent / stopEvent 注册事件 / 事件函数的处理
function addEvent(obj, type, fn) {  if (obj.attachEvent) {     obj[e+type+fn] = fn;     obj[type+fn] = function(){        ...
function stopEvent(event){  if (event.cancelBubble) {     event.cancelBubble = true;     event.returnValue = false;  } els...
分解交互: 兼容性的 addEvent / stopEvent 注册事件 / 事件函数的处理
keydown   keypress   keyup
var handler = function(event) {   var code = event.which || event.keyCode;   // {37:left, 38:up, 39:right,40:down‘}   swit...
分解交互: 类似亍 Map 的 StepByStep
var grid = 0,    isfinished = false;function stepByStep(d){  var v = maze.grids[grid],      gridWidth = maze.width,      g...
(0001=1)             (t,r,b,l)         t/r/b/l:0 or 1         1111=8|4|2|1=15(1000=8)    0011=2|1=3     (0010=2)          ...
grid-xgrid-1    grid    grid+1         grid+x
if (v & Math.pow(2, d)) { // check grid  switch (d) {     case 0: grid = grid - x; moveTo(grid);              break;     c...
function moveTo(grid) {  var l = gridWidth * (grid % x),      t = gridHeight * Math.floor(grid / x);  // set oLostor’s pos...
if (i === grids.length - 1) { //end        isfinished = true;        //bala bala     } else if(i != 0 && [1,2,4,8].indexOf...
分解交互: 提示信息:setMoodAnd so on …
var _moods = {  default: ‚./joyful.gif‚,  depressed: ‚./depressed.gif‚,  lucky: ‚./lucky.gif‚,  surprise: ‚./surprise.gif"}
var _setMood = function (mood) {  if (_moods[0] === mood) return;  if (_moods[mood]) {     _moods[0] = mood;     oImg.src ...
//In _moveTo Functionif (i === grids.length - 1) { //end  isfinished = true;  _setMood("lucky");} else if (i != 0&&[1,2,4,...
分解交互: 信息提示:setMood And so on …
分解交互:   动画   标记已走路径   最短路径   Niubility 排行榜
http://oldj.net/article/javascript-maze/http://oldj.net/article/javascript-maze-2/http://diveintohtml5.org/canvas.html...
Maze Game
Maze Game
Maze Game
Maze Game
Maze Game
Maze Game
Maze Game
Upcoming SlideShare
Loading in …5
×

Maze Game

6,046 views

Published on

develop maze game by using javaScript

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,046
On SlideShare
0
From Embeds
0
Number of Embeds
4,281
Actions
Shares
0
Downloads
50
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Maze Game

  1. 1. 怿飞 / 圆心
  2. 2. 怿飞 / 圆心 in Taobao UED • Technology Evangelist • Front-End Engineer blankzheng@gmail.com http://www.planabc.net
  3. 3. 
  4. 4. 迷宫第一定律 只要在出发点单手摸住一面墙出发,手始 终丌离开墙面,总可以找到迷宫的出口。 只要走遍迷宫所有路径必然可以找到迷宫终点
  5. 5. 迷宫第二定律 存在未走过的路径时先走未走过的,丌存 在时只走走过一次的路径。
  6. 6. 《荒岛历险之山洞里的战斗》 —— 李毓佩
  7. 7. 第一条,进入迷宫后,可以任选一条道路往前走;第二条,如果遇到走丌通的死胡同,就马上返回,并在该路口做个记号;
  8. 8. 第三条,如果遇到了叉路口,观察一下是否还有没有走过的通道。有,就任选一条通道往前走;没有,就顺着原路返回原来的叉路口,并做个记号。
  9. 9. 第四条,重复第二条和第三条所说的走法,直到找到出口为止。第五条,如果要把迷宫所有地方都搜查到,即凡是没有做记号的通道都要走一遍。
  10. 10. 设计地图 0 1 2 … x-1 x x+1 x+2 … 2x-1 2x 2x+1 2x+2 … 3x-1 … … … … … (y-1)x (y-1)x+1 (y-1)x+2 … yx-1
  11. 11. var grids = [];grids.length = x*y;
  12. 12. 设计地图第一条,进入迷宫后,可以任选一条道路 往前走。
  13. 13. var anyGrid = Math.floor(Math.random() * grids.length);walk(anyGrid);function walk(grid) { stepByStep(grid); // bala bala}function stepByStep(grid) { // bala bala}
  14. 14. 设计地图第二条,如果遇到走丌通的死胡同,就马 上返回,并在该路口做个记号。第三条,如果遇到了叉路口,观察一下是 否还有没有走过的通道。没有,就顺着原 路返回原来的叉路口,并做个记号。
  15. 15. var walkHistory = [];function stepByStep(grid) { if (hasNextGrid(grid)) { // bala bala } else { if(walkHistory.length > 0) { var preGrid = walkHistory.pop(); return stepByStep(preGrid); } }}
  16. 16. grid-xgrid-1 grid grid+1 grid+x
  17. 17. function getGridContext(grid) { var p = 0, c, gc = []; // 判断上方格子是否可通过 p = grid - x; c = p > 0 && !grids[p]; c ? gc.push(p) : gc.push(-1); // 判断右方格子是否可通过 p = grid + 1; c = p % x != 0 && !grids[p]; c ? gc.push(p) : gc.push(-1);
  18. 18. // 判断下方格子是否可通过 p = grid + x; c = p < grids.length && !grids[p]; c ? gc.push(p) : gc.push(-1); // 判断左方格子是否可通过 p = grid - 1; c = grid % x != 0 && !grids[p]; c ? gc.push(p) : gc.push(-1); return gc;}
  19. 19. function hasNextGrid(grid) { var gc = getGridContext(grid); if(gc.join(‘,’) !== ‘-1,-1,-1,-1’){ return true; } return false;}
  20. 20. 设计地图第三条,如果遇到了叉路口,观察一下是 否还有没有走过的通道。有,就任选一条 通道往前走。
  21. 21. // In stepByStep(): hasNextGrid() === truevar gc = getGridContext(grid), nextGrid, ngc = [], r;for(var i = 0; i < 4; i++) { if(gc[i] !== -1) { ngc.push(i); }}r = Math.floor(Math.random() * ngc.length);nextGrid = gc[ngc[r]];… // TODO: Mark FunctionwalkHistory.push(grid);return nextGrid;
  22. 22. (0001=1) (t,r,b,l) t/r/b/l:0 or 1 1111=8|4|2|1=15(1000=8) 0011=2|1=3 (0010=2) … (0100=4)
  23. 23. 0 1 2 3 4 45 6 7 8 910 11 12 13 14 315 16 17 18 1920 21 22 23 24 8 grids[4] = 8 stepByStep(4) [-1,-1,9,3] grids[3] = 2 grids[3] = 2|4= 6 stepByStep(3) [-1,-1,8,2] grids[8] = 1
  24. 24. switch (ngc[r]) { case 0: grids[grid] |= 1; grids[nextGrid] |= 4; break; case 1: grids[grid] |= 2; grids[nextGrid] |= 8; break; case 2: grids[grid] |= 4; grids[nextGrid] |= 1; break; case 3: grids[grid] |= 8; grids[nextGrid] |= 2; break;}
  25. 25. 设计地图第四条,重复第二条和第三条所说的走法, 直到找到出口为止。第五条,如果要把迷宫所有地方都搜查到, 即凡是没有做记号的通道都要走一遍。
  26. 26. function walk(grid) { while (getNextGrid() != -1) { grid = stepByStep(grid); if(grid === undefined) { break; } }}
  27. 27. function getNextGrid() { for (var i = 0, l = grids.length; i < l; i ++) { if (!grids[i]) { return i; } return -1; }}
  28. 28. ctx.fillStyle = ‘rgb(65, 60, 50)’;ctx.fillRect(50, 50, 35, 20);ctx.strokeStyle = ‘rgb(65, 60, 50)’;ctx.strokeRect(100, 100, 30, 30); 50 100 ctx.fillRect(x,y,w,h) 50 100
  29. 29. function drawMap(parentNode) { var canvas = document.createElement("canvas"), w, h, cxt, v, l, t; w = gridWidth * x; h = gridHeight * y; canvas.setAttribute("width", w); canvas.setAttribute("height", h); parentNode.appendChild(canvas); ctx = canvas.getContext("2d"); ctx.fillStyle = "#f5f5f5"; ctx.fillRect(0, 0, w, h);
  30. 30. ctx.strokeStyle = "#aaa"; ctx.strokeRect(0, 0, w, h); for(var i = 0, len = grids.length; i < len; i++) { v = grids[i]; l = gridWidth * (i%x); t = gridHeight * Math.floor(i/x); // TODO: Draw grid border function drawBorder(ctx, l, t , v); }}
  31. 31. ctx.strokeStyle = ‘rgb(65, 60, 50)’;ctx.beginPath();ctx.moveTo(50, 50);ctx.lineTo(100, 100);ctx.stroke(); 50 100 50 100
  32. 32. 0000 0001 0010 0011 0 1 2 30100 0101 0110 0111 4 5 6 7
  33. 33. 1000 1001 1010 1011 8 9 10 111100 1101 1110 111112 13 14 15
  34. 34. function drawBorder(ctx, l, t, v) { var x1 = l, y1 = t, x2 = x1 + gridWidth, y2 = y1 + gridHeight; ctx.strokeStyle = "#aaa"; var doDraw = function (x1, y1, x2, y2) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.closePath(); }
  35. 35. // 格子上方丌通过,画出上边 if (!(v & 1)) { doDraw(x1, y1, x2, y1); } // 格子右方丌通过,画出右边 if (!(v & 2)) { doDraw(x2, y1, x2, y2); } // 格子下方丌通过,画出下边 if (!(v & 4)) { doDraw(x1, y2, x2, y2); } // 格子左方丌通过,画出左边 if (!(v & 8)) { doDraw(x1, y1, x1, y2); }}
  36. 36. Draw a line from (1, 0) to (1, 3)
  37. 37. /** * if you try to draw a line from (1, 0) to (1, 3), * the browser will draw a line covering 0.5 screen pixels * on either side of x=1. * The screen can’t display half a pixel, * so it expands the line to cover a total of two pixels. * * Ref: http://diveintohtml5.org/canvas.html */
  38. 38. Draw a line from (1.5, 0) to (1.5, 3)
  39. 39. var doDraw = function (x1, y1, x2, y2) { x1 = x1 + 0.5; y1 = y1 + 0.5; x2 = x2 + 0.5; y2 = y2 + 0.5; r = Math.floor(Math.random() * ngc.length); ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.closePath();}
  40. 40. 分解交互 Event: up/left/down/right Behavior: stepBystep Fun: setMood
  41. 41. 分解交互: 兼容性的 addEvent / stopEvent 注册事件 / 事件函数的处理
  42. 42. function addEvent(obj, type, fn) { if (obj.attachEvent) { obj[e+type+fn] = fn; obj[type+fn] = function(){ obj[e+type+fn](window.event); } obj.attachEvent(on+type, obj[type+fn]); } else { obj.addEventListener(type, fn, false); }}
  43. 43. function stopEvent(event){ if (event.cancelBubble) { event.cancelBubble = true; event.returnValue = false; } else { event.preventDefault(); event.stopPropagation(); } return false;}
  44. 44. 分解交互: 兼容性的 addEvent / stopEvent 注册事件 / 事件函数的处理
  45. 45. keydown keypress keyup
  46. 46. var handler = function(event) { var code = event.which || event.keyCode; // {37:left, 38:up, 39:right,40:down‘} switch(code) { // TODO: _stepByStep function case 38: stepByStep(0); break; case 39: stepByStep(1); break; case 40: stepByStep(2); break; case 37: stepByStep(3); break; } stopEvent(event);};addEvent(document, keydown, handler);
  47. 47. 分解交互: 类似亍 Map 的 StepByStep
  48. 48. var grid = 0, isfinished = false;function stepByStep(d){ var v = maze.grids[grid], gridWidth = maze.width, gridHeight = maze.height, x = maze.x; if(isfinished) return; // TODO: Judgment …}
  49. 49. (0001=1) (t,r,b,l) t/r/b/l:0 or 1 1111=8|4|2|1=15(1000=8) 0011=2|1=3 (0010=2) … (0100=4)
  50. 50. grid-xgrid-1 grid grid+1 grid+x
  51. 51. if (v & Math.pow(2, d)) { // check grid switch (d) { case 0: grid = grid - x; moveTo(grid); break; case 1: grid = grid + 1; moveTo(grid); break; case 2: grid = grid + x; moveTo(grid); break; case 3: grid = grid - 1; moveTo(grid); break; }}
  52. 52. function moveTo(grid) { var l = gridWidth * (grid % x), t = gridHeight * Math.floor(grid / x); // set oLostor’s position oLostor.style.left = l + px; oLostor.style.top = t + px; // gird value is change v = grids[grid];
  53. 53. if (i === grids.length - 1) { //end isfinished = true; //bala bala } else if(i != 0 && [1,2,4,8].indexOf(v)>-1){ // impasse //bala bala } else if (i === 0) { //start //bala bala } else { //bala bala }};
  54. 54. 分解交互: 提示信息:setMoodAnd so on …
  55. 55. var _moods = { default: ‚./joyful.gif‚, depressed: ‚./depressed.gif‚, lucky: ‚./lucky.gif‚, surprise: ‚./surprise.gif"}
  56. 56. var _setMood = function (mood) { if (_moods[0] === mood) return; if (_moods[mood]) { _moods[0] = mood; oImg.src = _moods[mood]; }}var oImg = doc.createElement("img"),oImg.src = _moods.default;_moods[0] = ‚default‛;oLostor.appendChild(oImg);
  57. 57. //In _moveTo Functionif (i === grids.length - 1) { //end isfinished = true; _setMood("lucky");} else if (i != 0&&[1,2,4,8].indexOf(v)>-1){ // impasse _setMood("depressed");} else if (i === 0) { //start _setMood("surprise");} else { _setMood(‚default");}
  58. 58. 分解交互: 信息提示:setMood And so on …
  59. 59. 分解交互: 动画 标记已走路径 最短路径 Niubility 排行榜
  60. 60. http://oldj.net/article/javascript-maze/http://oldj.net/article/javascript-maze-2/http://diveintohtml5.org/canvas.htmlhttp://ejohn.org/projects/flexible- javascript-events/

×