A* Проблема с следопытом

Denik_Master

Пользователь
Регистрация
21.05.14
Сообщения
1
Реакции
0
Баллы
1
Спасибо, что позволили мне присоединиться к вашим форумам. У меня есть вопрос относительно сценария поиска пути A*, над ответом на который я ломал голову последние пару дней. Я разобрался с большей частью этого, но мои навыки программирования недостаточно хороши, чтобы понять некоторые его части.

Я понимаю, что он выбирает начальную и конечную точку при первой загрузке программы или когда пользователь щелкает мышью и вызывает функцию findPath(). и я могу проследить его до функции CalculatePath() и разобраться с большей частью остального кода, но есть пара строк, которые я просто не понимаю:

Эта линия. Как он может выполнить этот оператор условия, если переменной length еще не присвоено значение:
362 while(длина = открытая.длина)
{...}

Кроме того, что, черт возьми, означает индекс массива [0] в конце:
375 myNode = open.splice(мин, 1)[0];

Вот сценарий:

вар холст = ноль;
вар ctx = ноль;
вар спрайтшит = ноль;
вар spritesheetLoaded = ложь;

вар мир = [[]];

вар worldWidth = 16;
вар worldHeight = 16;

вар tileWidth = 32;
вар tileHeight = 32;

вар pathStart = [worldWidth,worldHeight];
вар pathEnd = [0,0];
вар currentPath = [];

if (typeof console == «неопределено») var console = { log: function() {} };

функция загрузки()
{
console.log('Страница загружена.');
холст = document.getElementById('gameCanvas');
Canvas.width = worldWidth * tileWidth;
Canvas.height = worldHeight * tileHeight;
Canvas.addEventListener("клик", CanvasClick, false);
if (!canvas) alert('Бла!');
ctx = Canvas.getContext("2d");
if (!ctx) alert('Хмм!');
спрайт-таблица = новое изображение();
spritesheet.src = 'spritesheet.png';
spritesheet.onload = загружено;
}

функция загружена()
{
console.log('Спрайт-таблица загружена.');
spritesheetLoaded = правда;
создатьМир();
}
A* Проблема с следопытом
функция createWorld() //********************************************
{
console.log('Создание мира...');

for (var x=0; x {
мир[х] = [];

for (var y=0; y {
мир[х][у] = 0;
}
}

for (var x=0; x {
for (var y=0; y {
если (Math.random() > 0,75)
мир[х][у] = 1;
}
}

текущийПуть = [];
в то время как (currentPath.length == 0)
{
pathStart = [Math.floor(Math.random()*worldWidth),Math.floor(Math.random()*worldHeight)];
pathEnd = [Math.floor(Math.random()*worldWidth),Math.floor(Math.random()*worldHeight)];
если (мир[pathStart[0]][pathStart[1]] == 0)
currentPath = findPath(мир,pathStart,pathEnd);
}
перерисовать();

} // завершение createWorld()****************************************** ****

функция перерисовки()
{
if (!spritesheetLoaded) return;

console.log('перерисовка...');

вар spriteNum = 0;

ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, холст.ширина, холст.высота);

for (var x=0; x {
for (var y=0; y {

переключатель (мир [x] [y])
{
Дело 1:
спрайтнум = 1;
перерыв;
по умолчанию:
спрайтнум = 0;
перерыв;
}

ctx.drawImage(таблица спрайтов,
spriteNum*tileWidth, 0,
ширина плитки,
x*tileWidth, y*tileHeight,
tileWidth, tileHeight);

}
}

console.log('Текущая длина пути: '+currentPath.length);
для (rp=0; rp {
переключатель (рп)
{
случай 0:
спрайтнум = 2; // начинать
перерыв;
случай currentPath.length-1:
спрайтнум = 3; // конец
перерыв;
по умолчанию:
спрайтнум = 4; // узел пути
перерыв;
}

ctx.drawImage(таблица спрайтов,
spriteNum*tileWidth, 0,
ширина плитки,
currentPath[rp][0]*tileWidth,
currentPath[rp][1]*tileHeight,
tileWidth, tileHeight);
}
}

функция CanvasClick(e)
{
вар х;
отличаться;

if (e.pageX != не определено && e.pageY != не определено)
{
х = е.страницаX;
y = e.pageY;
}
еще
{
x = e.clientX + document.body.scrollLeft +
документ.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}

х -= холст.offsetLeft;
y -= холст.offsetTop;

вар ячейка =
[
Math.floor(x/tileWidth),
Math.floor(y/tileHeight)
];

console.log('мы нажали плитку '+cell[0]+','+cell[1]); //@@@@@@@@@@@@

pathStart = pathEnd;// в этот момент pathEnd = [0,0], поэтому pathStart = [0,0]
Конец пути = ячейка; // например, pathEnd = [5,6]

currentPath = findPath(мир,pathStart,pathEnd);
перерисовать();
}

функция findPath(world, pathStart, pathEnd)//@@@@@@@@@@@найти путь
{
вар абс = Math.abs;
вар макс = Math.max;
вар pow = Math.pow;
вар sqrt = Math.sqrt;

вар maxWalkableTileNum = 0;

вар worldWidth = мир [0].length;
вар worldHeight = world.length;
вар worldSize = worldWidth * worldHeight;


вар distanceFunction = ManhattanDistance;
вар findNeighbours = функция () {}; // пустой


функция ManhattanDistance(Точка, Цель)
{ // линейное движение – никаких диагоналей – только стороны света (NSEW)
вернуть abs(Point.x - Goal.x) + abs(Point.y - Goal.y);
}

функция DiagonalDistance(Точка, Цель)
{ // диагональное движение - предполагается, что Diag Dist равен 1, как и кардиналы
return max(abs(Point.x - Goal.x), abs(Point.y - Goal.y));
}

функция EuclideanDistance(Точка, Цель)
{ // диагонали считаются немного дальше сторон света
return sqrt(pow(Point.x - Goal.x, 2) + pow(Point.y - Goal.y, 2));
}


функция Neighbours(x, y) //myNeighbours = Neighbours(myNode.x, myNode.y);
{
вар N = y - 1,
S = у + 1,
Е = х + 1,
Ш = х - 1,

myN = N > -1 && canWalkHere(x, N),
myS = S myE = E myW = W > -1 && canWalkHere(W, y),

результат = [];
если (мойN)
result.push({x:x, y:N});
если (myE)
result.push({x:E, y:y});
если (myS)
result.push({x:x, y:S});
если (myW)
result.push({x:W, y:y});

findNeighbours(myN, myS, myE, myW, N, S, E, W, результат);
вернуть результат;
}

функция canWalkHere(x, y)
{
return ((world[x] != null) &&
(мир[x][y] != ноль) &&
(world[x][y] <= maxWalkableTileNum));
};


функция Node(Parent, Point) // Point = {xathStart[0], yathStart[1]}
{
вар newNode = {
Родитель,
valueoint.x + (Point.y * worldWidth),
xoint.x,
йоинт.й,
ф:0,
г:0
};

вернуть новыйузел;
}

функция расчетаПути()
{

var mypathStart = Node(null, {xathStart[0], yathStart[1]});
var mypathEnd = Node(null, {xathEnd[0], yathEnd[1]});

вар AStar = новый массив (worldSize);

вар open = [mypathStart]; // массив объектов

вар Закрыто = []; // массив объектов

вар результат = [];

вар мои соседи;

вар myNode;

вар myPath;

длина var, max, min, i, j;

в то время как (длина = открытая длина)
{
Макс = WorldSize;
мин = -1;
for(i = 0; i < length; i++) // притворяемся, что длина = 1
{
если (открыть.f <макс)
{
макс = открыто.ф;
мин = я;
}
}
myNode = open.splice(мин, 1)[0];

if(myNode.value === mypathEnd.value)
{
myPath = Closed[Closed.push(myNode) - 1];
делать
{
result.push([myPath.x, myPath.y]);
}
в то время как (myPath = myPath.Parent);
AStar = Закрыто = открыто = [];
результат.обратный();
}
else // или это не целевой узел
{
myNeighbours = Neighbours(myNode.x, myNode.y);
for(i = 0, j = myNeighbours.length; i {
myPath = Node(myNode, myNeighbours); // myNode является родительским
если (!AStar[myPath.value])
{
myPath.g = myNode.g + distanceFunction(myNeighbours, мойУзел);
myPath.f = myPath.g + distanceFunction(myNeighbours, mypathEnd);
open.push(мойПуть);
AStar[myPath.value] = правда;
}
}
Closed.push(myNode);
}
} // продолжаем итерацию, пока список Open не станет пустым
вернуть результат;
}

вернуть расчетный путь();

} // конец функции findPath()
 
Сверху Снизу