Maze generation: Difference between revisions

Content added Content deleted
(Updated D entry)
(Added AWK example)
Line 508: Line 508:
| | |
| | |
+-+-+-+-+-+-+-+-+-+-+-+</pre>
+-+-+-+-+-+-+-+-+-+-+-+</pre>

=={{header|AWK}}==

<lang awk>#!/usr/bin/awk -f

# Remember: AWK is 1-based, for better or worse.

BEGIN {
# The maze dimensions.
width = 20; # Global
height = 20; # Global
resetMaze();

# Some constants.
top = 1;
bottom = 2;
left = 3;
right = 4;

# Randomize the PRNG.
randomize();

# Visit all the cells starting at a random point.
visitCell(getRandX(), getRandY());
# Show the result.
printMaze();
}

# Wander through the maze removing walls as we go.
function visitCell(x, y, dirList, dir, nx, ny, ndir, pi) {
setVisited(x, y); # This cell has been visited.

# Visit neighbors in a random order.
dirList = getRandDirList();
for (dir = 1; dir <= 4; dir++) {
# Get coordinates of a random neighbor (next in random direction list).
ndir = substr(dirList, dir, 1);
nx = getNextX(x, ndir);
ny = getNextY(y, ndir);
# Visit an unvisited neighbor, removing the separating walls.
if (wasVisited(nx, ny) == 0) {
rmWall(x, y, ndir);
rmWall(nx, ny, getOppositeDir(ndir));
visitCell(nx, ny)
}
}
}

# Display the text-mode maze.
function printMaze( x, y, r, w) {
for (y = 1; y <= height; y++) {
for (pass = 1; pass <= 2; pass++) { # Go over each row twice: top, middle
for (x = 1; x <= width; x++) {
if (pass == 1) { # top
printf("+");
printf(hasWall(x, y, top) == 1 ? "---" : " ");
if (x == width) printf("+");
}
else if (pass == 2) { # left, right
printf(hasWall(x, y, left) == 1 ? "|" : " ");
printf(" ");
if (x == width) printf(hasWall(x, y, right) == 1 ? "|" : " ");
}
}
print;
}
}
for (x = 1; x <= width; x++) printf("+---"); # bottom row
print("+"); # bottom right corner
}

# Given a direction, get its opposite.
function getOppositeDir(d) {
if (d == top) return bottom;
if (d == bottom) return top;
if (d == left) return right;
if (d == right) return left;
}

# Build a list (string) of the four directions in random order.
function getRandDirList( dirList, randDir, nx, ny, idx) {
dirList = "";
while (length(dirList) < 4) {
randDir = getRandDir();
if (!index(dirList, randDir)) {
dirList = dirList randDir;
}
}
return dirList;
}

# Get x coordinate of the neighbor in a given a direction.
function getNextX(x, dir) {
if (dir == left) x = x - 1;
if (dir == right) x = x + 1;
if (!isGoodXY(x, 1)) return -1; # Off the edge.
return x;
}

# Get y coordinate of the neighbor in a given a direction.
function getNextY(y, dir) {
if (dir == top) y = y - 1;
if (dir == bottom) y = y + 1;
if (!isGoodXY(1, y)) return -1; # Off the edge.
return y;
}

# Mark a cell as visited.
function setVisited(x, y, cell) {
cell = getCell(x, y);
if (cell == -1) return;
cell = substr(cell, 1, 4) "1"; # walls plus visited
setCell(x, y, cell);
}

# Get the visited state of a cell.
function wasVisited(x, y, cell) {
cell = getCell(x, y);
if (cell == -1) return 1; # Off edges already visited.
return substr(getCell(x,y), 5, 1);
}

# Remove a cell's wall in a given direction.
function rmWall(x, y, d, i, oldCell, newCell) {
oldCell = getCell(x, y);
if (oldCell == -1) return;
newCell = "";
for (i = 1; i <= 4; i++) { # Ugly as concat of two substrings and a constant?.
newCell = newCell (i == d ? "0" : substr(oldCell, i, 1));
}
newCell = newCell wasVisited(x, y);
setCell(x, y, newCell);
}

# Determine if a cell has a wall in a given direction.
function hasWall(x, y, d, cell) {
cell = getCell(x, y);
if (cell == -1) return 1; # Cells off edge always have all walls.
return substr(getCell(x, y), d, 1);
}

# Plunk a cell into the maze.
function setCell(x, y, cell, idx) {
if (!isGoodXY(x, y)) return;
maze[x, y] = cell
}

# Get a cell from the maze.
function getCell(x, y, idx) {
if (!isGoodXY(x, y)) return -1; # Bad cell marker.
return maze[x, y];
}

# Are the given coordinates in the maze?
function isGoodXY(x, y) {
if (x < 1 || x > width) return 0;
if (y < 1 || y > height) return 0;
return 1;
}

# Build the empty maze.
function resetMaze( x, y) {
delete maze;
for (y = 1; y <= height; y++) {
for (x = 1; x <= width; x++) {
maze[x, y] = "11110"; # walls (up, down, left, right) and visited state.
}
}
}

# Random things properly scaled.

function getRandX() {
return 1 + int(rand() * width);
}

function getRandY() {
return 1 +int(rand() * height);
}

function getRandDir() {
return 1 + int(rand() * 4);
}

function randomize() {
"echo $RANDOM" | getline t;
srand(t);
}
</lang>

Example output:
<pre>
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | |
+---+ +---+ +---+---+ +---+ +---+---+ +---+ +---+---+ + +---+ +
| | | | | | | | | | | | |
+ +---+ + + +---+---+ +---+---+ + +---+ + + +---+---+---+ +
| | | | | | | | |
+ + + +---+ +---+ + +---+ +---+---+ +---+---+ +---+ +---+ +
| | | | | | | | | | | | | |
+---+ + + +---+ +---+ + +---+---+ + + + +---+---+---+ +---+
| | | | | | | | | | |
+ + +---+---+ +---+ +---+---+---+---+ +---+---+ +---+ + +---+ +
| | | | | | | | | | | | |
+ +---+ + + +---+---+ +---+ + + + + +---+ + + + + +
| | | | | | | | | | | | | | |
+ + +---+---+---+ + +---+ + + + +---+---+ + + +---+---+ +
| | | | | | | | | |
+ + +---+---+---+ +---+---+---+ + +---+---+---+ + +---+---+ +---+
| | | | | | | | | |
+ +---+ +---+---+---+ + +---+---+---+---+ + +---+ + + +---+ +
| | | | | | | | | | | | | |
+ + + + +---+ + + + + + + + + + +---+---+ + +---+
| | | | | | | | | | | | | |
+ +---+---+---+ + +---+---+---+ + + + + + +---+ + +---+ +
| | | | | | | | | | | |
+---+ +---+---+---+---+---+ + +---+ +---+---+---+---+ + +---+ + +
| | | | | | | | | | | | |
+ + + +---+ +---+ + +---+ + + +---+ +---+ +---+ + + +
| | | | | | | | | | | |
+ + + +---+---+ +---+---+ + +---+ +---+---+ +---+---+ + +---+
| | | | | | | | | | | | |
+ + + + + +---+ +---+---+---+---+---+ + +---+---+ + +---+ +
| | | | | | | | |
+---+---+ + +---+---+---+---+ + +---+---+---+ +---+---+---+---+ + +
| | | | | | | | | |
+ + +---+ +---+---+ + + +---+ + + +---+---+ +---+---+---+ +
| | | | | | | | | | | | |
+ + +---+---+ + +---+ + +---+ +---+ + + +---+---+ + +---+
| | | | | | | | | | | | |
+ +---+ +---+ + + +---+---+ +---+ +---+ +---+---+ + +---+ +
| | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
</pre>



=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==