Maze generation: Difference between revisions

→‎{{header|C}}: simplified somewhat
(→‎{{header|Perl}}: shortened somewhat)
(→‎{{header|C}}: simplified somewhat)
Line 297:
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
 
#define DOUBLE_SPACE 1
 
#if DOUBLE_SPACE
typedef unsigned char cell;
# define SPC " "
enum { U = 1, D = 2, L = 4, R = 8, V = 16 };
#else
# define SPC " "
#endif
 
wchar_t glyph[] = L""SPC"│││─┘┐┤─└┌├─┴┬┼"SPC"┆┆┆┄╯╮ ┄╰╭ ┄";
wchar_t glyph[] =
 
L" │││─┘┐┤─└┌├─┴┬┼ ┆┆┆┄╯╮ ┄╰╭ ┄";
typedef unsigned char byte;
enum { N = 1, S = 2, W = 4, E = 8, V = 16 };
 
byte **cell;
int w, h, avail;
#define each(i, x, y) for (i = x; i <= y; i++)
 
int irand(int n)
{
int r, rand_maxrmax = RAND_MAXn -* (RAND_MAX %/ n);
while ((r = rand()) >= rand_maxrmax);
return r / (rand_maxRAND_MAX/n);
}
 
void show()
#define FOR(i, h) for(i = 0; i <= h; i++)
cell **grid(int w, int h)
{
int i, j, c;
each(i, 0, 2 * h) {
cell **x = malloc(sizeof(cell*) * h + h * w);
each(j, 0, 2 * w) {
x[0] = (cell*)(x + h);
FOR(i, c h-1)= xcell[i+1] = x[ij] + w;
if (c > V) printf("\033[31m");
FOR(i, h-1) FOR(j, w-1) x[i][j] = 0;
printf("%lc", glyph[c]);
return x;
if (c > V) printf("\033[m");
}
}
 
putchar('\n');
int rand_neighbor(cell **c, int w, int h, int x, int y, int *x2, int *y2) {
int d, ofx[] = {1, -1, 0, 0}, ofy[] = {0, 0, -1, 1};
int i, j, cnt = 0;
FOR(d, 3) {
j = x + ofx[d], i = y + ofy[d];
if (j < 0 || j >= w || i < 0 || i >= h || (c[i][j] & V))
continue;
if (!irand(++cnt)) *x2 = j, *y2 = i;
}
return cnt;
}
 
inline int buildmax(cellint **ca, int w,b) int{ h,return inta x,>= intb y,? inta avail): {b; }
inline int min(int a, int b) { return b >= a ? a : b; }
int x2, y2;
c[y][x] |= V;
 
static int dirs[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
while (avail) {
void walk(int x, int y)
if (!rand_neighbor(c, w, h, x, y, &x2, &y2)) break;
{
if (x2 > x) c[y][x] |= R, c[y][x2] |= L; else
if int (x2i, <t, x)x1, cy1, d[y][x4] |= L{ 0, c[y][x2]1, |=2, R;3 else};
if (y2 > y) c[y][x] |= D, c[y2][x] |= U; else
if (y2 < y) c[y][x] |= U, c[y2][x] |= D;
 
cell[y][x] |= V;
avail = build(c, w, h, x2, y2, avail - 1);
avail--;
}
 
for (x1 = 3; x1; x1--)
return avail;
if (x1 != (y1 = irand(x1 + 1)))
}
i = d[x1], d[x1] = d[y1], d[y1] = i;
 
for (i = 0; avail && i < 4; i++) {
x1 = x + dirs[ d[i] ][0], y1 = y + dirs[ d[i] ][1];
 
if (cell[y1][x1] & V) continue;
cell** make_maze(int w, int h)
 
{
/* break walls */
cell **cells = grid(w, h);
if (x1 == x) {
build(cells, w, h, 0, 0, w * h - 1);
t = (y + y1) / 2;
return cells;
cell[t][x+1] &= ~W, cell[t][x] &= ~(E|W), cell[t][x-1] &= ~E;
} else if (y1 == y) {
t = (x + x1)/2;
cell[y-1][t] &= ~S, cell[y][t] &= ~(N|S), cell[y+1][t] &= ~N;
}
walk(x1, y1);
}
}
 
int walksolve(cell **c, cell **s, int w, int h, int x, int y, int x2tox, int y2toy)
{
int i, jt, dx1, dirs[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}y1;
 
scell[y][x] |= V;
if (yx == y2tox && xy == x2toy) return 1;
 
FOReach(di, 0, 3) {
ifx1 (!(c= x + dirs[yi][x0], &y1 (1= <<y d)))+ continuedirs[i][1];
iif = y + dirs(cell[dy1][1x1]) continue;
j = x + dirs[d][0];
 
/* mark path */
if (i < 0 || i >= h || j < 0 || j >= w) continue;
if (s[i][j]x1 &== Vx) continue;{
t = (y + y1)/2;
if (cell[t][x] || !solve(x1, y1, tox, toy)) continue;
 
cell[t-1][x] |= S, cell[t][x] |= V|N|S, cell[t+1][x] |= N;
if (walk(c, s, w, h, j, i, x2, y2)) break;
} else if (y1 == y) {
}
t = (x + x1)/2;
if (cell[y][t] || !solve(x1, y1, tox, toy)) continue;
 
cell[y][t-1] |= E, cell[y][t] |= V|E|W, cell[y][t+1] |= W;
if (d <= 3) {
}
s[y][x] |= (1 << d);
if (d <= 1) s[i][j] |= 1 << (1 - d);
else s[i][j] |= 1 << (5 - d);
return 1;
}
 
/* backtrack */
cell[y][x] &= ~V;
return 0;
}
 
void make_maze()
void show_maze(cell **c, cell **s, int w, int h)
{
int i, j, x, y;
cellint **tileh2 = grid(2 *w h + 12, w2 = 2 *h w + 1)2;
byte **p;
 
p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);
FOR(i, 2*h) FOR(j, 2*w)
tile[i][j] = ((j&1) ? 0 : (U|D)) | ((i&1) ? 0 : (L|R));
 
FORp[1] = (i, 2byte*h)(p tile[i][0]+ &=h2 ~L,+ tile[i][2*w]) &=+ ~R1;
FOReach(ji, 2*w, h2) tilep[0][ji] &= ~U, tilep[2*h][ji-1] &=+ ~Dw2;
p[0] = p[h2];
cell = &p[1];
 
FOReach(i, h-1, 2 * h + 1) FOR(j,cell[i][-1] = cell[i][w2 w- 1)] = {V;
y each(j, =0, 2 * i +w) cell[-1, x][j] = 2cell[h2 *- 1][j] += 1V;
each(i, 0, h) each(j, 0, 2 * w) cell[2*i][j] |= E|W;
each(i, 0, 2 * h) each(j, 0, w) cell[i][2*j] |= N|S;
each(j, 0, 2 * w) cell[0][j] &= ~N, cell[2*h][j] &= ~S;
each(i, 0, 2 * h) cell[i][0] &= ~W, cell[i][2*w] &= ~E;
 
avail = w * h;
if (c[i][j] & R) {
walk(irand(2) * 2 + 1, irand(h) * 2 + 1);
tile[y-1][x+1] &= ~D;
tile[ y ][x+1] = 0;
tile[y+1][x+1] &= ~U;
}
if (c[i][j] & D) {
tile[y+1][x-1] &= ~R;
tile[y+1][ x ] = 0;
tile[y+1][x+1] &= ~L;
}
if(!s) continue;
 
/* reset visited marker (it's also used by path finder) */
tile[y][x] = s[i][j];
if each(s[i][, 0, 2 * h) each(j], &0, U2 * w) tilecell[y-1i][ x j] |&= ~V|D;
if solve(s[i][j]1, &1, D)2 * w - tile[y+1][, x2 ]* |=h V|U- 1);
if (s[i][j] & L) tile[ y ][x-1] |= V|R;
if (s[i][j] & R) tile[ y ][x+1] |= V|L;
}
 
show();
FOR(i, 2*h) {
FOR(j, 2*w)
printf((tile[i][j] & V) ? "\033[31m%lc\033[m" : "%lc",
glyph[ tile[i][j] ]);
putchar('\n');
}
free(tile);
}
 
int main(int c, char **v[])
{
setlocale(LC_ALL, "");
cell **solu, **maze;
intif (c < 2 || (w = atoi(v[1])) <= 0,) hw = 016;
if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;
 
setlocale(LC_CTYPE, "");
if (!DOUBLE_SPACE) glyph[0] = glyph[16] = L' ';
 
make_maze();
if (c > 2) w = atoi(v[1]), h = atoi(v[2]);
if (w <= 0) w = 16;
if (h <= 0) h = 8;
 
maze = make_maze(w, h);
solu = grid(w, h);
walk(maze, solu, w, h, 0, 0, w-1, h-1);
show_maze(maze, solu, w, h);
/* free(maze); free(solu); */
return 0;
}</lang>default output<lang>┌───┬─────┬─────────┬───────┬───┐
}</lang>output<lang>┌─┬───────┬───────┬─────────────┐
│┄┄╮│╭┄┄┄╮│  ╭┄┄┄┄┄╮│  ╭┄┄┄╮│╭┄╮│
│┆│╭┄┄┄┄┄╮│       │             │
│ │┆│┆──┐┆│ │┆──┬─┐┆└──┆┌─┐┆│┆│┆│
│┆│┆────┐┆└───┐ │ │ ┌───┐ ──────┤
│ │┆│╰┄╮│┆│ │╰┄╮│ │╰┄┄┄╯│ │╰┄╯│┆│
│┆│╰┄┄┄╮│╰┄┄┄╮│ │ │ │   │       │
│ │┆└──┆│┆└─┼──┆│ └─────┤ └─┬─┘┆│
│┆└─┐ │┆└───┐┆└─┤ │ │ │ └─────┐ │
│╰┄╮│ │╰┄┄┄╮│╰┄╮││╰┄┄┄╯│╰┄╮│╭┄╯│          │ ││╭┄╯│
│ └─────┴─┐┆│┆┌─┴───┐ │ │ │ │┆──┤
├─┐┆│ └─┬──┆├─┐┆│ │ │ │ │ ┌───┤ │
│ │┆│   │╭┄╯│ │┆│    │┆│┆│╭┄┄┄╮│ │ │╭┄╮│  │ │╰┄╮│
│ ──────┐ │┆│┆│┆──┐┆└─┤ ┌─┘ └─┐┆│
│ │┆├── │┆──┤ │┆│ ──┴─┘ ├─┘┆│┆│ │
│ │┆│   │╰┄╮│╭┄╯│    │┆│╰┄╯  │╰┄╮│ │╭┄╯│╰┄╮││     │┆│
│ ┌─────┘ │┆├─────┴─┐┆│ │ ──┬─┘┆│
│ │┆└─┬─┴──┆│┆┌─┴───┬───┘┆┌─┴──┆│
│ │       │┆│╭┄┄┄┄┄╮│┆│ │   │╭┄╯│
│ │╰┄╮│╭┄┄┄╯│┆│  ╭┄╮│╭┄┄┄╯│╭┄┄┄╯│
├─┤ ──┬─┬─┘┆│┆┌─┬──┆│┆└─┴─┐ │┆┌─┤
│ └─┐┆│┆┌───┤┆└─┐┆│┆│┆────┤┆┌───┤
│   │╰┄╯│  │╭┄╯│┆│ │╰┄╮│┆│┆│╰┄┄┄╮│┆│ │╭┄╯│╰┄┄┄╮│ │┆│ │
│ └── │ │┆──┘┆│ │┆──┴────┆│ │┆│ │
│ │ └───┘ │ └──┆│┆│┆└────┆│┆└── │
│        │╰┄┄┄╯│  ╰┄┄┄┄┄┄┄╯│  ╰┄╯│╰┄┄┄┄┄╯│╰┄┄┄┄│╰┄┄│
└─────┴───────┴───────────┴─────┘</lang>
└─┴───────┴───────┴───────┴─────┘</lang>
 
=={{header|D}}==
Anonymous user