記事の作成日 : 2020/02/16
突然ですが、迷路を生成したくなったので、生成してみようと思います。
// いろいろな関数のなかでも使うグローバルなやつ を宣言
let map = "",
wall = "■",
air = "□",
wh = 0;
// マップを読み込む
function read(x, y) {
return map[x + y * wh];
}
//マップを読み込む(安全版)
function SafeRead(x, y) {
if (x < 0 || y < 0 || x >= wh || y >= wh) {
return "e";
}
return read(x, y);
}
// マップに書き込む
function write(data, x, y) {
map = stringsel(map, x + y * wh, data);
}
// string sel write
function stringsel(str, sel, data) {
var startString = "";
var endString = "";
if (sel != 0) {
startString = str.substring(0, sel);
}
if (sel != str.length) {
endString = str.substring(sel + 1, str.length);
}
if (sel == 0) {
return data + endString;
}
if (sel == str.length) {
return startString + data;
}
return startString + data + endString;
}
// 囲いを作成する関数
function create_box() {
let i;
for (i = 0; i < wh; i++) {
write(wall, i, 0);
write(wall, 0, i);
write(wall, i, wh - 1);
write(wall, wh - 1, i);
}
}
// 棒を作成する関数
function create_stick() {
let x, y, setx = 1,
sety = 1;
for (y = 2; y < wh - 1; y++) {
for (x = 2; x < wh - 1; x++) {
console.log(x + "," + y + " / " + setx + "," + sety);
if (setx == true && sety == true) {
write(wall, x, y);
}
setx = !setx;
}
sety = !sety;
}
}
// 迷路を作成する(棒を倒す)関数
function create_maze() {
let x, y, setx = 1,
sety = 1,
cnt = 0,
r, l, u, d, total, target;
for (y = 2; y < wh - 1; y++) {
for (x = 2; x < wh - 1; x++) {
if (setx == true && sety == true) {
write(wall, x, y);
if (cnt == 0) {
total = "";
r = SafeRead(x + 1, y);
l = SafeRead(x - 1, y);
u = SafeRead(x, y - 1);
d = SafeRead(x, y + 1);
if (r == air) {
total += "r"
}
if (l == air) {
total += "l"
}
if (u == air) {
total += "u"
}
if (d == air) {
total += "d"
}
target = total[Math.round(Math.random() * (total.length - 1))];
if (target == "r") {
write(wall, x + 1, y);
}
if (target == "l") {
write(wall, x - 1, y);
}
if (target == "u") {
write(wall, x, y - 1);
}
if (target == "d") {
write(wall, x, y + 1);
}
}
if (cnt == 1) {
total = "";
r = SafeRead(x + 1, y);
l = SafeRead(x - 1, y);
d = SafeRead(x, y + 1);
if (r == air) {
total += "r"
}
if (l == air) {
total += "l"
}
if (d == air) {
total += "d"
}
target = total[Math.round(Math.random() * (total.length - 1))];
if (target == "r") {
write(wall, x + 1, y);
}
if (target == "l") {
write(wall, x - 1, y);
}
if (target == "d") {
write(wall, x, y + 1);
}
}
}
setx = !setx;
}
sety = !sety;
cnt = 1;
}
}
// 結果表示のための変換
function convert() {
let mapcv = "",
ch;
for (let i = 0; i < (wh * wh); i++) {
ch = map[i];
if (ch == air) {
ch = "<span style='color:rgb(0,0,0,0);'>" + wall + "";
}
mapcv += ch;
if (i % wh == wh - 1) {
mapcv += "<br>"; //String.fromCharCode(10);
}
}
return mapcv;
}
// これが「生成」ボタンが押されて実行される関数です。
function create() {
// マップサイズ設定
wh = document.getElementById("wh").value;
// 文字の決定
wall = "■";
air = "□";
// マップ作成
map = air.repeat(wh * wh);
//囲い作成
create_box();
// 棒を作成
create_stick();
// 迷路を作成(棒を倒す)
create_maze();
// 結果を表示
document.getElementById("map").innerHTML = convert(); // convert()で人が見られる形に修正してから出力
}
// いろいろな関数のなかでも使うグローバルなやつ を宣言
let map = "",
wall = "■",
air = "□",
wh = 0;
/*
mapは、迷路のデータが入る予定です。
wall は壁のデータです。
air は通路のデータです。が、表示する場合には、透明な■(wall の文字 の 透明)に置換されて、マップが崩れるのを防ぎます。
wh は迷路の大きさが入ります。
*/
function create() {
/*
マップサイズ設定
<input type="range" id="wh" min="5" max="99" value="13">
ここから ID"wh" の値を取得します。
横に数値を付けるには、inputの中にもう一つ下記のコードを配置します。
oninput="document.getElementById('ここにIDを入れる').innerHTML=this.value"
HTMLでは、<span id="ここに同じIDを入れる"> を追加します。
*/
wh = document.getElementById("wh").value;
/*
文字の決定
wall は壁です。
air は通路です。が文字がずれてしまうので、表示には使っていません。
*/
wall = "■";
air = "□";
// マップ作成 埋め立てる。
map = air.repeat(wh * wh);
//囲い作成 下のほうで内容の説明
create_box();
// 棒を作成 下のほうで内容の説明
create_stick();
// 迷路を作成(棒を倒す)下のほうで内容の説明
create_maze();
// 結果を表示
document.getElementById("map").innerHTML = convert(); // convert()で人が見られる形に修正してから出力
}
// マップを読み込む 簡単な式。whを使用することに注意。
function read(x, y) {
return map[x + y * wh]; // マップデータ1つを取り出す。
}
//マップを読み込む(安全版) 0 と wh がリミッターになり、規格外の数値が入っても、エラーにならずに結果に「e」が返ってきます。
function SafeRead(x, y) {
if (x < 0 || y < 0 || x >= wh || y >= wh) {
return "e";
}
return read(x, y);
}
// string sel write
/*
マップで使うときは、
str に map を。
sel に 編集位置(数値)を。
data に データを(文字列を上書き)。
*/
function stringsel(str, sel, data) {
var startString = "";
var endString = "";
if (sel != 0) {
startString = str.substring(0, sel);
}
if (sel != str.length) {
endString = str.substring(sel + 1, str.length);
}
if (sel == 0) {
return data + endString;
}
if (sel == str.length) {
return startString + data;
}
return startString + data + endString;
}
// 囲いを作成する関数
function create_box() {
let i;
for (i = 0; i < wh; i++) {
write(wall, i, 0);
write(wall, 0, i);
write(wall, i, wh - 1);
write(wall, wh - 1, i);
}
}
// 棒を作成する関数
function create_stick() {
let x, y, setx = 1,
sety = 1;
for (y = 2; y < wh - 1; y++) {
for (x = 2; x < wh - 1; x++) {
console.log(x + "," + y + " / " + setx + "," + sety);
if (setx == true && sety == true) {
write(wall, x, y);
}
setx = !setx;
}
sety = !sety;
}
}
// 迷路を作成する(棒を倒す)関数
function create_maze() {
let x, y, setx = 1,
sety = 1,
cnt = 0,
r, l, u, d, total, target;
for (y = 2; y < wh - 1; y++) {
for (x = 2; x < wh - 1; x++) {
if (setx == true && sety == true) {
write(wall, x, y);
if (cnt == 0) {
total = "";
r = SafeRead(x + 1, y);
l = SafeRead(x - 1, y);
u = SafeRead(x, y - 1);
d = SafeRead(x, y + 1);
if (r == air) {
total += "r"
}
if (l == air) {
total += "l"
}
if (u == air) {
total += "u"
}
if (d == air) {
total += "d"
}
target = total[Math.round(Math.random() * (total.length - 1))];
if (target == "r") {
write(wall, x + 1, y);
}
if (target == "l") {
write(wall, x - 1, y);
}
if (target == "u") {
write(wall, x, y - 1);
}
if (target == "d") {
write(wall, x, y + 1);
}
}
if (cnt == 1) {
total = "";
r = SafeRead(x + 1, y);
l = SafeRead(x - 1, y);
d = SafeRead(x, y + 1);
if (r == air) {
total += "r"
}
if (l == air) {
total += "l"
}
if (d == air) {
total += "d"
}
target = total[Math.round(Math.random() * (total.length - 1))];
if (target == "r") {
write(wall, x + 1, y);
}
if (target == "l") {
write(wall, x - 1, y);
}
if (target == "d") {
write(wall, x, y + 1);
}
}
}
setx = !setx;
}
sety = !sety;
cnt = 1;
}
}
// 結果表示のための変換
function convert() {
let mapcv = "",
ch;
for (let i = 0; i < (wh * wh); i++) {
ch = map[i];
if (ch == air) {
ch = "<span style='color:rgb(0,0,0,0);'>" + wall + "";
}
mapcv += ch;
if (i % wh == wh - 1) {
mapcv += "<br>";
}
}
return mapcv;
}
<h2>完成例</h2>
<input type="range" id="wh" min="5" max="99" step="2" value="13" oninput="document.getElementById('sizeview').innerHTML=this.value">
<span id="sizeview">13</span>
<input type="button" value="生成" onclick="create()">
<div id="map" style="letter-spacing: -6px; line-height: 0.6em;"></div>