{"id":7985,"date":"2024-10-31T07:47:33","date_gmt":"2024-10-31T14:47:33","guid":{"rendered":"https:\/\/cloudfour.com\/?p=7985"},"modified":"2024-10-31T07:47:34","modified_gmt":"2024-10-31T14:47:34","slug":"generating-random-mazes-with-javascript","status":"publish","type":"post","link":"https:\/\/cloudfour.com\/thinks\/generating-random-mazes-with-javascript\/","title":{"rendered":"Generating Random Mazes with JavaScript"},"content":{"rendered":"\n<p>I didn&#8217;t get a chance to hit the pumpkin patch this year, so I missed out on seeing any corn mazes. To make up for it, I decided to make some mazes of my own! Being a programmer, I over-engineered it and built a random maze generator!<\/p>\n\n\n\n<p>Here&#8217;s an example maze that it generated:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"1024\" height=\"580\" src=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image-1024x580.jpg\" alt=\"A rectangular maze on a gradient backdrop\" class=\"wp-image-8006\" srcset=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image-1024x580.jpg 1024w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image-300x170.jpg 300w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image-768x435.jpg 768w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image-1536x871.jpg 1536w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image.jpg 1600w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I made <a href=\"https:\/\/codepen.io\/phebert\/pen\/zYgqwVe\">a CodePen<\/a> that animates the creation of random mazes so you can watch how the algorithm works. (Click &#8220;Randomize&#8221; to generate a new maze.)<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_zYgqwVe\" src=\"\/\/codepen.io\/anon\/embed\/zYgqwVe?height=450&amp;theme-id=light&amp;slug-hash=zYgqwVe&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed zYgqwVe\" title=\"CodePen Embed zYgqwVe\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Defining Constraints<\/h2>\n\n\n\n<p>There are lots of different types of mazes and ways to make them. Before I started writing code, I thought through what I wanted from a maze and what would keep me from going off the deep end of complexity. There were some basic constraints I landed on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The maze would be rectangular. Hexagonal and circular mazes are cool, but they seem much more complicated!<\/li>\n\n\n\n<li>There would be one single path through the maze.<\/li>\n\n\n\n<li>The path would always go from the left edge to the right edge. <\/li>\n\n\n\n<li>It should be possible to visit every square in the maze. <\/li>\n<\/ul>\n\n\n\n<p>With these constraints in mind, I was ready to start planning.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Game Plan<\/h2>\n\n\n\n<p>I broke down the maze creation into three steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a rectangular grid.<\/li>\n\n\n\n<li>Find a path from the left side of the grid to the right.<\/li>\n\n\n\n<li>Branch off the main path to fill in the rest of the grid.<\/li>\n<\/ol>\n\n\n\n<p>Some quick sketches on graph paper can help understand these steps without writing any code:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img width=\"600\" height=\"580\" src=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-empty2.jpg\" alt=\"A square drawn on graph paper\" class=\"wp-image-7990\" style=\"width:256px;height:auto\" srcset=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-empty2.jpg 600w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-empty2-300x290.jpg 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img width=\"600\" height=\"590\" src=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-path1.jpg\" alt=\"The same square with a zig-zagging line draw through it.\" class=\"wp-image-7991\" srcset=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-path1.jpg 600w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-path1-300x295.jpg 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img width=\"600\" height=\"579\" src=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-finished1.jpg\" alt=\"The same square and line. In a lighter color, additional lines branch off the main line filling the square\" class=\"wp-image-7989\" srcset=\"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-finished1.jpg 600w, https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/maze-finished1-300x290.jpg 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n<\/div><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Create a Rectangular Grid<\/h2>\n\n\n\n<p>First off, we need to make some choices about our grid. For now, we&#8217;ll start with a ten-by-ten grid. We&#8217;ll store these choices as variables to reuse them and make them easy to change later:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> gridHeight = <span class=\"hljs-number\">10<\/span>;\n<span class=\"hljs-keyword\">const<\/span> gridWidth = <span class=\"hljs-number\">10<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Finding a Path Through the Maze<\/h2>\n\n\n\n<p>Now, we need to find a path from the left edge to the right edge. We can store the path as a series of points with X and Y coordinates. Here&#8217;s what the main path from the drawing above would look like:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> mainPath = &#91;\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">-1<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">7<\/span>},\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">7<\/span>},\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">6<\/span>},\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">5<\/span>},\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">5<\/span>},\n  <span class=\"hljs-comment\">\/* ... more points ... *\/<\/span>\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">9<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">1<\/span>},\n  {<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">10<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">1<\/span>}\n];\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>We&#8217;ll need to pick a starting point for our maze. We&#8217;ll choose a random Y coordinate and add two points using it: one off the left edge of our grid and one just inside the grid:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> { randomInt } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'https:\/\/unpkg.com\/randomness-helpers@0.0.1\/dist\/index.js'<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">mainPathStartPoints<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> yStart = randomInt(<span class=\"hljs-number\">0<\/span>, gridHeight - <span class=\"hljs-number\">1<\/span>);\n  \n  <span class=\"hljs-keyword\">return<\/span> &#91;\n    {\n      <span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">-1<\/span>, \n      <span class=\"hljs-attr\">y<\/span>: yStart\n    },\n    {\n      <span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">0<\/span>, \n      <span class=\"hljs-attr\">y<\/span>: yStart\n    }\n  ]\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p class=\"has-gray-lighter-background-color has-background\">Note: In this article, I&#8217;ll use some helpers from an npm package I made called <a href=\"https:\/\/www.npmjs.com\/package\/randomness-helpers\">randomness-helpers<\/a> to help with repetitive tasks like picking random integers and array items. If you&#8217;re curious about how they work, check out <a href=\"https:\/\/github.com\/Paul-Hebert\/randomness-helpers\">the GitHub Repo<\/a>.<\/p>\n\n\n\n<p>From here, we need to build the rest of our path. First, we&#8217;ll write a function that takes a point and returns a random point on the grid next to it:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> { randomItemInArray } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'https:\/\/unpkg.com\/randomness-helpers@0.0.1\/dist\/index.js'<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">findNextPoint<\/span>(<span class=\"hljs-params\">point<\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Build an array of adjacent points<\/span>\n  <span class=\"hljs-keyword\">const<\/span> potentialPoints = &#91;];\n  \n  <span class=\"hljs-comment\">\/\/ If \"up\" is within our grid add it as a potential point<\/span>\n  <span class=\"hljs-keyword\">if<\/span>(point.y - <span class=\"hljs-number\">1<\/span> &gt; <span class=\"hljs-number\">0<\/span>) {\n    potentialPoints.push({\n      <span class=\"hljs-attr\">y<\/span>: point.y - <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">x<\/span>: point.x\n    });\n  }\n  \n  <span class=\"hljs-comment\">\/\/ If \"down\" is within our grid, add it as a potential point<\/span>\n  <span class=\"hljs-keyword\">if<\/span>(point.y + <span class=\"hljs-number\">1<\/span> &lt; gridHeight) {\n    potentialPoints.push({\n      <span class=\"hljs-attr\">y<\/span>: point.y + <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">x<\/span>: point.x\n    });\n  }\n  \n  <span class=\"hljs-comment\">\/\/ If \"left\" is within our grid, add it as a potential point<\/span>\n  <span class=\"hljs-keyword\">if<\/span>(point.x - <span class=\"hljs-number\">1<\/span> &gt; <span class=\"hljs-number\">0<\/span>) {\n    potentialPoints.push({\n      <span class=\"hljs-attr\">y<\/span>: point.y,\n      <span class=\"hljs-attr\">x<\/span>: point.x - <span class=\"hljs-number\">1<\/span>\n    });\n  }\n  \n  <span class=\"hljs-comment\">\/\/ If \"right\" is within our grid, add it as a potential point<\/span>\n  <span class=\"hljs-keyword\">if<\/span>(point.x + <span class=\"hljs-number\">1<\/span> &lt; gridWidth) {\n    potentialPoints.push({\n      <span class=\"hljs-attr\">y<\/span>: point.y,\n      <span class=\"hljs-attr\">x<\/span>: point.x + <span class=\"hljs-number\">1<\/span>\n    });\n  }\n\n  <span class=\"hljs-comment\">\/\/ Randomly pick one of these points to add to our path  <\/span>\n  <span class=\"hljs-keyword\">return<\/span> randomItemInArray(potentialPoints);\n}\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>We can call this function repeatedly to build our path. We&#8217;ll stop calling it when we&#8217;ve reached the right end of our grid. Then, we&#8217;ll add a final point off the right edge.<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getMainPathPoints<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> mainPathPoints = mainPathStartPoints();\n\n  <span class=\"hljs-comment\">\/\/ Keep adding points until our last point is on the right edge<\/span>\n  <span class=\"hljs-keyword\">while<\/span>(mainPathPoints.at(<span class=\"hljs-number\">-1<\/span>).x &gt; gridWidth - <span class=\"hljs-number\">1<\/span>) {\n    mainPathPoints.push(findNextPoint(mainPathPoints.at(<span class=\"hljs-number\">-1<\/span>)));\n  }\n\n  <span class=\"hljs-comment\">\/\/ Add another point with the same Y coordinate as our final point, <\/span>\n  <span class=\"hljs-comment\">\/\/ but off the right edge.<\/span>\n  mainPathPoints.push({\n    <span class=\"hljs-attr\">x<\/span>: gridWidth,\n    <span class=\"hljs-attr\">y<\/span>: mainPathPoints.at(<span class=\"hljs-number\">-1<\/span>).y\n  });\n}\n\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p class=\"has-gray-lighter-background-color has-background\">In the code sample above we&#8217;re using<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array\/at#return_the_last_value_of_an_array\"> the array method <code>at<\/code><\/a> to get the final point in our array.<\/p>\n\n\n\n<p>We&#8217;re getting close, but there&#8217;s a major problem with our logic. Can you spot it? (Click &#8220;Draw Path&#8221; below to see it in action.)<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_KKOyQwV\" src=\"\/\/codepen.io\/anon\/embed\/KKOyQwV?height=450&amp;theme-id=1&amp;slug-hash=KKOyQwV&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed KKOyQwV\" title=\"CodePen Embed KKOyQwV\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Our path keeps doubling back on itself. There are a few problems with this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>There are way too many paths through the maze! It&#8217;s too easy!<\/li>\n\n\n\n<li>It takes a <em>looong<\/em> time to get to the right edge.<\/li>\n\n\n\n<li>We don&#8217;t know which cells we&#8217;ve filled, so we don&#8217;t know how to draw the rest of the maze.<\/li>\n\n\n\n<li>(This also causes an issue with how our maze is drawn, but that&#8217;s a separate problem that will fix itself when we fix the others.)<\/li>\n<\/ul>\n\n\n\n<p>We can fix all of these issues by keeping track of which cells are already visited and not visiting them again. We can make a 2-dimensional array in JavaScript, with a <code>0<\/code> representing each empty cell. To mark a cell as occupied, we can flip that <code>0<\/code> to a <code>1<\/code>. <\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> gridData = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Array<\/span>(gridHeight).fill().map(\n  <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Array<\/span>(gridWidth).fill(<span class=\"hljs-number\">0<\/span>)\n);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>That gives us an array that looks like this:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">&#91;\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n]\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>We&#8217;ll add another function to mark a specific grid cell as &#8220;taken&#8221; by flipping the 0 to a 1:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">markPointAsTaken<\/span>(<span class=\"hljs-params\">point, value = <span class=\"hljs-number\">1<\/span><\/span>) <\/span>{\n  gridData&#91;point.y]&#91;point.x] = value;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>Here&#8217;s what the grid array would look like after drawing a path through the maze and marking points as taken:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">&#91;\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>],\n  &#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>],\n]\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>We&#8217;ll add another helper function to check if a specific grid cell is on the grid and empty. (We&#8217;ll update the <code>findNextPoint<\/code> function we wrote above to only return available points.)<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">isCellEmpty<\/span>(<span class=\"hljs-params\">point<\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Check if the cell is off our grid<\/span>\n  <span class=\"hljs-keyword\">if<\/span>(\n    point.x &lt; <span class=\"hljs-number\">0<\/span> || \n    point.x &gt;= gridWidth || \n    point.y &lt; <span class=\"hljs-number\">0<\/span> || \n    point.y &gt;= gridHeight || \n  ) {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>;\n  }\n\n  <span class=\"hljs-comment\">\/\/ Check the grid cell and see if it's empty.<\/span>\n  <span class=\"hljs-keyword\">return<\/span> gridData&#91;y]&#91;x] === <span class=\"hljs-number\">0<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>Now, we&#8217;ve got all the tools we need to find a path across the grid. But there&#8217;s one decision we still need to make: what do we do if we get &#8220;stuck?&#8221; (If all of the adjacent grid cells are taken, where do we go?)<\/p>\n\n\n\n<p>The simplest solution is to just give up and restart our path if we get stuck. Click &#8220;Draw Path&#8221; a few times below to  see this in action:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_jOgaZKy\" src=\"\/\/codepen.io\/anon\/embed\/jOgaZKy?height=450&amp;theme-id=1&amp;slug-hash=jOgaZKy&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed jOgaZKy\" title=\"CodePen Embed jOgaZKy\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>This works well enough, but if we try to use this logic for a larger grid, it can take a long time to find a valid path:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_ExqbQOp\" src=\"\/\/codepen.io\/anon\/embed\/ExqbQOp?height=450&amp;theme-id=1&amp;slug-hash=ExqbQOp&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed ExqbQOp\" title=\"CodePen Embed ExqbQOp\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>We can make our logic a little smarter by trying to &#8220;back out&#8221; a few steps if we get stuck and continue from another position. This has a better chance of finding a path through the grid with fewer tries. (We&#8217;ll still start over if we get really stuck.) Try out the demo below to see this option in action.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_xxvPYmy\" src=\"\/\/codepen.io\/anon\/embed\/xxvPYmy?height=450&amp;theme-id=1&amp;slug-hash=xxvPYmy&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed xxvPYmy\" title=\"CodePen Embed xxvPYmy\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"has-gray-lighter-background-color has-background\">The code for this is tricky to explain so I&#8217;m not going to dig into it here, but feel free to check out <a href=\"https:\/\/codepen.io\/phebert\/pen\/xxvPYmy?editors=0010\" data-type=\"link\" data-id=\"https:\/\/codepen.io\/phebert\/pen\/xxvPYmy?editors=0010\">the CodePen<\/a> to see how it works<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Branch off the main path to fill in the rest of the grid.<\/h2>\n\n\n\n<p>Whew, that was a lot! But we&#8217;re almost there. Now that we have our main path, we just need to fill in the grid. We&#8217;ll add a helper function that will tell us whether every cell in the grid is occupied or not:<\/p>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">mazeComplete<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{ \n  <span class=\"hljs-comment\">\/\/ Flatten our array of arrays into a single array.<\/span>\n  <span class=\"hljs-comment\">\/\/ Then check whether they're all set to 1.<\/span>\n  <span class=\"hljs-keyword\">return<\/span> gridData.flat().every(<span class=\"hljs-function\"><span class=\"hljs-params\">cell<\/span> =&gt;<\/span> cell === <span class=\"hljs-number\">1<\/span>);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>Now, we can keep looping until the grid is full. We&#8217;ll create an array of additional paths that we&#8217;ll populate with points. In each loop we&#8217;ll take a few steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Iterate over every path, adding another point to the path if possible<\/li>\n\n\n\n<li>Iterate over all of the points in all of our paths, randomly adding new paths at some of those points<\/li>\n\n\n\n<li>Keep going until the grid is full!<\/li>\n<\/ol>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><pre aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> { randomChance } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'https:\/\/unpkg.com\/randomness-helpers@0.0.1\/dist\/index.js'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> otherPaths = &#91;];\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">buildOtherPaths<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">while<\/span>(!mazeComplete()) { \n    <span class=\"hljs-comment\">\/\/ Add some more paths<\/span>\n    addMorePaths();\n  \n    <span class=\"hljs-comment\">\/\/ Iterate over our paths<\/span>\n    otherPaths.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">path<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-comment\">\/\/ Try and add another point to each path<\/span>\n      <span class=\"hljs-keyword\">const<\/span> nextPoint = findNextPoint(path.at(<span class=\"hljs-number\">-1<\/span>));\n      \n      <span class=\"hljs-keyword\">if<\/span>(nextPoint) {\n        path.push(nextPoint);\n        markPointAsTaken(nextPoint);\n      }\n    });\n  }\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">addMorePaths<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Iterate over all of the cells in the grid<\/span>\n  gridData.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">row, y<\/span>) =&gt;<\/span> {\n    row.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">cell, x<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-comment\">\/\/ If a cell is occupied, set a 10% chance to start a new path from that cell<\/span>\n      <span class=\"hljs-keyword\">if<\/span>(cell &amp;&amp; randomChance(<span class=\"hljs-number\">0.1<\/span>)) {\n        otherPaths.push(&#91;{\n          y,\n          x,\n        }]);\n      }\n    })\n  })\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<\/div>\n\n\n\n<p>The code above will keep adding new paths and growing those paths until the entire grid is full. That gives us a complete maze! Click &#8220;Randomize&#8221; to generate new mazes!<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_zYgqwVe\" src=\"\/\/codepen.io\/anon\/embed\/zYgqwVe?height=450&amp;theme-id=1&amp;slug-hash=zYgqwVe&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed zYgqwVe\" title=\"CodePen Embed zYgqwVe\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>From this starting point, you can draw the maze using your technique of choice. I&#8217;m using SVG because it works well for vector shapes like this, but canvas or even a CSS Grid would also work.<\/p>\n\n\n\n<p>This was a fun experiment. We thought through how mazes work and explored different JavaScript techniques for drawing them. Check out <a href=\"https:\/\/codepen.io\/phebert\/pen\/zYgqwVe\">the CodePen<\/a> for the full code. Feel free to play with this and create your own mazes. Try changing the size and color of the maze, or think through how similar techniques could be used to draw circular or hexagonal mazes!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I didn&#8217;t get a chance to hit the pumpkin patch this year, so I missed out on seeing any corn mazes. To make up for it, I decided to make some mazes of my own! Being a programmer, I over-engineered it and built a random maze generator!<\/p>\n","protected":false},"author":19,"featured_media":8006,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":true,"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[235,256,240,7,300],"tags":[],"class_list":["post-7985","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-design","category-development","category-javascript","category-philosophy","category-svg"],"acf":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/cloudfour.com\/wp-content\/uploads\/2024\/10\/sharing-image.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/posts\/7985","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/comments?post=7985"}],"version-history":[{"count":0,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/posts\/7985\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/media\/8006"}],"wp:attachment":[{"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/media?parent=7985"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/categories?post=7985"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudfour.com\/wp-json\/wp\/v2\/tags?post=7985"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}