September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,146 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define DOUBLE_SPACE 1
|
||||
|
||||
#if DOUBLE_SPACE
|
||||
# define SPC " "
|
||||
#else
|
||||
# define SPC " "
|
||||
#endif
|
||||
|
||||
wchar_t glyph[] = L""SPC"│││─┘┐┤─└┌├─┴┬┼"SPC"┆┆┆┄╯╮ ┄╰╭ ┄";
|
||||
|
||||
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, rmax = n * (RAND_MAX / n);
|
||||
while ((r = rand()) >= rmax);
|
||||
return r / (RAND_MAX/n);
|
||||
}
|
||||
|
||||
void show()
|
||||
{
|
||||
int i, j, c;
|
||||
each(i, 0, 2 * h) {
|
||||
each(j, 0, 2 * w) {
|
||||
c = cell[i][j];
|
||||
if (c > V) printf("\033[31m");
|
||||
printf("%lc", glyph[c]);
|
||||
if (c > V) printf("\033[m");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
inline int max(int a, int b) { return a >= b ? a : b; }
|
||||
inline int min(int a, int b) { return b >= a ? a : b; }
|
||||
|
||||
static int dirs[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
|
||||
void walk(int x, int y)
|
||||
{
|
||||
int i, t, x1, y1, d[4] = { 0, 1, 2, 3 };
|
||||
|
||||
cell[y][x] |= V;
|
||||
avail--;
|
||||
|
||||
for (x1 = 3; x1; x1--)
|
||||
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;
|
||||
|
||||
/* break walls */
|
||||
if (x1 == x) {
|
||||
t = (y + y1) / 2;
|
||||
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 solve(int x, int y, int tox, int toy)
|
||||
{
|
||||
int i, t, x1, y1;
|
||||
|
||||
cell[y][x] |= V;
|
||||
if (x == tox && y == toy) return 1;
|
||||
|
||||
each(i, 0, 3) {
|
||||
x1 = x + dirs[i][0], y1 = y + dirs[i][1];
|
||||
if (cell[y1][x1]) continue;
|
||||
|
||||
/* mark path */
|
||||
if (x1 == x) {
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* backtrack */
|
||||
cell[y][x] &= ~V;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void make_maze()
|
||||
{
|
||||
int i, j;
|
||||
int h2 = 2 * h + 2, w2 = 2 * w + 2;
|
||||
byte **p;
|
||||
|
||||
p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);
|
||||
|
||||
p[1] = (byte*)(p + h2 + 2) + 1;
|
||||
each(i, 2, h2) p[i] = p[i-1] + w2;
|
||||
p[0] = p[h2];
|
||||
cell = &p[1];
|
||||
|
||||
each(i, -1, 2 * h + 1) cell[i][-1] = cell[i][w2 - 1] = V;
|
||||
each(j, 0, 2 * w) cell[-1][j] = cell[h2 - 1][j] = V;
|
||||
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;
|
||||
walk(irand(2) * 2 + 1, irand(h) * 2 + 1);
|
||||
|
||||
/* reset visited marker (it's also used by path finder) */
|
||||
each(i, 0, 2 * h) each(j, 0, 2 * w) cell[i][j] &= ~V;
|
||||
solve(1, 1, 2 * w - 1, 2 * h - 1);
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
int main(int c, char **v)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
if (c < 2 || (w = atoi(v[1])) <= 0) w = 16;
|
||||
if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;
|
||||
|
||||
make_maze();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CW 10 /* cell width. This decides how big the output is */
|
||||
|
||||
typedef struct cell_t cell_t, *cell;
|
||||
|
||||
enum { N, E, S, W, V };
|
||||
struct cell_t {
|
||||
unsigned int flags;
|
||||
cell prev, next, nei[4]; /* neighbors */
|
||||
};
|
||||
|
||||
int sx, sy, sz, w, h;
|
||||
|
||||
#define C(y, x) c[(y) * w + x]
|
||||
#define P(y, x) pix[(y) * w2 + x]
|
||||
void draw_maze(cell *c)
|
||||
{
|
||||
#define FOR(a, b) for(a = 0; a < b; a++)
|
||||
FILE *fp;
|
||||
int w2 = w * CW + 8, h2 = h * CW + 7;
|
||||
char *pix = malloc(w2 * h2);
|
||||
memset(pix, 200, w2 * h2);
|
||||
|
||||
void draw_face(int x, int y, int ww, int hh, int px, int py) {
|
||||
int i, j, k, l;
|
||||
cell t;
|
||||
|
||||
px += 2, py += 2;
|
||||
for (i = py; i <= py + hh * CW; i++)
|
||||
memset(&P(i, px), 0, ww * CW+1);
|
||||
|
||||
px++, py++;
|
||||
# define mark(y, x) P(py + CW*i + y, px + CW*j + x) = 255
|
||||
FOR (i, hh) FOR (j, ww) {
|
||||
FOR(k, CW - 1) FOR(l, CW - 1) mark(k, l);
|
||||
|
||||
t = C(y + i, x + j);
|
||||
if (t->flags & (1 << N))
|
||||
FOR (l, CW - 1) mark(-1, l);
|
||||
if (t->flags & (1 << S))
|
||||
FOR (l, CW - 1) mark(CW - 1, l);
|
||||
if (t->flags & (1 << E))
|
||||
FOR (l, CW - 1) mark(l, CW - 1);
|
||||
if (t->flags & (1 << W))
|
||||
FOR (l, CW - 1) mark(l, -1);
|
||||
}
|
||||
}
|
||||
|
||||
draw_face(0, 0, sx, sy, 0, 0);
|
||||
draw_face(0, sy, sx, sz, 0, CW*sy + 1);
|
||||
draw_face(sx, sy, sy, sz, CW*sx + 1, CW*sy + 1);
|
||||
draw_face(sx + sy, sy, sx, sz, CW*(sx + sy) + 2, CW*sy + 1);
|
||||
draw_face(sx + sy + sx, sy, sy, sz, CW*(sx + sy + sx) + 3, CW*sy + 1);
|
||||
draw_face(sx + sy, sy + sz, sx, sy, CW*(sx + sy) + 2, CW*(sy + sz) + 2);
|
||||
|
||||
fp = fopen("maze.pgm", "w+");
|
||||
fprintf(fp, "P5\n%d %d\n255\n", w2, h2);
|
||||
fwrite(pix, 1, w2 * h2, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
cell rand_neighbor(cell x)
|
||||
{
|
||||
cell r = 0;
|
||||
int i, c = 1;
|
||||
for (i = N; i <= W; i++) {
|
||||
if (!x->nei[i] || (x->nei[i]->flags & (1 << V)))
|
||||
continue;
|
||||
if (rand() % c++ == 0)
|
||||
r = x->nei[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void link_cells(cell a, cell b)
|
||||
{
|
||||
int i;
|
||||
for (i = N; i <= W; i++) {
|
||||
if (a->nei[i] != b) continue;
|
||||
a->flags |= 1 << i;
|
||||
break;
|
||||
}
|
||||
for (i = N; i <= W; i++) {
|
||||
if (b->nei[i] != a) continue;
|
||||
b->flags |= 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void walk(cell head)
|
||||
{
|
||||
cell tail = head, p, n;
|
||||
|
||||
while (head) {
|
||||
for (p = head; p; p = n) {
|
||||
p->flags |= 1 << V;
|
||||
n = rand_neighbor(p);
|
||||
if (!n) break;
|
||||
tail->next = n;
|
||||
n->prev = tail;
|
||||
|
||||
tail = n;
|
||||
link_cells(p, n);
|
||||
}
|
||||
while (head && !rand_neighbor(head)) head = head->next;
|
||||
}
|
||||
}
|
||||
|
||||
void make_maze(void)
|
||||
{
|
||||
int i, j;
|
||||
int n = (sx * sy + sx * sz + sy * sz) * 2;
|
||||
cell t, *c;
|
||||
cell_t * cells;
|
||||
|
||||
w = 2 * sx + 2 * sy, h = sy * 2 + sz;
|
||||
cells = calloc(sizeof(cell_t), n);
|
||||
c = calloc(sizeof(cell), w * h);
|
||||
|
||||
for (i = 0; i < sy; i++)
|
||||
for (j = 0; j < sx; j++)
|
||||
C(i, j) = cells + --n;
|
||||
for (; i < sy + sz; i++)
|
||||
for (j = 0; j < w; j++)
|
||||
C(i, j) = cells + --n;
|
||||
for (; i < h; i++)
|
||||
for (j = sx + sy; j < w - sy; j++)
|
||||
C(i, j) = cells + --n;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
for (j = 0; j < w; j++) {
|
||||
t = C(i, j);
|
||||
if (!t) continue;
|
||||
if (i) t->nei[N] = C(i - 1, j);
|
||||
if (i < h - 1) t->nei[S] = C(i + 1, j);
|
||||
if (j) t->nei[W] = C(i, j - 1);
|
||||
if (j < w - 1) t->nei[E] = C(i, j + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < sx; j++) {
|
||||
C(0, j)->nei[N] = C(sy, w - sy - j - 1);
|
||||
C(sy, w - sy - j - 1)->nei[N] = C(0, j);
|
||||
|
||||
C(h - sy - 1, j)->nei[S] = C(h - 1, w - sy - j - 1);
|
||||
C(h - 1, w - sy - j - 1)->nei[S] = C(h - sy - 1, j);
|
||||
}
|
||||
|
||||
for (i = sy; i < sy + sz; i++) {
|
||||
C(i, 0)->nei[W] = C(i, w - 1);
|
||||
C(i, w - 1)->nei[E] = C(i, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < sy; i++) {
|
||||
C(i, 0)->nei[W] = C(sy, w - sy + i);
|
||||
C(sy, w - sy + i)->nei[N] = C(i, 0);
|
||||
|
||||
C(i, sx - 1)->nei[E] = C(sy, sx + sy - i - 1);
|
||||
C(sy, sx + sy - i - 1)->nei[N] = C(i, sx - 1);
|
||||
|
||||
C(h - sy - 1, sx + i)->nei[S] = C(h - 1 - i, sx + sy);
|
||||
C(h - 1 - i, sx + sy)->nei[W] = C(h - sy - 1, sx + i);
|
||||
|
||||
C(sy + sz + i, w - sy - 1)->nei[E] = C(sy + sz - 1, w - sy + i);
|
||||
C(sy + sz - 1, w - sy + i)->nei[S] = C(sy + sz + i, w - sy - 1);
|
||||
}
|
||||
|
||||
walk(C(0, 0));
|
||||
draw_maze(c);
|
||||
}
|
||||
|
||||
int main(int c, char **v)
|
||||
{
|
||||
if (c < 2 || (sx = atoi(v[1])) <= 0) sx = 10;
|
||||
if (c < 3 || (sy = atoi(v[2])) <= 0) sy = sx;
|
||||
if (c < 4 || (sz = atoi(v[3])) <= 0) sz = sy;
|
||||
|
||||
make_maze();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue