記事のディレクトリ
画像プレゼンテーション
インターフェースは本当に醜いです
入力形式の迷路:通路;壁0;数字の間のスペースで区切られます;各行は-
間隔が空けられています
コード
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body,
html {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 0;
}
div#content {
display: inline-block;
border: 1px solid black;
position: relative;
}
div#content .child {
box-sizing: border-box;
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid black;
}
div.wall {
background-color: #362E3D;
}
div#position {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background: #362E3D;
left: 40px;
top: 40px;
}
</style>
</head>
<body>
<div id="content">
<div id="position" style="left: 40px;top: 40px;"></div>
</div>
<script>
let map = reLoad(), // 地图录入
re = [], // 标记
road = [], // 路径
count = 0;
let m = map[0].length, //列
n = map.length; // 行
for (let i = 0; i < n; i++) {
let newarr = [];
for (let j = 0; j < m; j++) {
newarr.push(0);
}
re.push(newarr);
}
document.getElementById('content').style.width = m * 100 + "px";
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
let div = document.createElement('div');
div.className = 'child';
if (map[i][j] == 0)
div.className += ' wall';
document.getElementById('content').appendChild(div);
}
}
function dfs(x, y) {
if (x < 0 || x > n - 1 || y < 0 || y > m - 1 || re[x][y] == 1 || map[x][y] == 0) return 0; //走出界外或之前走过或遇到障碍
count++;
if (arguments[2])
road.push(arguments[2]);
if (x == n - 1 && y == m - 1) {
recallMark(arguments[2]);
return 1; //走到终点
}
re[x][y] = 1; //该点标记为走过
dfs(x - 1, y, 'top'); //向上走
dfs(x, y + 1, 'right'); //向右走
dfs(x + 1, y, 'down'); //向下走
dfs(x, y - 1, 'left'); //向左走
if (!(x == 0 && y == 0)) // 最后一次回溯在起点不记录
recallMark(arguments[2]); // 记录回溯路径
re[x][y] = 0; //该点还原为没有走过
}
function recallMark(act) {
switch (act) {
case 'top':
act = 'down';
break;
case 'right':
act = 'left';
break;
case 'down':
act = 'top';
break;
case 'left':
act = 'right';
break;
}
road.push(act);
}
function reLoad() {
let str = prompt("输入地图 用-间隔");
let arr = str.split('-');
let map = [];
for (let i = 0; i < arr.length; i++) {
map.push(arr[i].trim().split(' ').map(Number));
}
return map; // 返回二维数组
}
function draw() {
let div = document.getElementsByClassName('child');
let pos = document.getElementById('position');
let i = 0,
flag = 1;
let timer = setInterval(() => {
if (road[i] == 'right') {
pos.style.left = parseInt(pos.style.left) + 100 + 'px';
}
if (road[i] == 'down') {
pos.style.top = parseInt(pos.style.top) + 100 + 'px';
}
if (road[i] == 'left') {
pos.style.left = parseInt(pos.style.left) - 100 + 'px';
}
if (road[i] == 'top') {
pos.style.top = parseInt(pos.style.top) - 100 + 'px';
}
i++;
if (i == road.length + 1) {
clearInterval(timer);
}
}, 500, i, pos);
}
dfs(0, 0);
draw();
</script>
</body>
</html>
部分的な説明
1. dfs()検索ルート
アルゴリズムコア:迷路検索を実現するためのディープ検索
function dfs(x, y) {
if (x < 0 || x > n - 1 || y < 0 || y > m - 1 || re[x][y] == 1 || map[x][y] == 0) return 0; //走出界外或之前走过或遇到障碍
if (arguments[2])// 排除从头开始,第一次没有第三个参数
road.push(arguments[2]); // 记录路径
if (x == n - 1 && y == m - 1) {
recallMark(arguments[2]); // 会return,提前记录路径
return 1; //走到终点
}
re[x][y] = 1; //该点标记为走过
dfs(x - 1, y, 'top'); //向上走
dfs(x, y + 1, 'right'); //向右走
dfs(x + 1, y, 'down'); //向下走
dfs(x, y - 1, 'left'); //向左走
if (!(x == 0 && y == 0)) // 最后一次回溯在起点不记录
recallMark(arguments[2]); // 记录回溯路径
re[x][y] = 0; //该点还原为没有走过
}
jsシングルスレッドにはスリープがないため、順序は右上、左下です。したがって、すべての結果が最初に記録され(3番目の文字列パラメーターが方向を表すためにdfsに渡されるたびにストレージを容易にするため)、次に結果が記録されます。描画に使用されます。
レコードの配列を使用した道路の進行方向、dfsパラメータ内の反対側recallMark
、逆方向の記録機能を使用して、配列の道路に保存
2. reLoad()は迷路を読みます
function reLoad() {
let str = prompt("输入地图 用-间隔");
let arr = str.split('-');
let map = [];
for (let i = 0; i < arr.length; i++) {
map.push(arr[i].trim().split(' ').map(Number));
}
return map; // 返回二维数组
}
プロンプトによって取得された文字列はstrに格納され、split
各行配列arrはstringメソッドによって分割されます。arrの各項目は、スペースを含む迷路内の数字の行であり、次にarrの各項目(文字列)です。がトラバースtrim
され、文字列メソッドが削除されますスペースを閉じてsplit
からmap(Number)
、文字列の各桁を新しい配列の1つの項目に分割し、文字列を数値に変換して、最後にマップ配列にプッシュし、別の配列への配列は、上記の2次元配列です。