Added Maze.ipynb
This commit is contained in:
456
ipynb/Maze.ipynb
Normal file
456
ipynb/Maze.ipynb
Normal file
@@ -0,0 +1,456 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div style=\"text-align: right\">Peter Norvig<br>13 March 2018</div> \n",
|
||||
"\n",
|
||||
"# Maze Generation\n",
|
||||
"\n",
|
||||
"Let's make some mazes! I'm thinking of mazes like this one, which is a rectangular grid of squares, with walls on some of the sides of squares, and openings on other sides:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"The main constraint is that there should be a path from entrance to exit, and it should be ***fun*** to solve the maze with pencil, paper, and brain power—not too easy, but also not impossible. \n",
|
||||
"\n",
|
||||
"As I think about how to model a maze on the computer, it seems like a **graph** is the right model: the nodes of\n",
|
||||
"the graph are the squares of the grid, and the edges of the graph are the openings between adjacent squares. So what properties of a graph make a good maze?\n",
|
||||
"- There must be a path from entrance to exit.\n",
|
||||
"- There must not be too such many paths; maybe it is best if there is only one. \n",
|
||||
"- Probably the graph should be *singly connected*—there shouldn't be islands of squares that are unreachable from the start. And maybe we want exactly one path between any two squares.\n",
|
||||
"- The path should have many twists; it would be too easy if it was mostly straight.\n",
|
||||
"\n",
|
||||
"I know that a **tree** has all these properties except the last one. So my goal has become: *Superimpose a tree over the grid, covering every square, and make sure the paths are twisty.* Here's how I'll do it:\n",
|
||||
"\n",
|
||||
"- Start with a grid with no edges (every square is surrounded by walls on all sides). \n",
|
||||
"- Add edges (that is, knock down walls) for the entrance at upper left and exit at lower right.\n",
|
||||
"- Place the root of the tree in some square.\n",
|
||||
"- Then repeat until the tree covers the whole grid:\n",
|
||||
" * Select some node already in the tree.\n",
|
||||
" * Randomly select a neighbor that hasn't been added to the tree yet.\n",
|
||||
" * Add an edge (knock down the wall) from the node to the neighbor.\n",
|
||||
" \n",
|
||||
"In the example below, the root, `A`, has been placed in the upper-left corner, and two branches,\n",
|
||||
"`A-B-C-D` and `A-b-c-d`, have been randomly chosen (well, not actually random; they are starting to create the same maze as in the diagram above):\n",
|
||||
"\n",
|
||||
" o o--o--o--o--o--o--o--o--o--o\n",
|
||||
" | A b c| | | | | | | |\n",
|
||||
" o o--o o--o--o--o--o--o--o--o\n",
|
||||
" | B| | d| | | | | | | |\n",
|
||||
" o o--o--o--o--o--o--o--o--o--o\n",
|
||||
" | C D| | | | | | | | |\n",
|
||||
" o--o--o--o--o--o--o--o--o--o--o\n",
|
||||
" | | | | | | | | | | |\n",
|
||||
" o--o--o--o--o--o--o--o--o--o--o\n",
|
||||
" | | | | | | | | | | |\n",
|
||||
" o--o--o--o--o--o--o--o--o--o o\n",
|
||||
" \n",
|
||||
"Next I select node `d` and extend it to `e` (at which point there are no available neighbors, so `e` will not be selected in the future), and then I select `D` and extend from there all the way to `N`, at each step selecting the node I just added:\n",
|
||||
"\n",
|
||||
" o o--o--o--o--o--o--o--o--o--o\n",
|
||||
" | A b c| | | | | | | |\n",
|
||||
" o o--o o--o--o--o--o--o--o--o\n",
|
||||
" | B| e d| | N| | | | | |\n",
|
||||
" o o--o--o--o o--o--o--o--o--o\n",
|
||||
" | C D| | | M| | | | | |\n",
|
||||
" o--o o--o--o o--o--o--o--o--o\n",
|
||||
" | F E| | K L| | | | | |\n",
|
||||
" o o--o--o o--o--o--o--o--o--o\n",
|
||||
" | G H I J| | | | | | |\n",
|
||||
" o--o--o--o--o--o--o--o--o--o o\n",
|
||||
" \n",
|
||||
"Continue like this until every square in the grid has been added to the tree. \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"## Implementing Random Trees\n",
|
||||
"\n",
|
||||
"I'll make the following implementation choices:\n",
|
||||
"\n",
|
||||
"- A tree will be represented as a list of edges.\n",
|
||||
"- An `Edge` is a tuple of two nodes. I'll keep them sorted so that `Edge(A, B)` is the same as `Edge(B, A)`.\n",
|
||||
"- A node in a tree can be anything: a number, a letter, a square, ...\n",
|
||||
"- The algorithm for `random_tree(nodes, neighbors, pop)` is as follows:\n",
|
||||
" * We will keep track of three collections:\n",
|
||||
" - `tree`: a list of edges that constitutes the tree.\n",
|
||||
" - `nodes`: the set of nodes that have not yet been added to the tree, but will be.\n",
|
||||
" - `frontier`: a queue of nodes in the tree that are eligible to have an edge added.\n",
|
||||
" * On each iteration:\n",
|
||||
" - Use `pop` to pick a `node` from the frontier, and find the neighbors that are not already in the tree.\n",
|
||||
" - If there are any neighbors, randomly pick one (`nbr`), add `Edge(node, nbr)` to `tree`, remove the\n",
|
||||
" neighbor from `nodes`, and keep both the node and the neighbor on the frontier. If there are no neighbors,\n",
|
||||
" drop the node from the frontier.\n",
|
||||
" * When no `nodes` remain, return `tree`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import random\n",
|
||||
"from collections import deque, namedtuple\n",
|
||||
"\n",
|
||||
"def Edge(node1, node2): return tuple(sorted([node1, node2]))\n",
|
||||
"\n",
|
||||
"def random_tree(nodes: set, neighbors: callable, pop: callable) -> [Edge]:\n",
|
||||
" \"Repeat: pop a node and add Edge(node, nbr) until all nodes have been added to tree.\"\n",
|
||||
" tree = []\n",
|
||||
" root = nodes.pop()\n",
|
||||
" frontier = deque([root])\n",
|
||||
" while nodes:\n",
|
||||
" node = pop(frontier)\n",
|
||||
" nbrs = neighbors(node) & nodes\n",
|
||||
" if nbrs:\n",
|
||||
" nbr = random.choice(list(nbrs))\n",
|
||||
" tree.append(Edge(node, nbr))\n",
|
||||
" nodes.remove(nbr)\n",
|
||||
" frontier.extend([node, nbr])\n",
|
||||
" return tree"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Implementing Random Mazes\n",
|
||||
"\n",
|
||||
"Now let's use `random_tree` to implement `random_maze`. Some more choices:\n",
|
||||
"\n",
|
||||
"* A `Maze` is a named tuple with three fields: the `width` and `height` of the grid, and a list of `edges` between squares. \n",
|
||||
"* A square is denoted by an `(x, y)` tuple of integer coordinates.\n",
|
||||
"* The function `neighbors4` gives the four surrounding squares."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Maze = namedtuple('Maze', 'width, height, edges')\n",
|
||||
"\n",
|
||||
"def neighbors4(square):\n",
|
||||
" \"The 4 neighbors of an (x, y) square.\"\n",
|
||||
" (x, y) = square\n",
|
||||
" return {(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)}\n",
|
||||
"\n",
|
||||
"def squares(width, height): \n",
|
||||
" \"All squares in a grid of these dimensions.\"\n",
|
||||
" return {(x, y) for x in range(width) for y in range(height)}\n",
|
||||
"\n",
|
||||
"def random_maze(width, height, pop=deque.pop):\n",
|
||||
" \"Use random_tree to generate a random maze.\"\n",
|
||||
" nodes = squares(width, height)\n",
|
||||
" tree = random_tree(nodes, neighbors4, pop)\n",
|
||||
" return Maze(width, height, tree)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Maze(width=10, height=5, edges=[((6, 3), (7, 3)), ((6, 2), (6, 3)), ((5, 2), (6, 2)), ((5, 1), (5, 2)), ((5, 1), (6, 1)), ((6, 0), (6, 1)), ((6, 0), (7, 0)), ((7, 0), (8, 0)), ((8, 0), (8, 1)), ((8, 1), (9, 1)), ((9, 0), (9, 1)), ((9, 1), (9, 2)), ((9, 2), (9, 3)), ((9, 3), (9, 4)), ((8, 4), (9, 4)), ((7, 4), (8, 4)), ((6, 4), (7, 4)), ((5, 4), (6, 4)), ((5, 3), (5, 4)), ((4, 3), (5, 3)), ((4, 2), (4, 3)), ((3, 2), (4, 2)), ((3, 2), (3, 3)), ((3, 3), (3, 4)), ((3, 4), (4, 4)), ((2, 4), (3, 4)), ((2, 3), (2, 4)), ((1, 3), (2, 3)), ((1, 2), (1, 3)), ((1, 2), (2, 2)), ((2, 1), (2, 2)), ((2, 1), (3, 1)), ((3, 1), (4, 1)), ((4, 0), (4, 1)), ((3, 0), (4, 0)), ((2, 0), (3, 0)), ((1, 0), (2, 0)), ((1, 0), (1, 1)), ((0, 1), (1, 1)), ((0, 1), (0, 2)), ((0, 2), (0, 3)), ((0, 3), (0, 4)), ((0, 4), (1, 4)), ((0, 0), (0, 1)), ((4, 0), (5, 0)), ((8, 3), (8, 4)), ((8, 2), (8, 3)), ((7, 2), (8, 2)), ((7, 1), (7, 2))])"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"random_maze(10,5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"That's not very pretty to look at. I'm going to need a way to visualize a maze.\n",
|
||||
"\n",
|
||||
"# Printing a maze"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"o o--o--o--o--o--o--o--o--o--o\n",
|
||||
"| | | |\n",
|
||||
"o o o--o o--o--o o o--o o\n",
|
||||
"| | | | | | |\n",
|
||||
"o o--o o--o o o--o--o o o\n",
|
||||
"| | | | | |\n",
|
||||
"o o--o o--o o o--o--o--o o\n",
|
||||
"| | | | | | |\n",
|
||||
"o o o--o o--o o o--o o--o\n",
|
||||
"| | | | |\n",
|
||||
"o--o--o--o--o--o--o--o--o--o o\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def print_maze(maze, dot='o', lin='--', bar='|', sp=' '):\n",
|
||||
" \"Print maze in ASCII.\"\n",
|
||||
" exit = Edge((maze.width-1, maze.height-1), (maze.width-1, maze.height))\n",
|
||||
" edges = set(maze.edges) | {exit}\n",
|
||||
" print(dot + sp + lin.join(dot * maze.width)) # Top line, including entrance\n",
|
||||
" def vert_wall(x, y): return (' ' if Edge((x, y), (x+1, y)) in edges else bar)\n",
|
||||
" def horz_wall(x, y): return (sp if Edge((x, y), (x, y+1)) in edges else lin)\n",
|
||||
" for y in range(maze.height):\n",
|
||||
" print(bar + cat(sp + vert_wall(x, y) for x in range(maze.width)))\n",
|
||||
" print(dot + cat(horz_wall(x, y) + dot for x in range(maze.width)))\n",
|
||||
" \n",
|
||||
"cat = ''.join\n",
|
||||
" \n",
|
||||
"print_maze(random_maze(10, 5))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"*Much better!* But can I do better still?\n",
|
||||
"\n",
|
||||
"# Plotting a maze\n",
|
||||
"\n",
|
||||
"I'll use `matplotlib` to plot lines where the edges aren't:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"def plot_maze(maze):\n",
|
||||
" \"Plot a maze by drawing lines between adjacent squares, except for pairs in maze.edges\"\n",
|
||||
" plt.figure(figsize=(8, 4))\n",
|
||||
" plt.axis('off')\n",
|
||||
" plt.axes().set_aspect('equal', 'datalim')\n",
|
||||
" plt.gca().invert_yaxis()\n",
|
||||
" w, h = maze.width, maze.height\n",
|
||||
" exits = {Edge((0, 0), (0, -1)), Edge((w-1, h-1), (w-1, h))}\n",
|
||||
" edges = set(maze.edges) | exits\n",
|
||||
" for sq in squares(w, h):\n",
|
||||
" for nbr in neighbors4(sq):\n",
|
||||
" if Edge(sq, nbr) not in edges:\n",
|
||||
" plot_wall(sq, nbr)\n",
|
||||
" plt.show()\n",
|
||||
"\n",
|
||||
"def plot_wall(s1, s2):\n",
|
||||
" \"Plot a thick black line between squares s1 and s2.\"\n",
|
||||
" (x1, y1), (x2, y2) = s1, s2\n",
|
||||
" if x1 == x2: # horizontal wall\n",
|
||||
" y = max(y1, y2)\n",
|
||||
" X, Y = [x1, x1+1], [y, y]\n",
|
||||
" else: # vertical wall\n",
|
||||
" x = max(x1, x2)\n",
|
||||
" X, Y = [x, x], [y1, y1+1]\n",
|
||||
" plt.plot(X, Y, 'k-', linewidth=4.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's compare the two visualization functions:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAAD8CAYAAAAyun5JAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAABOlJREFUeJzt3cFqHDsQQFErzP//cmWb5xdihnGupMk5O+8Kdbcvogxe\nM/MBAPx9P3YPAAD/CtEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6\nABARXQCIiC4ARB67B/iTtdZ//tnvzKxds/zO5/kAuEvdFTddAIiILgBERBcAIkfvdE932o75Vrft\n7k+b7wbOkFPs/lscN10AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqIL\nABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAERE\nFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIo/dA9xsrTW7Z3jWzKzdM/D9Pr+LnvPz\nbvyeT+c9/D83XQCIiC4AREQXACJ2ui+4YV9xw57qhnPkNTc+4xtn5nxuugAQEV0AiIguAEREFwAi\nogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4A\nREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFd\nAIiILgBERBcAIo/dAzxjrTW7Z/iTmVm7Z/jK6WfI9/Cc39Ntz/WG34k1N10AiIguAEREFwAiV+10\n7Qde5wyfd9se7ePjvOf8+QxPm+9Wp53jjd9KzU0XACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIgu\nAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABAR\nXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgMhj9wA3W2vN\nrz/PzNo1y82cIyf4/B7C3+CmCwAR0QWAiOgCQMROF75gx/xvOvG5n753PvHMTuOmCwAR0QWAiOgC\nQER0ASAiugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHR\nBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQEV0AiIguAEREFwAi\nogsAEdEFgIjoAkBEdAEg8tg9wDtZa83uGd6Bc4Q7+Xa/5qYLABHRBYCI6AJAxE73BTOzds/wDpwj\nJ/Aevu6GM9y9d3bTBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQ\nEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroAEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQB\nICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0ASAiugAQeewe4Blrrdk9A/A63/L3OP0cZ2bt\nnuE0broAEBFdAIiILgBE1szRKwEAeBtuugAQEV0AiIguAEREFwAiogsAEdEFgIjoAkBEdAEgIroA\nEBFdAIiILgBERBcAIqILABHRBYCI6AJARHQBICK6ABARXQCIiC4AREQXACKiCwAR0QWAiOgCQER0\nASAiugAQEV0AiIguAEREFwAiPwEaFX4D8XiUAwAAAABJRU5ErkJggg==\n",
|
||||
"text/plain": [
|
||||
"<matplotlib.figure.Figure at 0x10252dda0>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"o o--o--o--o--o--o--o--o--o--o\n",
|
||||
"| | | | |\n",
|
||||
"o o--o o o o o o--o--o o\n",
|
||||
"| | | | | |\n",
|
||||
"o--o o--o--o o--o--o o--o o\n",
|
||||
"| | | | | | | |\n",
|
||||
"o o o o o o o o--o o o\n",
|
||||
"| | | | | | | | |\n",
|
||||
"o o--o o--o--o o o o o--o\n",
|
||||
"| | | |\n",
|
||||
"o--o--o--o--o--o--o--o--o--o o\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"M = random_maze(10, 5)\n",
|
||||
"plot_maze(M) \n",
|
||||
"print_maze(M)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# `pop` strategies\n",
|
||||
"\n",
|
||||
"Now I want to compare how the maze varies based on theree different choices for the `pop` parameter. \n",
|
||||
"\n",
|
||||
"(1) The default is `deque.pop`\n",
|
||||
"which means that the tree is created **depth-first**; we always select the `node` at the end of the `frontier`, so the tree follows a single branch along a randomly-twisted path until the path doubles back on itself and there are no more neighbors; at that point we select the most recent square for which there are neighbors:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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\nEOI/KTjgmW23yvYAAAAASUVORK5CYII=\n",
|
||||
"text/plain": [
|
||||
"<matplotlib.figure.Figure at 0x107f12c50>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"plot_maze(random_maze(40, 20, deque.pop))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The maze with `deque.pop` looks pretty good. Reminds me of those [cyber brain](https://www.vectorstock.com/royalty-free-vector/cyber-brain-vector-3071965) images.\n",
|
||||
"\n",
|
||||
"(2) An alternative is `queue.popleft`, which creates the maze roughly **breadth-first**—we start at some root square , add an edge to it, and from then on we always select first a parent edge before we select a child edge. The net result is a design that appears to radiate out in concentric layers from the root (which is chosen by `random_tree` and is not necessarily the top-left square; below it looks like the root is in the upper-left quadrant). "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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\nbQAI8R8QCUbq2O5sJQAAAABJRU5ErkJggg==\n",
|
||||
"text/plain": [
|
||||
"<matplotlib.figure.Figure at 0x10bf13048>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"plot_maze(random_maze(40, 20, deque.popleft))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `deque.popleft` maze is interesting as a design, but to me it doesn't work well as a maze.\n",
|
||||
"\n",
|
||||
"(3) We can select a cell at random by shuffling the frontier before popping an element off of it:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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\nGwBCCG0ACPEfA+iaR4R5UDIAAAAASUVORK5CYII=\n",
|
||||
"text/plain": [
|
||||
"<matplotlib.figure.Figure at 0x10da3d748>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def poprandom(seq):\n",
|
||||
" \"Shuffle a mutable sequence (deque or list) and then pop an element.\"\n",
|
||||
" random.shuffle(seq)\n",
|
||||
" return seq.pop()\n",
|
||||
"\n",
|
||||
"plot_maze(random_maze(40, 20, poprandom))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This is an interesting compromise: it has some structure, but still works nicely as a maze, in my opinion.\n",
|
||||
"\n",
|
||||
"What other variations can you come up with to generate interesting mazes?"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
Reference in New Issue
Block a user