CubeとPlaneを用いて、迷路を生成する。
let maze1;
function preload() {
maze1 = new Maze(15, 15);
maze1.set_maze_boutaoshi();
}
function setup() {
createCanvas(0, 0);
}
window.addEventListener('load', init);
function init() {
const width = 640;
const height = 480;
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#myCanvas')
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, width / height);
camera.position.set(45, 45, 45);
camera.lookAt(new THREE.Vector3(0, 0, 0));
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshNormalMaterial();
for (let y=0; y<15; ++y) {
for (let x=0; x<15; ++x) {
if (maze1.maze[y][x] == 1) {
const box = new THREE.Mesh(geometry, material);
box.position.set(x+0.5, 0.5, y+0.5);
scene.add(box);
}
}
}
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(15, 15, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xffffff
}));
plane.position.set(7.5, 0, 7.5);
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);
const axes = new THREE.AxesHelper(35);
scene.add(axes);
renderer.render(scene, camera);
}
class Maze {
constructor(width, height, seed=0) {
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.from(new Array(this.height), () => new Array(this.width).fill(this.PATH));
this.dist = Array.from(new Array(this.height), () => new Array(this.width).fill(-1));
this.start = [1, 1];
this.goal = [this.width-2, this.height-2];
randomSeed(seed);
}
set_outer_wall() {
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_inner_wall() {
for (let y = 2; y < this.height-1; y+=2) {
for (let x = 2; x < this.width-1; x+=2) {
this.maze[y][x] = this.WALL;
}
}
return this.maze;
}
set_maze_boutaoshi() {
let wall_x;
let wall_y;
let direction;
this.set_outer_wall();
this.set_inner_wall();
for (let y = 2; y < this.height-1; y+=2) {
for (let x = 2; x < this.width-1; x+=2) {
while (true) {
wall_x = x;
wall_y = y;
if (y == 2) {
direction = floor(random(4));
} else {
direction = floor(random(3));
}
if (direction == 0) {
wall_x += 1;
} else if (direction == 1) {
wall_y += 1;
} else if (direction == 2) {
wall_x -= 1;
} else if (direction == 3) {
wall_y -= 1;
}
if (this.maze[wall_y][wall_x] != this.WALL) {
this.maze[wall_y][wall_x] = this.WALL;
break;
}
}
}
}
return this.maze;
}
set_start_goal(start, goal) {
if (this.maze[start[1]][start[0]] == this.PATH) {
this.start = start;
}
if (this.maze[goal[1]][goal[0]] == this.PATH) {
this.goal = goal;
}
return this.maze;
}
set_dist_bfs(flag=false) {
let queue = [];
this.dist[this.start[1]][this.start[0]] = 0;
queue.push(this.start);
while (queue.length > 0) {
let point = queue.shift();
for (let x of [[0,-1],[1,0],[0,1],[-1,0]]) {
if (this.maze[point[1]+x[1]][point[0]+x[0]] == 0 && this.dist[point[1]+x[1]][point[0]+x[0]] == -1) {
this.dist[point[1]+x[1]][point[0]+x[0]] = this.dist[point[1]][point[0]] + 1;
queue.push([point[0]+x[0],point[1]+x[1]]);
}
if (flag != true) {
if (point[0]+x[0] == this.goal[0] && point[1]+x[1] == this.goal[1]) {
queue = [];
break;
}
}
}
}
return this.dist;
}
set_dist_dfs(flag=false) {
let stack = [];
this.dist[this.start[1]][this.start[0]] = 0;
stack.push(this.start);
while (stack.length > 0) {
let point = stack.pop();
for (let x of [[0,-1],[1,0],[0,1],[-1,0]]) {
if (this.maze[point[1]+x[1]][point[0]+x[0]] == 0 && this.dist[point[1]+x[1]][point[0]+x[0]] == -1) {
this.dist[point[1]+x[1]][point[0]+x[0]] = this.dist[point[1]][point[0]] + 1;
stack.push([point[0]+x[0],point[1]+x[1]]);
}
if (flag != true) {
if (point[0]+x[0] == this.goal[0] && point[1]+x[1] == this.goal[1]) {
stack = [];
break;
}
}
}
}
return this.dist;
}
set_shortest_path() {
let point = this.goal;
let x = [[0,-1],[1,0],[0,1],[-1,0]];
this.maze[point[1]][point[0]] = '*';
while (this.dist[point[1]][point[0]] > 0) {
for (let i = 0; i < x.length; ++i) {
if (this.dist[point[1]][point[0]]-this.dist[point[1]+x[i][1]][point[0]+x[i][0]] == 1) {
if (this.dist[point[1]][point[0]] > 0) {
this.maze[point[1]+x[i][1]][point[0]+x[i][0]] = '*';
point = [point[0]+x[i][0],point[1]+x[i][1]];
}
}
}
}
return this.maze;
}
print_maze() {
this.maze[this.start[1]][this.start[0]] = 'S';
this.maze[this.goal[1]][this.goal[0]] = 'G';
for (let col of this.maze) {
let arr = '';
for(let cell of col) {
if (cell == this.WALL) {
arr += '#';
} else if (cell == this.PATH) {
arr += ' ';
} else if (cell == 'S') {
arr += 'S';
} else if (cell == 'G') {
arr += 'G';
} else if (cell == '*') {
arr += '*';
}
}
console.log(arr);
}
}
print_dist() {
for (let col of this.dist) {
let arr = '';
for (let cell of col) {
if (cell == -1) {
if (Math.max.apply(null, Array.prototype.concat.apply([], this.dist)) == -1) {
arr += '#';
} else {
for (let i = 0; i < str(Math.max.apply(null, Array.prototype.concat.apply([], this.dist))).length; ++i) {
arr += '#';
}
}
} else {
if (str(cell).length == str(Math.max.apply(null, Array.prototype.concat.apply([], this.dist))).length) {
arr += str(cell);
} else {
for (let i = 0; i < str(Math.max.apply(null, Array.prototype.concat.apply([], this.dist))).length-str(cell).length; ++i) {
arr += ' ';
}
arr += str(cell);
}
}
}
console.log(arr);
}
}
}
今回は、以下のように出力される。
generate-maze-js by inoha_naito -p5.js Web Editor
A web editor for p5.js, a JavaScript library with the goal of making coding accessible to artists, designers, educators,...