int cols = 25;
int rows = 25;
int cs = 20; // セルの大きさ
boolean[][] inMaze; // 迷路にもう入ったか
boolean[][] rightOpen; // [x][y] と [x+1][y] がつながっている
boolean[][] downOpen; // [x][y] と [x][y+1] がつながっている
void setup() {
size(501, 501);
inMaze = new boolean[cols][rows];
rightOpen = new boolean[cols-1][rows];
downOpen = new boolean[cols][rows-1];
// 1. 適当な1マスを迷路に入れる
int sx = int(random(cols));
int sy = int(random(rows));
inMaze[sx][sy] = true;
// 2. 全マスが入るまで繰り返す
while (!allIn()) {
// まだ入ってないマスを1つ選ぶ
int ux, uy;
while (true) {
ux = int(random(cols));
uy = int(random(rows));
if (!inMaze[ux][uy]) break;
}
// ループ消去ランダムウォーク開始
ArrayList<Integer> path = new ArrayList<Integer>();
int cur = id(ux, uy);
path.add(cur);
while (!inMaze[xOf(cur)][yOf(cur)]) {
int next = randomNeighbor(cur);
int loopIdx = path.indexOf(next);
if (loopIdx != -1) {
// ループができたので消す
while (path.size() > loopIdx+1) {
path.remove(path.size()-1);
}
} else {
path.add(next);
}
cur = next;
}
// 迷路にパスを追加
for (int i = 0; i < path.size()-1; i++) {
int a = path.get(i);
int b = path.get(i+1);
connect(a, b);
inMaze[xOf(a)][yOf(a)] = true;
}
}
// 描画
background(255);
stroke(0);
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
int x1 = x * cs;
int y1 = y * cs;
// 左端と上端は毎回描く
if (x == 0) line(x1, y1, x1, y1+cs);
if (y == 0) line(x1, y1, x1+cs, y1);
// 右の壁
if (x == cols-1 || !rightOpen[x][y]) {
line(x1+cs, y1, x1+cs, y1+cs);
}
// 下の壁
if (y == rows-1 || !downOpen[x][y]) {
line(x1, y1+cs, x1+cs, y1+cs);
}
}
}
noLoop();
}
// すべてのマスが迷路に入ったか
boolean allIn() {
for (int y = 0; y < rows; y++)
for (int x = 0; x < cols; x++)
if (!inMaze[x][y]) return false;
return true;
}
// 1次元IDにする
int id(int x, int y) {
return x + y * cols;
}
int xOf(int id) {
return id % cols;
}
int yOf(int id) {
return id / cols;
}
// ランダムに上下左右のどれかへ
int randomNeighbor(int id) {
int x = xOf(id);
int y = yOf(id);
int[][] dirs = {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
};
while (true) {
int[] d = dirs[int(random(4))];
int nx = x + d[0];
int ny = y + d[1];
if (0 <= nx && nx < cols && 0 <= ny && ny < rows) {
return this.id(nx, ny);
}
}
}
// 2セルをつなぐ(右か下のどちらか)
void connect(int a, int b) {
int ax = xOf(a), ay = yOf(a);
int bx = xOf(b), by = yOf(b);
if (ax == bx) {
// 縦につなぐ
int yy = min(ay, by);
downOpen[ax][yy] = true;
} else if (ay == by) {
// 横につなぐ
int xx = min(ax, bx);
rightOpen[xx][ay] = true;
}
}
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme
