Advertisement
Guest User

Untitled

a guest
Mar 30th, 2020
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.43 KB | None | 0 0
  1. "use strict";
  2.  
  3. let c = document.getElementById("myCanvas");
  4. let context = c.getContext("2d");
  5.  
  6. const WIDTH = 500;
  7. const HEIGHT = 500;
  8.  
  9. // const CELL_WIDTH = 25;
  10. // const CELL_HEIGHT = 25;
  11. const CELL_HEIGHT_WIDTH = 25;
  12. const CELL_WIDTH = CELL_HEIGHT_WIDTH;
  13. const CELL_HEIGHT = CELL_HEIGHT_WIDTH;
  14.  
  15. const MAX_CELL_X = WIDTH / CELL_WIDTH;
  16. const MAX_CELL_Y = HEIGHT / CELL_HEIGHT;
  17.  
  18. const TOP = "TOP";
  19. const BOTTOM = "BOTTOM";
  20. const RIGHT = "RIGHT";
  21. const LEFT = "LEFT";
  22.  
  23. let cells = [];
  24. let path = [];
  25. let finishedPath = [];
  26.  
  27. function sleep(ms) {
  28. return new Promise(resolve => setTimeout(resolve, ms));
  29. }
  30.  
  31. function shuffle(array) {
  32. for (let i = array.length - 1; i > 0; i--) {
  33. const j = Math.floor(Math.random() * (i + 1));
  34. [array[i], array[j]] = [array[j], array[i]];
  35. }
  36. return array;
  37. }
  38.  
  39. function directionDeltaPos(direction) {
  40. switch (direction) {
  41. case TOP:
  42. return { dx: 0, dy: -1 };
  43. case BOTTOM:
  44. return { dx: 0, dy: 1 };
  45. case RIGHT:
  46. return { dx: 1, dy: 0 };
  47. case LEFT:
  48. return { dx: -1, dy: 0 };
  49. default:
  50. return null;
  51. }
  52. }
  53.  
  54. function oppositeDirection(direction) {
  55. switch (direction) {
  56. case TOP:
  57. return BOTTOM;
  58. case BOTTOM:
  59. return TOP;
  60. case RIGHT:
  61. return LEFT;
  62. case LEFT:
  63. return RIGHT;
  64. default:
  65. return null;
  66. }
  67. }
  68.  
  69. function checkSizeConstraints(x, y) {
  70. return x >= 0 && y >= 0 && x < MAX_CELL_X && y < MAX_CELL_Y;
  71. }
  72.  
  73. class Wall {
  74. constructor(direction) {
  75. this.direction = direction;
  76. this.exists = true;
  77. }
  78.  
  79. draw(screenX, screenY) {
  80. if (this.exists) {
  81. switch (this.direction) {
  82. case TOP:
  83. context.moveTo(screenX, screenY);
  84. context.lineTo(screenX + CELL_WIDTH, screenY);
  85. break;
  86. case BOTTOM:
  87. context.moveTo(screenX, screenY + CELL_HEIGHT);
  88. context.lineTo(screenX + CELL_WIDTH, screenY + CELL_HEIGHT);
  89. break;
  90. case RIGHT:
  91. context.moveTo(screenX + CELL_WIDTH, screenY);
  92. context.lineTo(screenX + CELL_WIDTH, screenY + CELL_HEIGHT);
  93. break;
  94. case LEFT:
  95. context.moveTo(screenX, screenY);
  96. context.lineTo(screenX, screenY + CELL_HEIGHT);
  97. break;
  98. default:
  99. console.error(`Wall draw() error - x: ${screenX} y: ${screenY}`);
  100. break;
  101. }
  102. context.strokeStyle = "black";
  103. context.stroke();
  104. }
  105. }
  106. }
  107.  
  108. class Cell {
  109. walls = [new Wall(TOP), new Wall(RIGHT), new Wall(BOTTOM), new Wall(LEFT)];
  110.  
  111. constructor(x, y) {
  112. this.start = false;
  113. this.finish = false;
  114. this.visited = false;
  115. this.x = x;
  116. this.y = y;
  117. this.screenX = x * CELL_WIDTH;
  118. this.screenY = y * CELL_HEIGHT;
  119. }
  120.  
  121. disableWall(direction) {
  122. let wall = this.walls.find(wall => wall.direction === direction);
  123.  
  124. wall.exists = false;
  125. }
  126.  
  127. findWall(direction) {
  128. let wall = this.walls.find(wall => wall.direction === direction);
  129. return wall;
  130. }
  131.  
  132. draw() {
  133. if (this.visited) {
  134. context.fillStyle = "#00FFFF";
  135. } else {
  136. context.fillStyle = "#FFFFFF";
  137. }
  138.  
  139. if (this.start) context.fillStyle = "#0088FF";
  140. if (this.finish) context.fillStyle = "#8800FF";
  141.  
  142. context.fillRect(this.screenX, this.screenY, CELL_WIDTH, CELL_HEIGHT);
  143.  
  144. this.walls.map(wall => {
  145. if (wall.exists) {
  146. wall.draw(this.screenX, this.screenY);
  147. }
  148. });
  149. }
  150. }
  151.  
  152. function init() {
  153. for (let i = 0; i < MAX_CELL_X; i++) {
  154. for (let j = 0; j < MAX_CELL_Y; j++) {
  155. cells.push(new Cell(i, j));
  156. }
  157. }
  158. }
  159.  
  160. function drawCells(cells) {
  161. cells.map(cell => cell.draw());
  162. }
  163.  
  164. async function animateCells(cells) {
  165. for (let i = 0; i < cells.length; i++) {
  166. await sleep(10);
  167. cells[i].draw();
  168. }
  169. }
  170.  
  171. function resetCellsVisitedAttr() {
  172. cells.map(cell => (cell.visited = false));
  173. }
  174.  
  175. function generateMaze(cell) {
  176. cell.visited = true;
  177.  
  178. const directions = [TOP, BOTTOM, RIGHT, LEFT];
  179.  
  180. shuffle(directions);
  181.  
  182. directions.map(direction => {
  183. const nextX = cell.x + directionDeltaPos(direction).dx;
  184. const nextY = cell.y + directionDeltaPos(direction).dy;
  185.  
  186. let nextCell = cells.find(cell => cell.x === nextX && cell.y === nextY);
  187.  
  188. if (checkSizeConstraints(nextX, nextY) && nextCell.visited === false) {
  189. cell.disableWall(direction);
  190. nextCell.disableWall(oppositeDirection(direction));
  191.  
  192. generateMaze(nextCell);
  193. }
  194. });
  195. }
  196.  
  197. function solveMaze(cell) {
  198. cell.visited = true;
  199.  
  200. if (cell.finish) {
  201. finishedPath = [...path];
  202. return;
  203. }
  204.  
  205. const directions = [TOP, BOTTOM, RIGHT, LEFT];
  206. shuffle(directions);
  207.  
  208. directions.map(direction => {
  209. const nextX = cell.x + directionDeltaPos(direction).dx;
  210. const nextY = cell.y + directionDeltaPos(direction).dy;
  211. let nextCell = cells.find(cell => cell.x === nextX && cell.y === nextY);
  212. const wall = cell.findWall(direction);
  213.  
  214. if (
  215. checkSizeConstraints(nextX, nextY) &&
  216. !wall.exists &&
  217. !nextCell.visited
  218. ) {
  219. path.push(cell);
  220. solveMaze(nextCell);
  221. path.pop();
  222. }
  223. });
  224. }
  225.  
  226. function maze() {
  227. init();
  228. cells[0].start = true;
  229. cells[cells.length - 1].finish = true;
  230. generateMaze(cells.find(cell => cell.start));
  231.  
  232. resetCellsVisitedAttr();
  233. drawCells(cells);
  234. solveMaze(cells.find(cell => cell.start));
  235. animateCells(finishedPath);
  236. }
  237.  
  238. maze();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement