迷路の幅と高さをそれぞれ width, height として設定し、
その数値にしたがって穴掘り法で迷路を生成する。
※迷路の幅と高さは5以上の奇数とする。
Canvas.tsx
import React, { useEffect } from 'react';
import p5 from 'p5';
import Maze from './maze';
const sketch = (p: p5) => {
p.setup = () => {
const maze1 = new Maze(p, 15, 15);
maze1.set_maze_anahori();
maze1.print_maze();
}
}
const Canvas = () => {
useEffect(() => {
new p5(sketch)
})
return (
<React.Fragment>
</React.Fragment>
);
}
export default Canvas;
maze.ts
import p5 from 'p5';
class Maze {
p: p5;
PATH: number;
WALL: number;
width: number;
height: number;
maze: number[][] = [];
start: number[] = [];
constructor(p: p5, width: number, height: number, seed: number = 0) {
this.p = p;
this.PATH = 0;
this.WALL = 1;
this.width = width;
this.height = height;
if (this.width < 5 || this.height < 5) {
return;
}
if (this.width%2 === 0) {
this.width++;
}
if (this.height%2 === 0) {
this.height++;
}
this.maze = [...Array(this.height)].map(() => Array(this.width).fill(0));
this.start = [1, 1];
p.randomSeed(seed);
}
set_all_wall(): number[][] {
for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
this.maze[y][x] = this.WALL;
}
}
return this.maze;
}
set_outer_path(): number[][] {
for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
if (x === 0 || y === 0 || x === this.width-1 || y === this.height-1) {
this.maze[y][x] = this.PATH;
}
}
}
return this.maze;
}
set_outer_wall(): number[][] {
for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
if (x === 0 || y === 0 || x === this.width-1 || y === this.height-1) {
this.maze[y][x] = this.WALL;
}
}
}
return this.maze;
}
set_maze_anahori(): number[][] {
let stack: number[][] = [], point: number[] = this.start, directions: number[], direction: number;
this.set_all_wall();
this.set_outer_path();
stack.push(point);
this.maze[point[1]][point[0]] = this.PATH;
while (true) {
if (stack.length === 0) {
break;
}
stack = this.p.shuffle(stack);
point = stack.pop()!;
while (true) {
directions = [];
if (this.maze[point[1]-1][point[0]] === this.WALL && this.maze[point[1]-2][point[0]] === this.WALL) {
directions.push(0);
}
if (this.maze[point[1]][point[0]+1] === this.WALL && this.maze[point[1]][point[0]+2] === this.WALL) {
directions.push(1);
}
if (this.maze[point[1]+1][point[0]] === this.WALL && this.maze[point[1]+2][point[0]] === this.WALL) {
directions.push(2);
}
if (this.maze[point[1]][point[0]-1] === this.WALL && this.maze[point[1]][point[0]-2] === this.WALL) {
directions.push(3);
}
if (directions.length === 0) {
break;
}
direction = directions[this.p.floor(this.p.random(directions.length))];
if (direction === 0) {
stack.push(point);
this.maze[point[1]-1][point[0]] = this.PATH;
this.maze[point[1]-2][point[0]] = this.PATH;
point = [point[0],point[1]-2];
} else if (direction === 1) {
stack.push(point);
this.maze[point[1]][point[0]+1] = this.PATH;
this.maze[point[1]][point[0]+2] = this.PATH;
point = [point[0]+2,point[1]];
} else if (direction === 2) {
stack.push(point);
this.maze[point[1]+1][point[0]] = this.PATH;
this.maze[point[1]+2][point[0]] = this.PATH;
point = [point[0],point[1]+2];
} else if (direction === 3) {
stack.push(point);
this.maze[point[1]][point[0]-1] = this.PATH;
this.maze[point[1]][point[0]-2] = this.PATH;
point = [point[0]-2,point[1]];
}
}
}
this.set_outer_wall();
return this.maze;
}
print_maze(): void {
let arr: string;
for (let row of this.maze) {
arr = '';
for (let cell of row) {
if (cell === this.WALL) {
arr += '#';
} else if (cell === this.PATH) {
arr += ' ';
}
}
console.log(arr);
}
}
}
export default Maze;
今回は、以下のように出力される。
###############
# # # #
##### # # ### #
# # # # # #
# # ### # #####
# # # # #
# # # ####### #
# # # # #
# # ### ### # #
# # # # #
# # ##### # # #
# # # # # # #
# # # # # # # #
# # # # #
###############
参考
迷路生成(穴掘り法) - Algoful
穴掘り法は迷路生成アルゴリズムの一種です。全面壁の状態から穴を掘り進めながら迷路を作ります。シミュレーション機能で生成される過程を確認できます。複雑な迷路が生成できるためおすすめです。C#の実装サンプルを用意しているのでUnityでのゲーム...
[Python] 穴掘り法による迷路生成
迷路生成のアルゴリズム 迷路生成のアルゴリズムは数多くあります。 Maze Classification -M…
自動生成迷路