P5.jsで迷路を作ってみました。このページで操作できると思います。画像をマウスでクリックして選択してから、矢印キーで球を移動します。そうしないとこのページがスクロールしてしまいます。
左上からスタート、右下がゴール。
棒倒し法で作成した迷路はそんなに難しくないみたいです。
コードは下記です。
let mpos = []; // 区画の座標とブロックの有無(0 or 1)
let rc = 35; // 区画の一辺の数(奇数が望ましい)
let bs = 100; // 区画一辺の大きさ
let cl; // 区画の色
let pos;
let directions = [];
let nemn
let emn = 1; // 初期の球の区画番号
let ed = 2; // 向きの初期値
function setup() {
createCanvas(700, 700, WEBGL);
// すべての区画の座標を格納、yには初期値の0
for (let i = 0; i < rc * rc; i++) {
let x = bs / 2 + (i % rc) * bs;
let z = bs / 2 + Math.floor(i / rc) * bs;
mpos.push(createVector(x, 0, z));
}
// 周りの区画の y を 1(ブロックを置く)
for (let i = 0; i < rc * rc; i++) {
let row = Math.floor(i / rc); //行
let col = i % rc; //列
if (row == 0 || row == rc - 1 || col == 0 || col == rc - 1) {
mpos[i].y = 1;
}
}
// 1区画おきにブロックを置いて棒倒しで迷路作成
for (let i = 2; i < rc - 2; i += 2) {
for (let j = 2; j < rc - 2; j += 2) {
let num = i + j * rc;
mpos[num].y = 1;
createMaze(num);
}
}
mpos[1].y = 0; // スタート位置はブロック無し
mpos[rc * rc - 2].y = 0; // ゴール位置にも無し
}
function draw() {
background(0);
// 迷路のセンター
let mazeCenterX = (rc * bs) /2;
let mazeCenterZ = (rc * bs) /2;
// カメラを上空に設置(真上から見下ろす)
camera(
mazeCenterX, -(rc * bs) - 600, mazeCenterZ, // カメラ位置
mazeCenterX, 0, mazeCenterZ - 1, // 注視点
0, 1, 0
);
// 迷路のブロックを描画
for (let i = 0; i < rc * rc; i++) {
pos = mpos[i];
if (pos.y == 1) {
cl = color(207, 139, 110);
stroke(0);
createBox(pos.x, 0, pos.z, bs, bs, bs, cl);
}
}
createBall(emn);
}
// ボックスを作成する関数
function createBox(x, y, z, w, h, d, cl) {
fill(cl);
push();
translate(x, y, z);
box(w, h, d);
pop();
}
function createMaze(num) {
directions = []; // 配列を毎回リセット
let north = num - rc;
let east = num + 1;
let south = num + rc;
let west = num -1;
// 3行目のみ東西南北の4方向を調べる
if (Math.floor(num / rc) == 2) {
if (north >= 0 && mpos[north].y == 0)
directions.push(north);
if (east < rc * rc && mpos[east].y == 0)
directions.push(east);
if (south < rc * rc && mpos[south].y == 0)
directions.push(south);
if (west >= 0 && mpos[west].y == 0)
directions.push(west);
} else { // 4行目以下は北は選択肢から外す
if (east < rc * rc && mpos[east].y == 0)
directions.push(east);
if (south < rc * rc && mpos[south].y == 0)
directions.push(south);
if (west >= 0 && mpos[west].y == 0)
directions.push(west);
}
if (directions.length > 0) {
let idx = floor(random(directions.length));
let chosen = directions[idx];
mpos[chosen].y = 1;
}
}
function createBall(emn) {
pos = mpos[emn];
fill(150, 50, 200);
noStroke();
push();
translate(pos.x, 0, pos.z);
sphere(40);
pop();
}
function keyPressed() {
switch (keyCode) {
case UP_ARROW:
ed = 0;
break;
case RIGHT_ARROW:
ed = 1;
break;
case DOWN_ARROW:
ed = 2;
break;
case LEFT_ARROW:
ed = 3;
break;
}
nextPosition();
}
function nextPosition() {
nemn = emn; // デフォルトは変更なし(動かない)
switch (ed) {
case 0: // UP
if (emn > rc) { // 上端でないとき
nemn = emn - rc;
}
break;
case 1: // RIGHT
if (emn % rc < rc) { // 右端でないとき
nemn = emn + 1;
}
break;
case 2: // DOWN
if (emn < rc * rc - rc) { // 下端でないとき
nemn = emn + rc;
}
break;
case 3: // LEFT
if (emn % rc > 0) { // 左端でないとき
nemn = emn - 1;
}
break;
}
// 移動先が壁でない場合のみ更新(移動)
if (mpos[nemn].y == 0) {
emn = nemn;
}
}