Maze generation: Difference between revisions

m
→‎{{header|POV-Ray}}: Explanation added about iterative approach
m (→‎{{header|POV-Ray}}: Explanation added about iterative approach)
(40 intermediate revisions by 14 users not shown)
Line 20:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F make_maze(w = 16, h = 8)
V vis = [[0] * w [+] [1]] * h [+] [[1] * (w + 1)]
V ver = [[‘| ’] * w [+] [String(‘|’)]] * h [+] [[String]()]
Line 49:
R s
 
print(make_maze())</langsyntaxhighlight>
 
{{out}}
Line 74:
=={{header|Action!}}==
Action! language does not support recursion. Therefore an iterative approach with a stack has been proposed.
<langsyntaxhighlight Actionlang="action!">DEFINE TOP="0"
DEFINE RIGHT="1"
DEFINE BOTTOM="2"
Line 188:
DO UNTIL CH#$FF OD
CH=$FF
RETURN</langsyntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Maze_generation.png Screenshot from Atari 8-bit computer]
Line 196:
{{works with|GNAT}}
mazes.ads:
<langsyntaxhighlight Adalang="ada">generic
Height : Positive;
Width : Positive;
Line 222:
type Maze_Grid is array (Height_Type, Width_Type) of Cells;
 
end Mazes;</langsyntaxhighlight>
mazes.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
Line 397:
end Put;
end Mazes;
</syntaxhighlight>
</lang>
Example main.adb:
<langsyntaxhighlight Adalang="ada">with Mazes;
procedure Main is
package Small_Mazes is new Mazes (Height => 8, Width => 11);
Line 406:
Small_Mazes.Initialize (My_Maze);
Small_Mazes.Put (My_Maze);
end Main;</langsyntaxhighlight>
{{out}}
<pre>Starting generation at 3 x 7
Line 428:
 
=={{header|Aime}}==
<langsyntaxhighlight lang="aime">grid_maze(data b, integer N)
{
data d;
Line 501:
 
0;
}</langsyntaxhighlight>
{{out}}
<pre>+---+---+---+---+---+---+---+---+---+---+
Line 527:
 
=={{header|APL}}==
<syntaxhighlight lang="apl">
<lang APL>
This example shows how to use GNU APL scripting.
 
Line 633:
doMaze 9 9
)OFF
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 660:
=={{header|AutoHotkey}}==
For a challenge, this maze generation is entirely string based. That is to say, all operations including the wall removal and retrieval of cell states are done on the output string.
<langsyntaxhighlight AHKlang="ahk">; Initially build the board
Width := 11
Height := 8
Line 724:
If (A_Index = Y)
return SubStr(A_LoopField, x, 1)
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>+-+-+-+-+-+-+-+-+-+-+-+
Line 750:
=={{header|AWK}}==
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
 
# Remember: AWK is 1-based, for better or worse.
Line 937:
srand(t);
}
</syntaxhighlight>
</lang>
 
Example output:
Line 987:
==={{header|QB64}}===
This implementation was written using QB64. It should also be compatible with Qbasic, as it uses no QB64-exclusive features.
<langsyntaxhighlight lang="qb64">OPTION BASE 0
RANDOMIZE TIMER
 
Line 1,054:
 
REM wait
DO: LOOP WHILE INKEY$ = ""</langsyntaxhighlight>
 
{{out}}
Line 1,081:
 
==={{header|BASIC256}}===
<langsyntaxhighlight lang="basic256">global size_x, size_y
size_x = 25
size_y = 15
Line 1,144:
print
next i
end subroutine</langsyntaxhighlight>
 
{{out}}
Line 1,182:
{{works with|Windows NT}}
 
<langsyntaxhighlight lang="dos">:amaze Rows Cols [wall char]
:: A stack-less, iterative, depth-first maze generator in native WinNT batch.
:: Rows and Cols must each be >1 and Rows*Cols cannot exceed 2096.
Line 1,276:
ENDLOCAL
EXIT /B 0
</syntaxhighlight>
</lang>
 
Example output:
Line 1,307:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> MazeWidth% = 11
MazeHeight% = 9
MazeCell% = 50
Line 1,348:
ENDIF
NEXT
ENDPROC</langsyntaxhighlight>
'''Sample output:'''
<br>
Line 1,358:
Also note that this requires an interpreter with working read-write memory support, which is suprisingly rare in online implementations. Padding the code page with extra blank lines or spaces can sometimes help. Using smaller dimensions might also be preferable, especially on slower implementations.
<langsyntaxhighlight lang="befunge">45*28*10p00p020p030p006p0>20g30g00g*+::"P"%\"P"/6+gv>$\1v@v1::\+g02+*g00+g03-\<
0_ 1!%4+1\-\0!::\-\2%2:p<pv0<< v0p+6/"P"\%"P":\+4%4<^<v-<$>+2%\1-*20g+\1+4%::v^
#| +2%\1-*30g+\1\40g1-:v0+v2?1#<v>+:00g%!55+*>:#0>#,_^>:!|>\#%"P"v#:*+*g00g0<>1
Line 1,364:
0#$g#<1#<-#<`#<\#<0#<^#_^/>#1+#4<>"P"%\"P"/6+g:2%^!>,1-:#v_$55+^|$$ "JH" $$>#<0
::"P"%\"P"/6+g40p\40g+\:#^"P"%#\<^ ::$_,#!0#:<*"|"<^," _"<:g000 <> /6+g4/2%+#^_
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,387:
=={{header|C}}==
Generation/solver in one. Requires UTF8 locale and unicode capable console. If your console font line-drawing chars are single width, define DOUBLE_SPACE to 0.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 1,532:
 
return 0;
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>┌───┬─────┬─────────┬───────┬───┐
Line 1,551:
│     │  ╰┄┄┄╯│  ╰┄┄┄┄┄┄┄╯│  ╰┄┄│
└─────┴───────┴───────────┴─────┘</pre>
 
Alternative approach
<pre>
 
/* --------------------------------------------------- */
/* I include this alternative method for consideration */
/* --------------------------------------------------- */
/* in file define’s.h */
/* I came to ansi-C after Algol-60 etc and these five pretend to be language tokens */
/* I do like ansi-C but the syntax is rather 'scruffy' */
 
#define then
#define endif
#define endwhile
#define endfor
#define endswitch
#ifndef BOOL
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif
#define MAZE_SIZE_X 16
#define MAZE_SIZE_Y 16
/* in file GlobalDefs.h */
unsigned char box[MAZE_SIZE_X+1][MAZE_SIZE_Y+1];
int allowed[4];
int x_[4] = { 0, 1, 0, -1 };
int y_[4] = { 1, 0, -1, 0 };
/* in file DesignMaze.c */
 
/* This produces an enclosed rectangular maze. There will only be one path
between any (x1,y1) and (x2,y2). The code to add doors is not included here */
/* When I write code for me I put an explanation before a function to remind me
what I was thinking at the time – I have retained those explanations to self here */
/* Also note at the end of the path_check() function the return relies on the
weak type checking of ansi-C and (int)TRUE == 1 */
/* By making the recursive functions static, this is a hint to the compiler to
simplify the stack code instructions as the compiler knows everything that it needs
from the current source file and does not need to involve the linker.
Implementation specific #pragma could also be used */
 
/**************************************************************************/
/* */
/* The maze is made up of a set of boxes (it is a rectangular maze). */
/* Each box has a description of the four sides, each side can be :- */
/* (a) a solid wall */
/* (b) a gap */
/* (c) a door */
/* */
/* A side has an opening bit set for gaps and doors, this makes the */
/* movement checking easier. */
/* */
/* For any opening there are four bits corresponding to the four sides:- */
/* Bit 0 is set if Northwards movement is allowed */
/* Bit 1 is set if Eastwards movement is allowed */
/* Bit 2 is set if Southwards movement is allowed */
/* Bit 3 is set if Westwards movement is allowed */
/* */
/* For a door there are four bits corresponding to the four sides:- */
/* Bit 4 is set if North has a door, unset if North has a gap */
/* Bit 5 is set if East has a door, unset if East has a gap */
/* Bit 6 is set if South has a door, unset if South has a gap */
/* Bit 7 is set if West has a door, unset if West has a gap */
/* */
/**************************************************************************/
/**************************************************************************/
/********************************** path_check ****************************/
/**************************************************************************/
/* */
/* This sets: */
/* allowed[0] to TRUE if a path could be extended to the 'North' */
/* allowed[1] to TRUE if a path could be extended to the 'East' */
/* allowed[2] to TRUE if a path could be extended to the 'South' */
/* allowed[3] to TRUE if a path could be extended to the 'West' */
/* */
/* A path could be extended in a given direction if it does not go */
/* beyond the edge of the maze (there are no gaps in the surrounding */
/* walls), or the adjacent box has not already been visited */
/* (i.e. it contains 0). */
/* */
/* It also returns non-zero if there is at least one potential path */
/* which can be extended. */
/* */
/**************************************************************************/
static int path_check(int x, int y)
{
if ( y > (MAZE_SIZE_Y-1) )
then { allowed[0] = FALSE; }
else { allowed[0] = (box[x ][y+1] == 0) ? TRUE : FALSE; }
endif
if ( x > (MAZE_SIZE_X-1) )
then { allowed[1] = FALSE; }
else { allowed[1] = (box[x+1][y ] == 0) ? TRUE : FALSE; }
endif
if ( y < 2 )
then { allowed[2] = FALSE; }
else { allowed[2] = (box[x ][y-1] == 0) ? TRUE : FALSE; }
endif
if ( x < 2 )
then { allowed[3] = FALSE; }
else { allowed[3] = (box[x-1][y ] == 0) ? TRUE : FALSE; }
endif
return (allowed[0]+allowed[1]+allowed[2]+allowed[3]);
} /* end of 'path_check' */
/**************************************************************************/
/********************************** design_maze ***************************/
/**************************************************************************/
/* */
/* This is a recursive routine to produce a random rectangular maze */
/* with only one route between any two points. */
/* For each box reached, a 'wall' is knocked through to an adjacent */
/* box if that box has not previously been reached (i.e. no walls */
/* knocked out). */
/* For the adjacent box the adjacent wall is also knocked out. */
/* Then the routine is called again from the adjacent box. */
/* If there are no adjacent boxes which have not already been reached */
/* then the routine returns to the previous call. */
/* */
/**************************************************************************/
static void design_maze(int x, int y)
{
int direction;
while ( path_check(x,y) > 0)
{
do { direction = rand()%4; } while ( allowed[direction]==FALSE );
box[x ][y ] |= (1 << direction );
box[x+x_[direction]][y+y_[direction]] |= (1 << ((direction+2) % 4) );
design_maze( x+x_[direction] , y+y_[direction] );
} endwhile
} /* end of 'design_maze()' */
</pre>
 
=={{header|C sharp|C#}}==
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Diagnostics;
Line 1,678 ⟶ 1,831:
}
}
</syntaxhighlight>
</lang>
Sample output:
<pre>
Line 1,726 ⟶ 1,879:
=={{header|C++}}==
[[File:maze_cpp.png|300px]]
<langsyntaxhighlight lang="cpp">
#include <windows.h>
#include <iostream>
Line 1,996 ⟶ 2,149:
}
//--------------------------------------------------------------------------------------------------
</syntaxhighlight>
</lang>
 
=={{header|Chapel}}==
<syntaxhighlight lang="chapel">
use Random;
 
config const rows: int = 9;
config const cols: int = 16;
if rows < 1 || cols < 1 {
writeln("Maze must be at least 1x1 in size.");
exit(1);
}
 
enum direction {N = 1, E = 2, S = 3, W = 4};
 
record Cell {
var spaces: [direction.N .. direction.W] bool;
var visited: bool;
}
 
const dirs = [
((-1, 0), direction.N, direction.S), // ((rowDir, colDir), myWall, neighbourWall)
((0, 1), direction.E, direction.W),
((1, 0), direction.S, direction.N),
((0, -1), direction.W, direction.E)
];
 
var maze: [1..rows, 1..cols] Cell;
var startingCell = (choose(maze.dim(0)), choose(maze.dim(1)));
 
checkCell(maze, startingCell);
displayMaze(maze);
 
proc checkCell(ref maze, cell) {
maze[cell].visited = true;
for dir in permute(dirs) {
var (offset, thisDir, neighbourDir) = dir;
var neighbour = cell + offset;
if maze.domain.contains(neighbour) && !maze[neighbour].visited {
maze[cell].spaces[thisDir] = true;
maze[neighbour].spaces[neighbourDir] = true;
checkCell(maze, neighbour);
}
}
}
 
proc displayMaze(maze) {
for row in maze.dim(0) {
for col in maze.dim(1) {
write(if maze[row, col].spaces[direction.N] then "+ " else "+---");
}
writeln("+");
for col in maze.dim(1) {
write(if maze[row, col].spaces[direction.W] then " " else "| ");
}
writeln("|");
}
write("+---" * maze.dim(1).size);
writeln("+");
}
</syntaxhighlight>
 
{{out}}
 
<pre>
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | |
+ + + +---+---+ + +---+ + +---+---+ +---+---+ +
| | | | | | | | | |
+ +---+---+---+ +---+---+ + +---+ +---+ + + +---+
| | | | | | |
+---+---+ + +---+---+---+---+---+---+ + +---+---+---+ +
| | | | | | |
+ + +---+---+---+---+---+ + +---+---+---+---+---+ + +
| | | | | | | |
+ +---+---+---+ + +---+---+ + +---+ +---+ +---+ +
| | | | | | | | | | |
+ +---+ + +---+---+ + +---+---+ + + +---+ + +
| | | | | | | | |
+---+---+---+ + + + +---+---+ + +---+---+ +---+ +
| | | | | | | | | | | |
+ + +---+ + + +---+ + + +---+ + +---+ + +
| | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
</pre>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns maze.core
(:require [clojure.set :refer [intersection
select]]
Line 2,092 ⟶ 2,329:
 
;;Task
(println (maze->str (create-random-maze 10 10)))</langsyntaxhighlight>
 
{{out}}
Line 2,120 ⟶ 2,357:
Written in Commodore BASIC V2 and tested on Commodore 64 and Commodore 128 hardware. (It will also run on the unexpanded Commodore VIC-20 if you reduce the maze size to 8x8.) Due to stack size limitations in the operating systems, this solution eschews recursive subroutine calls. Recursion is accomplished by conditional branching within the maze build routine and the use of an array-based stack for data elements.
 
<langsyntaxhighlight BASIClang="basic">100 MS=10:REM MAZE SIZE
110 DIM S(MS+1,MS+1):REM SOUTH WALLS
120 DIM W(MS+1,MS+1):REM WEST WALLS
Line 2,178 ⟶ 2,415:
670 NEXT R
680 REM PRINT#4:CLOSE 4:REM CLOSE PRINTER DEVICE
690 RETURN</langsyntaxhighlight>
{{out|Output example (for 10x10 maze)}}
<pre>+--+--+--+--+--+--+--+--+--+--+
Line 2,205 ⟶ 2,442:
 
The remove-wall function has been written so as to be as close as possible to the specification. The walls are made from a single unicode character, specified by the block keyword, e. g. (maze 20 6 :block #\X). The BOX_DRAWINGS_LIGHT_DIAGONAL_CROSS character is used by default.
<langsyntaxhighlight lang="lisp">(defun shuffle (list) ;; Z not uniform
(sort list '> :key (lambda(x) (random 1.0))))
 
Line 2,234 ⟶ 2,471:
do (princ (aref maze i j))))))
 
(draw-maze 20 6)</langsyntaxhighlight>
{{out}}
<pre>
Line 2,252 ⟶ 2,489:
 
Another solution using unicode line drawing chars. Assumes they are single width on console. Code pretty horribly unreadable.
<langsyntaxhighlight lang="lisp">(setf *random-state* (make-random-state t))
 
(defun 2d-array (w h)
Line 2,308 ⟶ 2,545:
(show))))
 
(make-maze 20 20)</langsyntaxhighlight>
{{out}}
<pre>┼───┴───┼───┴───┴───┼───┴───┴───┼
Line 2,329 ⟶ 2,566:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">void main() @safe {
import std.stdio, std.algorithm, std.range, std.random;
 
Line 2,350 ⟶ 2,587:
foreach (const a, const b; hor.zip(ver ~ []))
join(a ~ "+\n" ~ b).writeln;
}</langsyntaxhighlight>
{{out}}
<pre>+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
Line 2,374 ⟶ 2,611:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+</pre>
=={{header|Delphi}}==
<langsyntaxhighlight Pascallang="pascal">program MazeGen_Rosetta;
 
{$APPTYPE CONSOLE}
Line 2,485 ⟶ 2,722:
Main;
 
end.</langsyntaxhighlight>
{{out}}
<pre>+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
Line 2,514 ⟶ 2,751:
=={{header|EasyLang}}==
 
[https://easylang.dev/show/#cod=fZPLbqswEIb3fopP6iYXQe20WWTBkyB0RLE5sRrsCHJ6e/rKxBhQq7MB/P8z9vibYbBfhgJ1FI6CAzuGoOxRog26lDyycWTI/LgVF+PoygrHDiceEC918/q39/+cRkoprr1vGM7+/U9XfxlycgE0F1P34aP1PTZsy80T9wo6YFu60lYUyKgAHxRsLBlqS+c1brY+F5a2b0ur8RffczqdZqnzb4YPdrRktDxy4HO5miN709xo2aHy4/SO7niX8TFcjLkic6lELnzbDmUovEThyBSbzG2pAp6RR3eHcfXDBKQrr35Id028wkKnrQ488Uy15PaM9u/u5lGxJE1BXztt3Q07abanYKxKl7qaAIdvCnRpV8hDVfuQU419qZ1OYpiGyVigXKcsurW4Z0peo8uFcTr4xX2CQvsio/rVrGbmP6MS50Sldqxi3TrqkJbhxN8kMlwY+J+Wi9acNR53jn/KBF4dY1zIWRtixnK+N/4OIJGLPPYFTuQiURDzTHwD Run it]
[https://easylang.online/apps/_r_maze0.html Run it]
 
<syntaxhighlight>
<lang>size = 20
size = 15
n = 2 * size + 1
endpos = n * n - 2
startpos = n + 1
#
f = 100 / (n - 0.5)
len m[] n * n
#
background 000
funcproc show_maze . .
clear
for i range= 1 to len m[]
if m[i] = 0
x = (i - 1) mod n
y = (i - 1) div n
color 777999
move x * f - f / 2 y * f - f / 2
rect f * 1.5 f * 1.5
.
.
sleep 0.00101
.
offs[] = [ 1 n -1 (-n) ]
#
brdc[] = [ n - 2 -1 1 -1 ]
proc m_maze pos . .
brdr[] = [ -1 n - 2 -1 1 ]
m[pos] = 0
#
show_maze
func m_maze pos . .
m d[pos] = 0[ 1 2 3 4 ]
for i = 4 downto 1
call show_maze
d[] = [ 0 1d 2= 3randint ]i
for i = 3 downtodir = 0offs[d[d]]
d[d] = random (d[i + 1)]
if m[pos + dir] = d1 and m[dpos + 2 * dir] = 1
d m[dpos + dir] = d[i]0
r = m_maze pos div+ 2 * ndir
c = pos mod n.
.
posn = pos + 2 * offs[dir]
if c <> brdc[dir] and r <> brdr[dir] and m[posn] <> 0
posn = pos + 2 * offs[dir]
m[(pos + posn) div 2] = 0
call m_maze posn
.
.
.
endpos = n * n - 1
func make_maze . .
proc make_maze . .
for i range len m[]
for m[i] = 1 to len m[]
m[i] = 1
.
.
call m_maze startpos
m[endpos] for i = 01 to n
m[i] = 2
m[n * i] = 2
m[n * i - n + 1] = 2
m[n * n - n + i] = 2
.
h = 2 * randint 15 - n + n * 2 * randint 15
m_maze h
m[endpos] = 0
endpos += n
.
call make_maze
call show_maze</lang>
</syntaxhighlight>
 
=={{header|EDSAC order code}}==
In this EDSAC solution there is no recursion or stack. As suggested in the Wikipedia article "Maze generation algorithm", backtracking information is stored in the maze itself. The code below leaves enough storage for a 24x24 maze, but the demo maze is cut down to 12x8 to save space.
<syntaxhighlight lang="edsac">
[Maze generation for Rosetta Code.
EDSAC program, Initial Orders 2.
 
Cells, horizontal walls, and vertical walls are numbered
as shown in this example:
+---1---+---2---+---3---+
| | | |
1 1 2 2 3 3 4 N
| | | | |
+---5---+---6---+---7---+ W---+---E
| | | | |
5 5 6 6 7 7 8 S
| | | |
+---9---+--10---+--11---+
 
Maze data are held in a single 1-based array of 17-bit values
(equivalent to an array of records in a high-level language).
In each entry, fields for cells and walls are as shown in "Flags" below.]
 
[Arrange the storage]
T51K P56F [G parameter: generator for pseudo-random numbers]
T47K P100F [M parameter: main routine + dependent subroutines]
T45K P398F [H parameter: storage for maze]
[The following once-only code can be overwritten by the maze data.]
T46K P398F [N parameter: library subroutine R4 to read data]
T50K P420F [X parameter: code executed at start-up only]
 
[=========== Executed at start-up, then overwritten ================]
E25K TX GK
[Enter with acc = 0]
[0] A@ GN [read 35-bit maze width into 0D]
AF TM [load and store width, assuming high word = 0]
[4] A4@ GN AF T1M [same for height]
[Initialize linear congruential generator for pseudo-random numbers]
[8] A8@ GN [read seed for LCG into 0D]
AD T4D [pass seed to LCG in 4D]
[12] A12@ GG [initialize LCG]
[Choose a random cell in the maze, for use later.]
[Also update storage of width and height.]
T4D [clear the whole of 4D, including sandwich bit]
AM U4F [load 17-bit width, pass to LCG as 35-bit value]
LD A2F TM [width to address field, add 1, store]
[20] A20@ G1G [call LCG, 0D := random in 0..(width - 1)]
AF T3M [save random to temporary store]
T4D A1M U4F [pass height of maze to LCG]
LD A2F T1M [height to address field, add 1, store]
[30] A30@ G1G [call LCG, 0D := random in 0..(height - 1)]
HF VM L64F L32F [acc := random*(width + 1)]
A3M LD A2F [add first random, shift to address, add 1]
T3M [save random index for use below]
HM V1M L64F L32F T2M [store (width+1)*(height+1)]
E65M [jump to main routine with acc = 0]
 
[================ Main routine ====================]
E25K TM GK
[Variables]
[0] PF [initially maze width; then (width + 1) in address field]
[1] PF [initially maze height; then (height + 1) in address field]
[List of up to four E orders to move N, S, W, E.]
[The first two are also used as temporary store at program start]
[2] PF
[3] PF PF PF
[6] TF [T order to store E order in list]
[Constants]
[7] T2@ [initial value of T order]
[8] TH [order to store into array{0}]
[9] AH [order to load from array{0}]
[10] C1H [order to collate with array{1};]
[also teleprinter colon in figures mode]
[11] MF [add to T order to make A order with same address]
[12] LF [add to T order to make C order with same address]
[Flags]
[13] K4096F [horizontal wall deleted, 10000 hex]
[14] IF [vertical wall deleted, 8000 hex]
[15] RF [no north neighbour, 4000 hex]
[16] WF [no south neighbour, 2000 hex]
[17] QF [no west neighbour, 1000 hex]
[18] P1024F [no east neighbour, 0800 hex]
[19] PD [cell visited, 0001 hex]
[20] V2047F [mask to clear visited bit]
[21] P1023F [mask to select EDSAC address field, which contains
index of previous cell for backtracking (0 if none).
[Teleprinter]
[22] #F [set figures mode]
[23] !F [space]
[24] @F [carriage return]
[25] &F [line feed]
 
[Subroutine called to set flag "no north neighbour" in cells along north edge,
similarly for east, south and west edges (order must be N, E, S, W).
Input: 4F = negative count of cells
5F = step in array index
6F = flag to be set]
[26] A3F T42@ [plant return link as usual]
A36@
G34@ [jump into middle of loop (since A < 0)]
[30] T4F [loop: update megative count]
A36@ A5F U36@
[34] S11@ T38@
[The following order initially refers to the NW corner cell.
First call leaves it referring to NE corner; second call to SE corner, etc.
Hence the need for calls to be in the order N, E, S, W.]
[36] A1H [planted; loaded as A1H]
A6F
[38] TF
A4F A2F [add 1 to negative count]
G30@ [if not yet 0, loop back]
[42] ZF
 
[Subroutine to test for unvisited neighbour of current cell in a given direction.
Input: 4F = E order to be added to list if unvisited neighbour is found
5F = step in array index to reach neighbour
6F = flag to test for no neighbour in this direction]
[43] A3F T64@ [plant return link as usual]
S6F H6F CH [if no neighbour then acc = 0, else acc < 0]
E64@ [exit if no neighbour]
TF A118@
A5F T55@
S19@ H19@
[55] CF E64@
TF A6@ U63@
A2F T6@
A4F [load jump to execute move]
[63] TF [store in list of moves]
[64] ZF [(planted) jump back to caller]
 
[Jump to here from once-only code, with acc = 0]
[Clear maze array]
[65] S2@
[66] TF [use 0F as loop counter]
[67] TH [planted, loaded as TH]
A67@ A2F T67@
AF A2F G66@
 
[Set flag "no north neighbour" in cells along northern edge]
S@ A2F T4F [count = width, pass in 4F]
A2F T5F [step in array index = 1, pass in 5F]
A15@ T6F [pass flag in 6F]
[81] A81@ G26@ [call subroutine to set flag]
 
[Repeat for east, south, west edges (must be in that order)]
S1@ A2F T4F A@ T5F A18@ T6F
[90] A90@ G26@
S@ A2F T4F S2F T5F A16@ T6F
[99] A99@ G26@
S1@ A2F T4F S@ T5F A17@ T6F
[108] A108@ G26@
 
[Start with the random cell chosen at program start (X parameter)]
A3@ A8@
[Loop: here acc = T order for current cell]
[112] U121@ [plant T order]
A12@ T118@ [make and plant C order, same address]
[Initialize storing in list of moves]
A7@ T6@
H20@
[118] CF A19@ [mark cell as visited]
UH [store flags of current cell in array{0} for easy access]
[121] TF [and also in the body of the array]
 
[If cell has unvisited North neighbour, add North to list of possible moves]
A177@ T4F
S@ T5F
A15@ T6F
[128] A128@ G43@
[Repeat for South, West, East neighbours]
A178@ T4F
A@ T5F
A16@ T6F
[136] A136@ G43@
A179@ T4F
S2F T5F
A17@ T6F
[144] A144@ G43@
A180@ T4F
A2F T5F
A18@ T6F
[152] A152@ G43@
 
[List now has 0..4 possible moves. If more than one, choose randomly.]
T4D [clear whole of 4D, including sandwich bit, for randomizer]
A6@ S7@ [address field := count of moves]
S2F G225@ [jump if none]
S2F G169@ [jump if one only]
RD A2F T4F [pass count, right-justified, to randomizer]
[164] A164@ G1G [0F := random value 0..(count - 1)]
AF LD E170@
[169] TF [only one move, must be at list{0}]
[170] A7@ A11@ T173@
[173] AF T176@
A121@ [common to all moves]
[176] EF [jump to move N,S,E, or W with acc = 0]
[177] E181@
[178] E190@
[179] E199@
[180] E208@
 
[Move North and delete horizontal wall]
[181] U186@ A11@ T184@
[184] AF A13@
[186] TF A121@ S@ E216@
 
[Move South and delete horizontal wall]
[190] A@ U196@ A11@ T194@
[194] AF A13@
[196] TF A196@ E216@
 
[Move West and delete vertical wall]
[199] U204@ A11@ T202@
[202] AF A14@
[204] TF A121@ S2F E216@
 
[Move East and delete vertical wall]
[208] A2F U214@ A11@ T212@
[212] AF A14@
[214] TF A214@
[fall through]
 
[Set index of current cell as previous to the new cell.
Here with T order for new cell in acc.]
[216] U222@ A11@ T221@
A121@ S8@
[221] AF
[222] TF
A222@ E112@
 
[No unvisited neighbour, backtrack if possible]
[225] TF [clear acc, needed]
H21@ CH [get index of previous cell (in address field)]
S2F [is it 0?]
G233@ [if so, maze is complete, jump to print]
A2F [restore]
A8@ [make T order]
E112@
 
[Print the maze created above]
[233] O22@ [set teleprinter to figures mode]
TF [clear acc]
S1@ T5F
[Outer 'loop and a half' with 5F as negative counter.
h + 1 rows for horizontal walls plus h rows for vertical walls]
[237]
[Print row for horizontal walls]
O296@ [print leading + sign]
S@ A2F [set inner loop counter in 4F]
H13@
[241] T4F [4F := negative count of horizontal walls per row]
S13@ [has current horizontal wall been deleted?]
[243] C1H [planted; loaded as C1H]
G247@ [jump if not]
A23@ G249@
[247] T1F [clear acc]
[248] A248@ [load hyphen (since A = minus in figures mode)]
[249] TF OF OF OF [print 3 spaces or 3 minus]
O296@ [print plus sign]
A243@ A2F T243@ [inc address in C order]
A4F A2F G241@
[Here with acc = 0 after printing one row]
A243@ A2F T243@ [skip next element in array]
O24@ O25@ [print CR, LF]
A5F A2F E295@
T5F
[Print row for vertical walls]
S@
T4F
H14@
[272] S14@
[273] C1H [planted; loaded as C1H]
G277@
A23@ G279@
[277] T1F [clear acc]
A10@ [colon in figures mode]
[279] TF OF [print colon or space]
A273@ A2F T273@ [update C order]
A4F A2F [inc negative counter for inner loop]
E292@ [jump out of loop if counter = 0]
T4F [update counter]
O23@ O23@ O23@ [print 3 spaces]
E272@
[Exit from inner loop for vertical walls]
[292] O24@ O25@ [print CR, LF]
E237@
[Exit]
[295] O22@ [dummy character to flush print buffer]
[296] ZF [(1) halt program (2) plus sign in figures mode]
 
[==================== Generator for pseudo-random numbers ===========]
[Linear congruential generator, same algorithm as Delphi 7 LCG
38 locations]
E25K TG
GKG10@G15@T2#ZPFT2ZI514DP257FT4#ZPFT4ZPDPFT6#ZPFT6ZPFRFA6#@S4#@
T6#@E25FE8ZPFT8ZPFPFA3FT14@A4DT8#@ZFA3FT37@H2#@V8#@L512FL512F
L1024FA4#@T8#@H6#@C8#@T8#@S4DG32@TDA8#@E35@H4DTDV8#@L1FTDZF
 
[==================== LIBRARY SUBROUTINE ============================]
E25K TN
[R4 Input of one signed integer.
22 storage locations; working positions 4, 5, and 6.]
GKA3FT21@T4DH6@E11@P5DJFT6FVDL4FA4DTDI4FA4FS5@G7@S5@G20@SDTDT6FEF
 
[===================================================================]
[The following, without the comments and white space, might have
been input from a separate tape.]
E25K TX GK
EZ [define entry point]
PF [acc = 0 on entry]
[Integers supplied by user: maze width, maze height, seed for LCG.
To be read by library subroutine R4; sign comes after value.]
12+8+987654321+
</syntaxhighlight>
{{out}}
<pre>
+---+---+---+---+---+---+---+---+---+---+---+---+
: : : : :
+ +---+ +---+---+ +---+---+ + +---+ +
: : : : : :
+ + +---+ +---+---+ +---+---+---+---+ +
: : : : : : :
+ + +---+---+ + +---+ +---+ + +---+
: : : : : : : :
+---+---+ + +---+---+ +---+ + +---+ +
: : : : : :
+ +---+---+---+ + +---+---+---+---+ + +
: : : : : : :
+ + +---+ +---+---+---+---+ + +---+ +
: : : : : :
+ +---+ +---+---+---+---+ +---+---+---+ +
: : :
+---+---+---+---+---+---+---+---+---+---+---+---+
</pre>
 
=={{header|EGL}}==
<langsyntaxhighlight EGLlang="egl">program MazeGen
 
// First and last columns/rows are "dead" cells. Makes generating
Line 2,720 ⟶ 3,294:
end
 
end</langsyntaxhighlight>
{{out|Output example (for 10x10 maze)}}
<pre>
Line 2,748 ⟶ 3,322:
=={{header|Elixir}}==
{{trans|D}}
<langsyntaxhighlight lang="elixir">defmodule Maze do
def generate(w, h) do
maze = (for i <- 1..w, j <- 1..h, into: Map.new, do: {{:vis, i, j}, true})
Line 2,778 ⟶ 3,352:
end
 
Maze.generate(20, 10)</langsyntaxhighlight>
 
{{out}}
Line 2,806 ⟶ 3,380:
 
=={{header|Elm}}==
<langsyntaxhighlight lang="elm">import Maybe as M
import Result as R
import Matrix
Line 3,054 ⟶ 3,628:
, update = update
, subscriptions = subscriptions
}</langsyntaxhighlight>
 
Link to live demo: http://dc25.github.io/mazeGenerationElm/
Line 3,061 ⟶ 3,635:
{{libheader|cl-lib}}
 
<langsyntaxhighlight lang="lisp">(require 'cl-lib)
 
(cl-defstruct maze rows cols data)
Line 3,253 ⟶ 3,827:
(print-maze maze solution)))
 
(generate 20 20)</langsyntaxhighlight>
 
{{out}}
Line 3,284 ⟶ 3,858:
 
===Using multiple processes===
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( maze ).
 
Line 3,428 ⟶ 4,002:
[Pid ! {Key, My_pid} || {_Position, Pid} <- Position_pids],
[{Position, read_receive(Pid, Key)} || {Position, Pid} <- Position_pids].
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,464 ⟶ 4,038:
 
Usage: start with generate_default/0. Use generate_MxN() to test other maze sizes.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module(maze).
-record(maze, {g, m, n}).
Line 3,579 ⟶ 4,153:
generate_default() ->
generate_MxN(9, 9).
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,607 ⟶ 4,181:
=={{header|F_Sharp|F#}}==
Using mutable state in the form of 2D arrays:
<langsyntaxhighlight lang="fsharp">let rnd : int -> int =
let gen = new System.Random()
fun max -> gen.Next(max)
Line 3,663 ⟶ 4,237:
 
let m = new Maze(10,10)
m.Print()</langsyntaxhighlight>
{{out|Output example}}
<pre>+-+-+-+-+-+-+-+-+-+-+
Line 3,692 ⟶ 4,266:
The solution uses the following library <tt>bits.fs</tt>, which implements bit-arrays:
<br>
<langsyntaxhighlight lang="forth">\ Bit Arrays
 
: to-bits ( c -- f f f f f f f f )
Line 3,802 ⟶ 4,376:
else
drop
then ;</langsyntaxhighlight>
<br>
The solution uses three bit-arrays: one to track whether a cell has been visited, one for "East"-walls (walls to the right of a cell) and one for "South"-walls (walls to the bottom of a cell).
<br>
<langsyntaxhighlight lang="forth">#! /usr/bin/gforth
\ Maze Generation
 
Line 3,927 ⟶ 4,501:
: maze ( width height -- ) build-maze maze. ;
 
maze cr bye</langsyntaxhighlight>
 
{{out}}<pre>
Line 4,007 ⟶ 4,581:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' version 04-12-2016
' compile with: fbc -s console
' when generating a big maze it's possible to run out of stack space
Line 4,136 ⟶ 4,710:
Loop
 
End</langsyntaxhighlight>
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Maze_generation}}
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for storage and transfer purposes more than visualization and edition.
 
'''Solution'''
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
[[File:Fōrmulæ - Maze generation 01.png]]
In '''[https://formulae.org/?example=Maze_generation this]''' page you can see the program(s) related to this task and their results.
 
'''Test cases'''
 
[[File:Fōrmulæ - Maze generation 02.png]]
 
[[File:Fōrmulæ - Maze generation 03.png]]
 
[[File:Fōrmulæ - Maze generation 04.png]]
 
[[File:Fōrmulæ - Maze generation 05.png]]
 
[[File:Fōrmulæ - Maze generation 06.png]]
 
[[File:Fōrmulæ - Maze generation 07.png]]
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
_rows = 9
_cols = 11
_size = 32
_mgn = 32
 
_t = ( 1 << 0 )
_l = ( 1 << 1 )
_b = ( 1 << 2 )
_r = ( 1 << 3 )
_a = _t + _l + _b + _r
 
_window = 1
 
void local fn BuildWindow
window _window, @"FutureBasic - Maze generation", (0,0,_cols*_size+_mgn*2,_rows*_size+_mgn*2), NSWindowStyleMaskTitled
end fn
 
 
local fn CellAvailable( r as long, c as long ) as BOOL
if ( r < 0 || c < 0 || r >= _rows || c >= _cols ) then exit fn
if ( mda_integer(r,c) == _a ) then exit fn = YES
end fn = NO
 
 
void local fn ProcessCell( r as long, c as long )
long r1 = r, c1 = c, d(3), count, dir, opp
while ( 1 )
BlockZero( @d(0), sizeof(long) * 4 )
count = 0
if ( fn CellAvailable( r - 1, c ) ) then d(count) = _t : count++
if ( fn CellAvailable( r, c - 1 ) ) then d(count) = _l : count++
if ( fn CellAvailable( r + 1, c ) ) then d(count) = _b : count++
if ( fn CellAvailable( r, c + 1 ) ) then d(count) = _r : count++
if ( count == 0 ) then break
dir = d(rnd(count)-1)
mda(r,c) = @(mda_integer(r,c) - dir)
select ( dir )
case _t
r1 = r-1 : opp = _b
case _l
c1 = c-1 : opp = _r
case _b
r1 = r+1 : opp = _t
case _r
c1 = c+1 : opp = _l
end select
mda(r1,c1) = @(mda_integer(r1,c1) - opp)
fn ProcessCell( r1, c1 )
wend
end fn
 
 
void local fn DrawMaze
long r, c, x = _mgn, y = _mgn, value
pen 2,, NSLineCapStyleRound
for r = 0 to _rows - 1
for c = 0 to _cols - 1
value = mda(r,c)
if ( value & _t ) then line x, y to x + _size, y
if ( value & _l ) then line x, y to x, y + _size
if ( value & _b ) then line x, y + _size to x + _size, y + _size
if ( value & _r ) then line x + _size, y to x + _size, y + _size
x += _size
next
x = _mgn
y += _size
next
end fn
 
 
void local fn BuildMaze
long r, c
for r = 0 to _rows - 1
for c = 0 to _cols - 1
mda(r,c) = _a
next
next
random
r = rnd(_rows) - 1
c = rnd(_cols) - 1
fn ProcessCell( r, c )
fn DrawMaze
end fn
 
fn BuildWindow
fn BuildMaze
 
HandleEvents
</syntaxhighlight>
[[file:FutureBasic - Maze generation1.png]]
[[file:FutureBasic - Maze generation2.png]]
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 4,265 ⟶ 4,955:
m.gen()
fmt.Print(m)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 4,280 ⟶ 4,970:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
 
Line 4,357 ⟶ 5,047:
 
main :: IO ()
main = getStdGen >>= stToIO . maze 11 8 >>= printMaze</langsyntaxhighlight>
{{out|Sample output}}
+---+---+---+---+---+---+---+---+---+---+---+
Line 4,378 ⟶ 5,068:
 
=={{header|Huginn}}==
<langsyntaxhighlight lang="huginn">import Algorithms as algo;
import Mathematics as math;
import Terminal as term;
Line 4,448 ⟶ 5,138:
maze = Maze( rows, cols );
print( "{}".format( maze ) );
}</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
[[File:Mazegen-unicon-20x30-1321112170.gif|thumb|right|20x30 with two random openings]]
[[File:Mazegen-unicon-20x30-1321060467.gif|thumb|right|20x30 with opposite openings]]
<langsyntaxhighlight Iconlang="icon">link printf
 
procedure main(A) # generate rows x col maze
Line 4,545 ⟶ 5,235:
 
return mazeinfo(&window,maze,sprintf("maze-%dx%d-%d.gif",r,c,&now))
end</langsyntaxhighlight>
Note: The underlying maze structure (matrix) is uni-directional from the start
{{libheader|Icon Programming Library}}
Line 4,555 ⟶ 5,245:
{{trans|PicoLisp}}
But without any relevant grid library:
<langsyntaxhighlight lang="j">maze=:4 :0
assert.0<:n=.<:x*y
horiz=. 0$~x,y-1
Line 4,585 ⟶ 5,275:
'hdoor vdoor'=. 2 4&*&.>&.> (#&,{@;&i./@$)&.> y
' ' (a:-.~0 1;0 2; 0 3;(2 1-~$text);(1 4&+&.> hdoor),,vdoor+&.>"0/2 1;2 2;2 3)} text
)</langsyntaxhighlight>
The result of <code>maze</code> is a pair of arrays: one for open "doors" in the horizontal direction and the other for open "doors" in the vertical direction. The entry and exit doors are not represented by <code>maze</code> -- they are implicitly defined and are implemented in <code>display</code>. (The sequences of coordinates in <code>display</code> are the relative coordinates for the doors. For example, <code>2 1;2 2;2 3</code> are where we put spaces for each vertical door. The variable <code>text</code> is an ascii representation of the maze grid before the doors are placed.)
 
{{out|Example use (with ascii box drawing enabled)}}
<langsyntaxhighlight lang="j"> display 8 maze 11
+ +---+---+---+---+---+---+---+---+---+---+
| | | | |
Line 4,606 ⟶ 5,296:
+ + + + + + + + +---+ + +
| | | | |
+---+---+---+---+---+---+---+---+---+---+---+</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">package org.rosettacode;
 
import java.util.Collections;
Line 4,700 ⟶ 5,390:
}
 
}</langsyntaxhighlight>
{{out}}
<pre>+---+---+---+---+---+---+---+---+---+---+
Line 4,726 ⟶ 5,416:
=={{header|JavaScript}}==
{{trans|J}}
<langsyntaxhighlight lang="javascript">function maze(x,y) {
var n=x*y-1;
if (n<0) {alert("illegal maze dimensions");return;}
Line 4,788 ⟶ 5,478:
}
return text.join('');
}</langsyntaxhighlight>
Variable meanings in function <code>maze</code>:
# <code>x</code>,<code>y</code> — dimensions of maze
Line 4,806 ⟶ 5,496:
 
{{out|Example use}}
<langsyntaxhighlight lang="html"><html><head><title></title></head><body><pre id="out"></pre></body></html>
<script type="text/javascript">
/* ABOVE CODE GOES HERE */
document.getElementById('out').innerHTML= display(maze(8,11));
</script></langsyntaxhighlight>
produced output:
<pre>+ +---+---+---+---+---+---+---+---+---+---+
Line 4,832 ⟶ 5,522:
 
For example, change replace the line <code>while (0<n) {</code> with:
<langsyntaxhighlight lang="javascript"> function step() {
if (0<n) {</langsyntaxhighlight>
And replace the closing brace for this while loop with:
<langsyntaxhighlight lang="javascript"> document.getElementById('out').innerHTML= display({x: x, y: y, horiz: horiz, verti: verti, here: here});
setTimeout(step, 100);
}
}
step();</langsyntaxhighlight>
To better see the progress, you might want a marker in place, showing the position being considered. To do that, replace the line which reads <code>if (0 == k%4) {</code> with
<langsyntaxhighlight lang="javascript"> if (m.here && m.here[0]*2+1 == j && m.here[1]*4+2 == k)
line[k]= '#'
else if (0 == k%4) {</langsyntaxhighlight>
Note however that this leaves the final '#' in place on maze completion, and that the function <code>maze</code> no longer returns a result which represents a generated maze.
 
Note also that this display suggests an optimization. You can replace the line reading <code>path.push(here= next);</code> with:
<langsyntaxhighlight lang="javascript"> here= next;
if (1 < neighbors.length)
path.push(here);</langsyntaxhighlight>
And this does indeed save a negligible bit of processing, but the maze algorithm will still be forced to backtrack through a number of locations which have no unvisited neighbors.
===HTML Table===
Using HTML, CSS and table cells for maze.
<langsyntaxhighlight lang="html"><html><head><title>Maze maker</title>
<style type="text/css">
table { border-collapse: collapse }
Line 4,967 ⟶ 5,657:
<a href="javascript:make_maze()">Generate</a>
<a id='solve' style='display:none' href='javascript:solve(); void(0)'>Solve</a>
</fieldset></form><table id='maze'/></body></html></langsyntaxhighlight>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
Since jq does not have a builtin PRNG,
it is assumed that /dev/urandom is available.
An invocation such as the following may be used:
<pre>
< /dev/urandom tr -cd '0-9' | fold -w 1 | jq -Rcnr -f maze-generation.jq
</pre>
In the following, a maze is represented by a matrix, each of whose elements
is in turn a JSON object representing the bounding box:
$box["N"] is true iff the northern (top) edge is open, and similarly for the
other points of the compass.
 
Note that in the following, the "walk" always starts at the (0,0)
cell; this is just to make it clear that walk starts at the top left of the
display.
<syntaxhighlight lang="jq">
# Output: a prn in range(0;$n) where $n is .
def prn:
if . == 1 then 0
else . as $n
| (($n-1)|tostring|length) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;
 
# Input: an array
def knuthShuffle:
length as $n
| if $n <= 1 then .
else {i: $n, a: .}
| until(.i == 0;
.i += -1
| (.i + 1 | prn) as $j
| .a[.i] as $t
| .a[.i] = .a[$j]
| .a[$j] = $t)
| .a
end;
 
# Compass is a JSON object {n,s,e,w} representing the four possible
# directions in which to move, i.e. to open a gate.
# For example, Compass.n corresponds to a move north (i.e. dx is 0, dy is 1),
# and Compass.n.gates["N"] is true indicating that the "northern" gate should be opened.
def Compass:
{n: { gates: {"N": true}, dx: 0, dy: -1},
s: { gates: {"S": true}, dx: 0, dy: 1},
e: { gates: {"E": true}, dx: 1, dy: 0},
w: { gates: {"W": true}, dx:-1, dy: 0} }
| .n.opposite = .s
| .s.opposite = .n
| .e.opposite = .w
| .w.opposite = .e
;
 
# Produce a matrix representing an $x x $y maze.
# .[$i][$j] represents the box in row $i, column $j.
# Initially, all the gates of all the boxes are closed.
def MazeMatrix($x; $y):
[range(0;$x) | {} ] as $v | [range(0;$y) | $v];
 
# Input: a MazeMatrix
def generate($cx; $cy):
def interior($a; $upper): $a >= 0 and $a < $upper;
length as $x
| (.[0]|length) as $y
| Compass as $Compass
| ([$Compass.n, $Compass.s, $Compass.e, $Compass.w] | knuthShuffle) as $directions
| reduce $directions[] as $v (.;
($cx + $v.dx) as $nx
| ($cy + $v.dy) as $ny
| if interior($nx; $x) and interior($ny; $y) and .[$nx][$ny] == {}
then .[$cx][$cy] += $v.gates
| .[$nx][$ny] += $v.opposite.gates
| generate($nx; $ny)
end );
 
# Input: a MazeMatrix
def display:
. as $maze
| ($maze|length) as $x
| ($maze[0]|length) as $y
| ( range(0;$y) as $i
# draw the north edge
| ([range(0;$x) as $j
| if $maze[$j][$i]["N"] then "+ " else "+---" end] | join("")) + "+",
# draw the west edge
([range(0;$x) as $j
| if $maze[$j][$i]["W"] then " " else "| " end] | join("")) + "|" ),
# draw the bottom line
($x * "+---") + "+"
;
 
# Start the walk at the top left
def amaze($x;$y):
MazeMatrix($x; $y)
| generate(0; 0)
| display;
 
# Example
amaze(4; 5);
</syntaxhighlight>
{{output}}
Example output:
<pre>
+---+---+---+---+---+
| | |
+---+ + +---+ +
| | | | |
+ + + + + +
| | | | | |
+ + +---+ + +
| | |
+---+---+---+---+---+
</pre>
 
=={{header|Julia}}==
Line 4,973 ⟶ 5,784:
 
'''Generating functions'''
<langsyntaxhighlight lang="julia">using Random
check(bound::Vector) = cell -> all([1, 1] .≤ cell .≤ bound)
neighbors(cell::Vector, bound::Vector, step::Int=2) =
Line 4,992 ⟶ 5,803:
firstcell = 2 * [rand(1:w), rand(1:h)]
return walk(maze, firstcell)
end</langsyntaxhighlight>
 
'''Printing functions'''
<langsyntaxhighlight lang="julia">pprint(matrix) = for i = 1:size(matrix, 1) println(join(matrix[i, :])) end
function printmaze(maze)
walls = split("╹ ╸ ┛ ╺ ┗ ━ ┻ ╻ ┃ ┓ ┫ ┏ ┣ ┳ ╋")
Line 5,008 ⟶ 5,819:
 
printmaze(maze(10, 10))
</syntaxhighlight>
</lang>
 
{{out}}
Line 5,025 ⟶ 5,836:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">import java.util.*
 
class MazeGenerator(val x: Int, val y: Int) {
Line 5,091 ⟶ 5,902:
display()
}
}</langsyntaxhighlight>
 
=={{header|Lua}}==
{{Works with|Lua|5.1}}
<syntaxhighlight lang="lua">
<lang Lua>
math.randomseed( os.time() )
 
Line 5,169 ⟶ 5,980:
 
print(make_maze())
</syntaxhighlight>
</lang>
{{Out}}
<pre>#################################
Line 5,204 ⟶ 6,015:
INT((currentx% + oldx%) / 2) return a double, because has 2 as double so we get (integer+integer)/double or integer/double or double. Int(0.5) return.
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Maze {
width% = 40
Line 5,261 ⟶ 6,072:
}
Maze
</syntaxhighlight>
</lang>
 
===Depth-first search===
Line 5,271 ⟶ 6,082:
 
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Maze2 {
\\ depth-first search
Line 5,301 ⟶ 6,112:
status--
forchoose=forchoose#val(random(0,status))
if status>0 then Push forchoose
OpenDoor(!Entry, !forchoose)
Rem : ShowMaze()
Line 5,342 ⟶ 6,153:
}
Maze2
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight lang="mathematica">MazeGraphics[m_, n_] :=
Block[{$RecursionLimit = Infinity,
unvisited = Tuples[Range /@ {m, n}], maze},
Line 5,359 ⟶ 6,170:
RandomSample@{# + {0, 1}, # - {0, 1}, # + {1, 0}, # - {1,
0}}}]} &@RandomChoice@unvisited; maze];
maze = MazeGraphics[21, 13]</langsyntaxhighlight>
{{Out}}
[[File:MathematicaMazeGraphics.png]]
Line 5,365 ⟶ 6,176:
{{Works with|Mathematica|9.0}}
Here I generate a maze as a graph. Vertices of the graph are cells and edges of the graph are removed walls. This version is mush faster and is convenient to solve.
<langsyntaxhighlight lang="mathematica">MazeGraph[m_, n_] :=
Block[{$RecursionLimit = Infinity, grid = GridGraph[{m, n}],
unvisitedQ}, unvisitedQ[_] := True;
Line 5,375 ⟶ 6,186:
RandomChoice@VertexList@grid][[2, 1]],
GraphLayout -> {"GridEmbedding", "Dimension" -> {m, n}}]];
maze = MazeGraph[13, 21]</langsyntaxhighlight>
{{Out}}
[[File:MathematicaMazeGraph.png]]
 
=={{header|MATLAB}} / {{header|Octave}}==
<langsyntaxhighlight Matlablang="matlab">function M = makeMaze(n)
showProgress = false;
 
Line 5,432 ⟶ 6,243:
 
image(M-VISITED);
axis equal off;</langsyntaxhighlight>
 
=={{header|Nim}}==
{{trans|D}}
<langsyntaxhighlight lang="nim">import random, sequtils, strutils
randomize()
 
Line 5,466 ⟶ 6,277:
walk rand(0..<w), rand(0..<h)
for a,b in zip(hor, ver & @[""]).items:
echo join(a & "+\n" & b)</langsyntaxhighlight>
 
{{out}}
Line 5,497 ⟶ 6,308:
This difers of the basic Javascript in that in NodeJS we take advantage of the asynchronous behaviour. This code was modified from the plain Javascript section to make it '''Asynchronous''' and able to run under ''strict mode''.
 
<langsyntaxhighlight lang="javascript">
'use strict';
/*
Line 5,597 ⟶ 6,408:
display: display
}
</syntaxhighlight>
</lang>
 
{{out|Example use}}
Line 5,603 ⟶ 6,414:
Here is a basic example of what your main file should contain:
 
<langsyntaxhighlight lang="javascript">
'use strict';
 
Line 5,620 ⟶ 6,431:
}, (err) => console.error(err));
 
</syntaxhighlight>
</lang>
 
Sample Output:
Line 5,651 ⟶ 6,462:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let seen = Hashtbl.create 7
let mark t = Hashtbl.add seen t true
let marked t = Hashtbl.mem seen t
Line 5,697 ⟶ 6,508:
Random.self_init();
visit (Random.int nx, Random.int ny);
print_maze ();</langsyntaxhighlight>
Output from 'ocaml gen_maze.ml 10 10':<pre>+---+---+---+---+---+---+---+---+---+---+
| | | |
Line 5,722 ⟶ 6,533:
 
=={{header|Ol}}==
<langsyntaxhighlight lang="scheme">
; maze generation
(import (otus random!))
Line 5,760 ⟶ 6,571:
(loop nx ny)))
(try))))))
</syntaxhighlight>
</lang>
<langsyntaxhighlight lang="scheme">
; maze printing:
(display "+")
Line 5,784 ⟶ 6,595:
maze)
(print)
</syntaxhighlight>
</lang>
{{out|Sample 30 x 8 output}}
<pre>+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Line 5,805 ⟶ 6,616:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use List::Util 'max';
 
my ($w, $h) = @ARGV;
Line 5,840 ⟶ 6,651:
print @{$hor[$_]}, "+\n";
print @{$ver[$_]}, "|\n" if $_ < $h;
}</langsyntaxhighlight>
Run as <code>maze.pl [width] [height]</code> or use default dimensions.
{{out|Sample 4 x 1 output}}
Line 5,850 ⟶ 6,661:
Adapted a couple of techniques from the excellent D submission<br>
(however this holds the grid as an array of complete lines)
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #000080;font-style:italic;">--
Line 5,898 ⟶ 6,709:
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grid</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">))</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 5,922 ⟶ 6,733:
=={{header|PHP}}==
Code inspired by the D and Python solutions (with the implementation of backtracking, or sometimes it wouldn't work). Could have been done procedurally or fully OO (with cells as class too). A debug flag has been provided to allow following the inner workings. Works on PHP > 5.6.
<langsyntaxhighlight lang="php"><?php
class Maze
{
Line 6,069 ⟶ 6,880:
 
$maze = new Maze(10,10);
$maze->printOut();</langsyntaxhighlight>
{{out}}
<pre>
Line 6,096 ⟶ 6,907:
 
=={{header|Picat}}==
<langsyntaxhighlight Picatlang="picat">main =>
gen_maze(8,8).
 
Line 6,156 ⟶ 6,967:
end,
println("+").
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 6,180 ⟶ 6,991:
=={{header|PicoLisp}}==
This solution uses 'grid' from "lib/simul.l" to generate the two-dimensional structure.
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
 
(de maze (DX DY)
Line 6,209 ⟶ 7,020:
 
(de display (Maze)
(disp Maze 0 '((This) " ")) )</langsyntaxhighlight>
{{out}}
<pre>: (display (maze 11 8))
Line 6,233 ⟶ 7,044:
=={{header|PL/I}}==
{{trans|REXX}}
<langsyntaxhighlight lang="pli">*process source attributes xref or(!);
mgg: Proc Options(main);
/* REXX ***************************************************************
Line 6,449 ⟶ 7,260:
 
End;
End;</langsyntaxhighlight>
Output:
<pre>
Line 6,466 ⟶ 7,277:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 11
</pre>
 
=={{header|POV-Ray}}==
This POV-Ray solution uses an iterative rather than recursive approach because POV-Ray has a small stack for recursion (about 100 levels) and so the program would crash on even quite small mazes. With the iterative approach it works on very large mazes.
<syntaxhighlight lang="pov">
#version 3.7;
 
global_settings {
assumed_gamma 1
}
 
#declare Rows = 15;
#declare Cols = 17;
 
#declare Seed = seed(2); // A seed produces a fixed sequence of pseudorandom numbers
 
#declare Wall = prism {
0, 0.8, 7,
<0, -0.5>, <0.05, -0.45>, <0.05, 0.45>, <0, 0.5>,
<-0.05, 0.45>, <-0.05, -0.45>, <0, -0.5>
texture {
pigment {
brick colour rgb 1, colour rgb <0.8, 0.25, 0.1> // Colour mortar, colour brick
brick_size 3*<0.25, 0.0525, 0.125>
mortar 3*0.01 // Size of the mortar
}
normal { wrinkles 0.75 scale 0.01 }
finish { diffuse 0.9 phong 0.2 }
}
}
 
#macro Fisher_Yates_Shuffle(Stack, Start, Top)
#for (I, Top, Start+1, -1)
#local J = floor(rand(Seed)*I + 0.5);
#if (J != I) // Waste of time swapping an element with itself
#local Src_Row = Stack[I][0];
#local Src_Col = Stack[I][1];
#local Dst_Row = Stack[I][2];
#local Dst_Col = Stack[I][3];
#declare Stack[I][0] = Stack[J][0];
#declare Stack[I][1] = Stack[J][1];
#declare Stack[I][2] = Stack[J][2];
#declare Stack[I][3] = Stack[J][3];
#declare Stack[J][0] = Src_Row;
#declare Stack[J][1] = Src_Col;
#declare Stack[J][2] = Dst_Row;
#declare Stack[J][3] = Dst_Col;
#end
#end
#end
 
#macro Initialise(Visited, North_Walls, East_Walls)
#for (R, 0, Rows-1)
#for (C, 0, Cols-1)
#declare Visited[R][C] = false;
#declare North_Walls[R][C] = true;
#declare East_Walls[R][C] = true;
#end
#end
#end
 
#macro Push(Stack, Top, Src_Row, Src_Col, Dst_Row, Dst_Col)
#declare Top = Top + 1;
#declare Stack[Top][0] = Src_Row;
#declare Stack[Top][1] = Src_Col;
#declare Stack[Top][2] = Dst_Row;
#declare Stack[Top][3] = Dst_Col;
#end
 
#macro Generate_Maze(Visited, North_Walls, East_Walls)
#local Stack = array[Rows*Cols][4]; // 0: from row, 1: from col, 2: to row, 3: to col
#local Row = floor(rand(Seed)*(Rows-1) + 0.5); // Random start row
#local Col = floor(rand(Seed)*(Cols-1) + 0.5); // Random start column
#local Top = -1;
Push(Stack, Top, Row, Col, Row, Col)
 
#while (Top >= 0)
#declare Visited[Row][Col] = true;
#local Start = Top + 1;
 
#if (Row < Rows-1) // Add north neighbour
#if (Visited[Row+1][Col] = false)
Push(Stack, Top, Row, Col, Row+1, Col)
#end
#end
 
#if (Col < Cols-1) // Add east neighbour
#if (Visited[Row][Col+1] = false)
Push(Stack, Top, Row, Col, Row, Col+1)
#end
#end
 
#if (Row > 0) // Add south neighbour
#if (Visited[Row-1][Col] = false)
Push(Stack, Top, Row, Col, Row-1, Col)
#end
#end
 
#if (Col > 0) // Add west neighbour
#if (Visited[Row][Col-1] = false)
Push(Stack, Top, Row, Col, Row, Col-1)
#end
#end
 
Fisher_Yates_Shuffle(Stack, Start, Top)
 
#local Removed_Wall = false;
#while (Top >= 0 & Removed_Wall = false)
#local Src_Row = Stack[Top][0];
#local Src_Col = Stack[Top][1];
#local Dst_Row = Stack[Top][2];
#local Dst_Col = Stack[Top][3];
#declare Top = Top - 1;
 
#if (Visited[Dst_Row][Dst_Col] = false)
#if (Dst_Row = Src_Row+1 & Dst_Col = Src_Col) // North wall
#declare North_Walls[Src_Row][Src_Col] = false;
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col+1) // East wall
#declare East_Walls[Src_Row][Src_Col] = false;
#elseif (Dst_Row = Src_Row-1 & Dst_Col = Src_Col) // South wall
#declare North_Walls[Dst_Row][Src_Col] = false;
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col-1) // West wall
#declare East_Walls[Src_Row][Dst_Col] = false;
#else
#error "Unknown wall!\n"
#end
 
#declare Row = Dst_Row;
#declare Col = Dst_Col;
#declare Removed_Wall = true;
#end
#end
#end
#end
 
#macro Draw_Maze(North_Walls, East_Walls)
merge {
#for (R, 0, Rows-1)
object { Wall translate <1, 0, 0.5> translate <-1, 0, R> } // West edge
#for (C, 0, Cols-1)
#if (R = 0) // South edge
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, -1> }
#end
#if (North_Walls[R][C])
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, R> }
#end
#if (East_Walls[R][C])
object { Wall translate <1, 0, 0.5> translate <C, 0, R> }
#end
#end
#end
translate <-0.5*Cols, 0, 0> // Centre maze on x=0
}
#end
 
camera {
location <0, 13, -2>
right x*image_width/image_height
look_at <0, 2, 5>
}
 
light_source {
<-0.1*Cols, Rows, 0.5*Rows>, colour rgb <1, 1, 1>
area_light
x, y, 3, 3
circular orient
}
 
box {
<-0.5*Cols, -0.1, 0>, <0.5*Cols, 0, Rows>
texture {
pigment {
checker colour rgb <0, 0.3, 0> colour rgb <0, 0.4, 0>
scale 0.5
}
finish { specular 0.5 reflection { 0.1 } }
}
}
 
#declare Visited = array[Rows][Cols];
#declare North_Walls = array[Rows][Cols];
#declare East_Walls = array[Rows][Cols];
 
Initialise(Visited, North_Walls, East_Walls)
Generate_Maze(Visited, North_Walls, East_Walls)
Draw_Maze(North_Walls, East_Walls)
</syntaxhighlight>
{{out}}
[[File:Povray maze solution 640px.png|640px|frame|none|alt=POV-Ray maze with red brick walls|POV-Ray solution with 15 rows and 17 columns]]
 
=={{header|Processing}}==
<langsyntaxhighlight lang="java">int g_size = 10;
color background_color = color (80, 80, 220);
color runner = color (255, 50, 50);
Line 6,594 ⟶ 7,593:
if(wall[3]) line((j+1)*c_size, i*c_size, j*c_size, i*c_size);
}
}</langsyntaxhighlight>
'''It can be played on line''' :<BR> [https://www.openprocessing.org/sketch/880778/ here.]
 
==={{header|Processing Python mode}}===
 
<langsyntaxhighlight lang="python">
g_size = 10
background_color = color(80, 80, 220)
Line 6,722 ⟶ 7,721:
if wall[2]: line((j + 1) * c_size, (i + 1) * c_size, (j + 1) * c_size, i * c_size)
if wall[3]: line((j + 1) * c_size, i * c_size, j * c_size, i * c_size)
</syntaxhighlight>
</lang>
 
=={{header|Prolog}}==
Works with SWI-Prolog and XPCE.
<langsyntaxhighlight Prologlang="prolog">:- dynamic cell/2.
 
maze(Lig,Col) :-
Line 6,816 ⟶ 7,815:
\+cell(L, C1).
 
</syntaxhighlight>
</lang>
{{out}}
[[File:Prolog-Maze.jpg]]
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Enumeration
;indexes for types of offsets from maze coordinates (x,y)
#visited ;used to index visited(x,y) in a given direction from current maze cell
Line 6,956 ⟶ 7,955:
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf</langsyntaxhighlight>
The maze is represented by an array of cells where each cell indicates the walls present above (#dir_N) and to its left (#dir_W). Maze generation is done with a additional array marking the visited cells. Neither an entry nor an exit are created, these were not part of the task. A simple means of doing so is included but has been commented out.
 
Line 6,980 ⟶ 7,979:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from random import shuffle, randrange
 
def make_maze(w = 16, h = 8):
Line 7,006 ⟶ 8,005:
 
if __name__ == '__main__':
print(make_maze())</langsyntaxhighlight>
{{out}}
<pre>+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Line 7,029 ⟶ 8,028:
 
Maze generator
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 7,060 ⟶ 8,059:
; return the result
(maze N M tbl))
</syntaxhighlight>
</lang>
 
Printing out the maze
 
<langsyntaxhighlight lang="racket">
;; Shows a maze
(define (show-maze m)
Line 7,084 ⟶ 8,083:
(displayln "+"))
(newline))
</syntaxhighlight>
</lang>
 
Example:
Line 7,111 ⟶ 8,110:
{{works with|rakudo|2015-09-22}}
Supply a width and height and optionally the x,y grid coords for the starting cell. If no starting cell is supplied, a random one will be selected automatically. 0,0 is the top left corner.
<syntaxhighlight lang="raku" perl6line>constant mapping = :OPEN(' '),
:N< ╵ >,
:E< ╶ >,
Line 7,197 ⟶ 8,196:
}
display gen_maze( 29, 19 );</langsyntaxhighlight>
{{out}}
<small><pre style="font-family: consolas, inconsolata, monospace; line-height: normal;">┌ ╵ ────────────────────────────┬───────────────────────────────────────────┬───────────┬───────────────────────────┐
Line 7,241 ⟶ 8,240:
=={{header|Rascal}}==
{{trans|Python}}
<langsyntaxhighlight lang="rascal">import IO;
import util::Math;
import List;
Line 7,269 ⟶ 8,268:
println(("" | it + "<z>" | z <- b));
}
}</langsyntaxhighlight>
 
<pre>rascal>make_maze(10,10)
Line 7,298 ⟶ 8,297:
 
=={{header|Red}}==
<langsyntaxhighlight Redlang="red">Red ["Maze generation"]
 
size: as-pair to-integer ask "Maze width: " to-integer ask "Maze height: "
Line 7,345 ⟶ 8,344:
]
print ""
]</langsyntaxhighlight>
{{out}}
<pre>Maze width: 15
Line 7,371 ⟶ 8,370:
In order to preserve the aspect ratio (for most display terminals), several &nbsp; '''changestr''' &nbsp; invocations and
<br>some other instructions were added to increase the horizontal dimension (cell size).
<langsyntaxhighlight lang="rexx">/*REXX program generates and displays a rectangular solvable maze (of any size). */
parse arg rows cols seed . /*allow user to specify the maze size. */
if rows='' | rows==',' then rows= 19 /*No rows given? Then use the default.*/
Line 7,467 ⟶ 8,466:
otherwise nop
end /*select*/
end /*k*/; return</langsyntaxhighlight>
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, so one is included here &nbsp; ──► &nbsp; [[CHANGESTR.REX]].
 
Line 7,527 ⟶ 8,526:
The above REXX version had a quite of bit of code to "dress up" the maze presentation, &nbsp; so a slimmed-down version
<br>was included here for easier reading and understanding of the program's logic.
<langsyntaxhighlight lang="rexx">/*REXX program generates and displays a rectangular solvable maze (of any size). */
parse arg rows cols seed . /*allow user to specify the maze size. */
if rows='' | rows=="," then rows= 19 /*No rows given? Then use the default.*/
Line 7,580 ⟶ 8,579:
if hood(rr,cc)==1 then do; r!= rr; c!= cc; @.r!.c!= 0; return 1; end
end /*c*/ /* [↑] r! and c! are used by invoker.*/
end /*r*/; return 0</langsyntaxhighlight>
{{out|output|text=&nbsp; when using input: &nbsp; &nbsp; <tt> 10 &nbsp;10 </tt>}}
 
Line 7,610 ⟶ 8,609:
 
===version 3===
<langsyntaxhighlight lang="rexx">/* REXX ***************************************************************
* 04.09.2013 Walter Pachl
**********************************************************************/
Line 7,777 ⟶ 8,776:
End
End
Return is js /* return the new start point*/</langsyntaxhighlight>
Output:
<pre>
Line 7,798 ⟶ 8,797:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class Maze
DIRECTIONS = [ [1, 0], [-1, 0], [0, 1], [0, -1] ]
Line 7,892 ⟶ 8,891:
# Demonstration:
maze = Maze.new 20, 10
maze.print</langsyntaxhighlight>
 
{{out}}
Line 7,921 ⟶ 8,920:
=={{header|Rust}}==
Uses the [https://crates.io/crates/rand rand] library
<langsyntaxhighlight lang="rust">use rand::{thread_rng, Rng, rngs::ThreadRng};
 
const WIDTH: usize = 16;
Line 8,057 ⟶ 9,056:
maze.open_doors();
maze.paint();
}</langsyntaxhighlight>
 
{{out}}
Line 8,095 ⟶ 9,094:
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">import scala.util.Random
 
object MazeTypes {
Line 8,180 ⟶ 9,179:
private def openInDirection(loc: Loc, dir: Direction): Boolean =
doors.contains(Door(loc, loc + dir)) || doors.contains(Door(loc + dir, loc))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 8,218 ⟶ 9,217:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">var(w:5, h:5) = ARGV.map{.to_i}...
var avail = (w * h)
 
Line 8,227 ⟶ 9,226:
 
func walk(x, y) {
cell[y][x] = false;
avail-- > 0 || return; nil # no more bottles, er, cells
 
var d = [[-1, 0], [0, 1], [1, 0], [0, -1]]
Line 8,250 ⟶ 9,249:
say (ver[i].join('') + '|')
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 8,267 ⟶ 9,266:
 
=={{header|SuperCollider}}==
<syntaxhighlight lang="supercollider">
<lang SuperCollider>
// some useful functions
(
Line 8,324 ⟶ 9,323:
w.front.refresh;
)
</syntaxhighlight>
</lang>
 
=={{header|Swift}}==
{{works with|Swift|3}}
<langsyntaxhighlight Swiftlang="swift">import Foundation
 
extension Array {
Line 8,496 ⟶ 9,495:
let y = 10
let maze = MazeGenerator(x, y)
maze.display()</langsyntaxhighlight>
{{out}}
<pre>
Line 8,523 ⟶ 9,522:
=={{header|Tcl}}==
{{trans|Javascript}}
<langsyntaxhighlight lang="tcl">package require TclOO; # Or Tcl 8.6
 
# Helper to pick a random number
Line 8,619 ⟶ 9,618:
# Demonstration
maze create m 11 8
puts [m view]</langsyntaxhighlight>
{{out}}
<pre>
Line 8,647 ⟶ 9,646:
Legend: cu = current location; vi = boolean hash of visited locations; pa = hash giving a list neighboring cells to which there is a path from a given cell.
 
<langsyntaxhighlight lang="txr">@(bind (width height) (15 15))
@(do
(defvar *r* (make-random-state nil))
Line 8,701 ⟶ 9,700:
@;;
@(bind m @(make-maze width height))
@(do (print-maze m width height))</langsyntaxhighlight>
 
{{out}}
Line 8,766 ⟶ 9,765:
At the user interface level, the straightness parameter is represented as a percentage. This percentage is converted to a number of cells based on the width and height of the maze. For instance if the straightness parameter is 15, and the maze size is 20x20, it means that 15% out of 400 cells, or 60 cells will be traversed before the queue is scrambled. Then another 60 will be traversed and the queue will be scrambled, and so forth.
 
<langsyntaxhighlight lang="txrlisp">(defvar vi) ;; visited hash
(defvar pa) ;; path connectivity hash
(defvar sc) ;; count, derived from straightness fator
Line 8,845 ⟶ 9,844:
(set h (max 1 h))
(print-maze (make-maze w h s) w h))
(else (usage))))</langsyntaxhighlight>
 
{{out}}
Line 8,959 ⟶ 9,958:
+----+----+----+----+----+----+----+----+----+----+</pre>
 
=={{header|XPL0TypeScript}}==
<lang XPL0>code Ran=1, CrLf=9, Text=12; \intrinsic routines
def Cols=20, Rows=6; \dimensions of maze (cells)
int Cell(Cols+1, Rows+1, 3); \cells (plus right and bottom borders)
def LeftWall, Ceiling, Connected; \attributes of each cell (= 0, 1 and 2)
 
===randomized depth first search function to create maze===
proc ConnectFrom(X, Y); \Connect cells starting from cell X,Y
int X, Y;
int Dir, Dir0;
[Cell(X, Y, Connected):= true; \mark current cell as connected
Dir:= Ran(4); \randomly choose a direction
Dir0:= Dir; \save this initial direction
repeat case Dir of \try to connect to cell at Dir
0: if X+1<Cols & not Cell(X+1, Y, Connected) then \go right
[Cell(X+1, Y, LeftWall):= false; ConnectFrom(X+1, Y)];
1: if Y+1<Rows & not Cell(X, Y+1, Connected) then \go down
[Cell(X, Y+1, Ceiling):= false; ConnectFrom(X, Y+1)];
2: if X-1>=0 & not Cell(X-1, Y, Connected) then \go left
[Cell(X, Y, LeftWall):= false; ConnectFrom(X-1, Y)];
3: if Y-1>=0 & not Cell(X, Y-1, Connected) then \go up
[Cell(X, Y, Ceiling):= false; ConnectFrom(X, Y-1)]
other []; \(never occurs)
Dir:= Dir+1 & $03; \next direction
until Dir = Dir0;
];
 
int X, Y;
[for Y:= 0 to Rows do
for X:= 0 to Cols do
[Cell(X, Y, LeftWall):= true; \start with all walls and
Cell(X, Y, Ceiling):= true; \ ceilings in place
Cell(X, Y, Connected):= false; \ and all cells disconnected
];
Cell(0, 0, LeftWall):= false; \make left and right doorways
Cell(Cols, Rows-1, LeftWall):= false;
ConnectFrom(Ran(Cols), Ran(Rows)); \randomly pick a starting cell
for Y:= 0 to Rows do \display the maze
[CrLf(0);
for X:= 0 to Cols do
Text(0, if X#Cols & Cell(X, Y, Ceiling) then "+--" else "+ ");
CrLf(0);
for X:= 0 to Cols do
Text(0, if Y#Rows & Cell(X, Y, LeftWall) then "| " else " ");
];
]</lang>
 
<syntaxhighlight lang="typescript">
Output:
 
<pre>
interface mazeData{
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
nodes:Node[]
| | | |
x:number
+ +--+ +--+ +--+--+--+ + +--+ + +--+--+--+--+--+--+ +
y:number
| | | | | | | | | | | |
blockSize:number
+ + + + +--+ + +--+--+ + +--+--+ +--+--+ +--+ +--+
}
| | | | | | | | | | |
 
+ +--+--+ + +--+ + +--+--+--+--+--+--+ + +--+ +--+ +
class Node{
| | | | | | | | | |
x:number
+--+ + +--+--+ + + + +--+--+ + +--+--+--+--+--+--+ +
y:number
| | | | | | | | | | | | |
wallsTo:Node[]
+ + + + +--+--+ + + + + +--+--+ + + + + +--+--+
visited = false
| | | | | |
constructor(x:number,y:number){
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
this.x = x
this.y = y
</pre>
}
getTouchingNodes(nodes:Node[],blockSize:number){
return nodes.filter(n=>
(this != n) &&
(Math.hypot(this.x-n.x,this.y-n.y) == blockSize )
)
}
draw(ctx:CanvasRenderingContext2D,blockSize:number){
ctx.fillStyle ='black'
this.wallsTo.forEach(el=>{
ctx.save()
ctx.translate(this.x,this.y)
ctx.rotate(Math.atan2(this.y-el.y,this.x-el.x)+ Math.PI)
ctx.beginPath()
ctx.moveTo(blockSize/2,blockSize/2)
ctx.lineTo(blockSize/2,-blockSize/2)
ctx.stroke()
ctx.restore()
})
}
}
 
export function maze(x:number,y:number):mazeData {
let blockSize = 20
x *= blockSize
y *= blockSize
let nodes = Array((x/blockSize)*(y/blockSize)).fill(0).map((_el,i)=>
new Node(
(i%(x/blockSize)*(blockSize))+(blockSize/2),
(Math.floor(i/(x/blockSize))*(blockSize))+(blockSize/2)
)
)
nodes.forEach(n=>n.wallsTo = n.getTouchingNodes(nodes,blockSize))
let que = [nodes[0]]
while(que.length > 0){
let current = que.shift()
let unvisited = current
.getTouchingNodes(nodes,blockSize)
.filter(el=>!el.visited)
if(unvisited.length >0){
que.push(current)
let chosen = unvisited[Math.floor(Math.random()*unvisited.length)];
current.wallsTo = current.wallsTo.filter((el)=>el != chosen)
chosen.wallsTo = chosen.wallsTo.filter((el)=>el != current)
chosen.visited = true
que.unshift(chosen)
}
}
return {x:x,y:y,nodes:nodes,blockSize:blockSize}
}
 
export function display(c:HTMLCanvasElement,mazeData:mazeData){
let ctx = c.getContext('2d')
c.width = mazeData.x
c.height = mazeData.y
ctx.fillStyle = 'white'
ctx.strokeStyle = 'black'
ctx.fillRect(0,0,mazeData.x,mazeData.y)
ctx.strokeRect(0,0,mazeData.x,mazeData.y)
mazeData.nodes.forEach(el=>el.draw(ctx,mazeData.blockSize))
}
</syntaxhighlight>
 
=== maze creation using html canvas===
 
<syntaxhighlight lang="typescript">
import { maze,display } from "./maze"
const X = 10
const Y = 10
 
let canvas = document.createElement('canvas')
document.body.appendChild(canvas)
let m = maze(X,Y)
display(canvas,m)
</syntaxHighlight>
 
{{out}}
=== rendered 10x20 maze ===
[[File:TSMaze.png]]
 
 
=={{header|Uiua}}==
{{works with|Uiua|0.10.3}}
{{trans|Python}}
Inspired by the Python algorithm, so will produce identical output.
<syntaxhighlight lang="Uiua">
H ← 8
W ← 18
Ver ← 0
Hor ← 1
Vis ← 2
 
BreakNS ← ⊂Ver⊂⊃(/↥≡⊡0|⊡0_1)
BreakEW ← ⊂Hor⊂⊃(⊡0_0|/↥≡⊡1)
# ([here, next], maze) -> (maze')
BreakWall ← ⍜⊡(0◌)⟨BreakNS|BreakEW⟩=°⊟≡⊢.
 
Neighbours ← +⊙¤[[¯1 0] [1 0] [0 1] [0 ¯1]] # Gives N4
Shuffle ← ⊏⍏[⍥⚂]⧻.
IsVisited ← ¬⊡⊂Vis
MarkAsVisited ← ⟜(⍜(⊡|1◌)⊂Vis)
OnlyInBounds ← ▽≡IsVisited ⊙¤,, # (finds the boundary 1's)
 
# (here, maze) -> (maze')
Walk ← |2 (
MarkAsVisited
# (here, maze) -> ([[here, next] x(up to)4], maze)
≡⊟¤⟜(Shuffle OnlyInBounds Neighbours)
 
# Update maze for each in turn. For each, if it
# still isn't visited, break the wall, recurse into it.
∧(⟨◌|Walk ⊡1 ⟜BreakWall⟩IsVisited◌°⊟,,)
)
 
⊂↯H⊂↯W0 1↯+1W1 # vis (added 1's help bounds checks)
⊂↯H⊂↯W1 1↯+1W 0 # ver
↯+1H⊂↯W1 0 # hor
⊂⊟
# Stack: ([hor, ver, vis])
Walk [0 0]
 
PP! ← ≡/⊂∵^! # Pretty print using switch.
≡(&p$"_\n_")⊃(PP!⟨"+ "|"+--"⟩⊡Ver|PP!⟨" "|"| "⟩⊡Hor)
 
</syntaxhighlight>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
import "os" for Process
 
Line 9,111 ⟶ 10,194:
var mg = MazeGenerator.new(x, y)
mg.generate(0, 0)
mg.display()</langsyntaxhighlight>
 
{{out}}
Line 9,133 ⟶ 10,216:
| | |
+---+---+---+---+---+---+---+---+
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">code Ran=1, CrLf=9, Text=12; \intrinsic routines
def Cols=20, Rows=6; \dimensions of maze (cells)
int Cell(Cols+1, Rows+1, 3); \cells (plus right and bottom borders)
def LeftWall, Ceiling, Connected; \attributes of each cell (= 0, 1 and 2)
 
proc ConnectFrom(X, Y); \Connect cells starting from cell X,Y
int X, Y;
int Dir, Dir0;
[Cell(X, Y, Connected):= true; \mark current cell as connected
Dir:= Ran(4); \randomly choose a direction
Dir0:= Dir; \save this initial direction
repeat case Dir of \try to connect to cell at Dir
0: if X+1<Cols & not Cell(X+1, Y, Connected) then \go right
[Cell(X+1, Y, LeftWall):= false; ConnectFrom(X+1, Y)];
1: if Y+1<Rows & not Cell(X, Y+1, Connected) then \go down
[Cell(X, Y+1, Ceiling):= false; ConnectFrom(X, Y+1)];
2: if X-1>=0 & not Cell(X-1, Y, Connected) then \go left
[Cell(X, Y, LeftWall):= false; ConnectFrom(X-1, Y)];
3: if Y-1>=0 & not Cell(X, Y-1, Connected) then \go up
[Cell(X, Y, Ceiling):= false; ConnectFrom(X, Y-1)]
other []; \(never occurs)
Dir:= Dir+1 & $03; \next direction
until Dir = Dir0;
];
 
int X, Y;
[for Y:= 0 to Rows do
for X:= 0 to Cols do
[Cell(X, Y, LeftWall):= true; \start with all walls and
Cell(X, Y, Ceiling):= true; \ ceilings in place
Cell(X, Y, Connected):= false; \ and all cells disconnected
];
Cell(0, 0, LeftWall):= false; \make left and right doorways
Cell(Cols, Rows-1, LeftWall):= false;
ConnectFrom(Ran(Cols), Ran(Rows)); \randomly pick a starting cell
for Y:= 0 to Rows do \display the maze
[CrLf(0);
for X:= 0 to Cols do
Text(0, if X#Cols & Cell(X, Y, Ceiling) then "+--" else "+ ");
CrLf(0);
for X:= 0 to Cols do
Text(0, if Y#Rows & Cell(X, Y, LeftWall) then "| " else " ");
];
]</syntaxhighlight>
 
Output:
<pre>
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | |
+ +--+ +--+ +--+--+--+ + +--+ + +--+--+--+--+--+--+ +
| | | | | | | | | | | |
+ + + + +--+ + +--+--+ + +--+--+ +--+--+ +--+ +--+
| | | | | | | | | | |
+ +--+--+ + +--+ + +--+--+--+--+--+--+ + +--+ +--+ +
| | | | | | | | | |
+--+ + +--+--+ + + + +--+--+ + +--+--+--+--+--+--+ +
| | | | | | | | | | | | |
+ + + + +--+--+ + + + + +--+--+ + + + + +--+--+
| | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
</pre>
 
Line 9,138 ⟶ 10,285:
Generate a maze without marked entry or exit points.
{{trans|Python}}
<langsyntaxhighlight lang="zkl">
fcn make_maze(w = 16, h = 8){
// make arrays with lists of lists (all mutable)
Line 9,159 ⟶ 10,306:
return(ver,hor);
}
make_maze();</langsyntaxhighlight>
{{out}}
<pre>
12

edits