0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Wilson's algorithm で迷路生成

Last updated at Posted at 2025-11-02

image.png

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;
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?