Jump Point Search логика

201
21 августа 2018, 20:20

Кто-нибудь пробовал внедрять JPS в Astar? не совсем понимаю логику, опишу пожалуй, как это понял, ознакомившись с теорией и на практике:

  1. Создаем стартовый нод, присваиваем ему координаты начала и конца, кидаем его в открытый список.

  2. Пока количество в открытом списке больше нуля, добавляем данный нод в закрытый список, поп в открытом, далее вызов функции индетификации соседей

  3. в данной функции первым делом ищем соседей (без диагоналей), следующим образом

    public List<PathFinderNode> findNeighbors(PathFinderNode node)
    {
        List<PathFinderNode> neighbors = new List<PathFinderNode>();
        // directed pruning: can ignore most neighbors, unless forced.
         int x = node.X;
         int y = node.Y;
         // get normalized direction of travel
         int dx = (x - node.PX) / Math.Max(Math.Abs(x - node.PX), 1);
         int dy = (y - node.PY) / Math.Max(Math.Abs(y - node.PY), 1);
        // search horizontally/vertically
        if (dx != 0)
        {
            if (walkable(x + dx, y))
                neighbors.Add(new PathFinderNode(x + dx, y, x, y));
            if (walkable(x, y + 1))
                neighbors.Add(new PathFinderNode(x, y + 1, x, y));
            if (walkable(x, y - 1))
                neighbors.Add(new PathFinderNode(x, y - 1, x, y));
        }
        else if (dy != 0)
        {
            if (walkable(x, y + dy))
                neighbors.Add(new PathFinderNode(x, y + dy, x, y));
            if (walkable(x + 1, y))
                neighbors.Add(new PathFinderNode(x + 1, y, x, y));
            if (walkable(x - 1, y))
                neighbors.Add(new PathFinderNode(x - 1, y, x, y));
        }
        else if (dx == 0 && dy == 0)
        {
            neighbors = getNeighborsOf(node);
        }
        return neighbors;
    }
    public List<PathFinderNode> getNeighborsOf(PathFinderNode node)
    {
        int x = node.X;
        int y = node.Y;
        List<PathFinderNode> neighbors = new List<PathFinderNode>();
        bool n = false, s = false, e = false, w = false, ne = false, nw = false, se = false, sw = false;
        // ?
        if (walkable(x, y - 1))
        {
            neighbors.Add(new PathFinderNode(x, y - 1, x, y));
            n = true;
        }
        // ?
        if (walkable(x + 1, y))
        {
            neighbors.Add(new PathFinderNode(x + 1, y, x, y));
            e = true;
        }
        // ?
        if (walkable(x, y + 1))
        {
            neighbors.Add(new PathFinderNode(x, y + 1, x, y));
            s = true;
        }
        // ?
        if (walkable(x - 1, y))
        {
            neighbors.Add(new PathFinderNode(x - 1, y, x, y));
            w = true;
        }
        return neighbors;
    }
    

То есть мы сначала проходимся по соседу, если их не находим, идем по вертикали/горизонтали - в общем с этим гуд, соседей получается найти

  1. Сам класс PathFinderNode состоит из текущей координаты и родительской ((X,Y);(PX,PY)), от нее и идут все расчеты dx и dy

  2. А тут начинаются уже проблемы. Я начинаю перебирать список найденных соседей (коих 4, так как по диагоналям не хожу), и запускаю функцию прыжка

    private PathFinderNode jump(PathFinderNode neighbor, PathFinderNode current, List goals) { if (neighbor.X == -1 || !walkable(neighbor.X, neighbor.Y)) { return null; } if (goals.Contains(neighbor)) return neighbor;

    int dx = neighbor.X - current.X;
    int dy = neighbor.Y - current.Y;
    // check for forced neighbors
    // check horizontally/vertically
    if (dx != 0)
    {
        if ((walkable(neighbor.X, neighbor.Y + 1) && !walkable(neighbor.X - dx, neighbor.Y + 1)) ||
                (walkable(neighbor.X, neighbor.Y - 1) && !walkable(neighbor.X - dx, neighbor.Y - 1)))
        {
            return neighbor;
        }
    }
    else if (dy != 0)
    {
        if ((walkable(neighbor.X + 1, neighbor.Y) && !walkable(neighbor.X + 1, neighbor.Y - dy)) ||
                (walkable(neighbor.X - 1, neighbor.Y) && !walkable(neighbor.X - 1, neighbor.Y - dy)))
        {
            return neighbor;
        }
        // when moving vertically check for horizontal jump points
        PathFinderNode TestNeigbour1 = new PathFinderNode(neighbor.X + 1, neighbor.Y, neighbor.X,neighbor.Y);
        PathFinderNode TestNeigbour2 = new PathFinderNode(neighbor.X - 1, neighbor.Y, neighbor.X, neighbor.Y);
        if (jump(TestNeigbour1, neighbor, goals) != null ||jump(TestNeigbour2, neighbor,goals) != null)
        {
            return neighbor;
        }
    }
    else
    {
        return null; //null
    }
    return jump(new PathFinderNode(neighbor.X + dx, neighbor.Y + dy, neighbor.PX, neighbor.PY), neighbor, goals);
    

    }

По идее, какие-то объекты могут быть пустыми, но этот алгоритм прыгает до края сетки и скидывает всегда null (сетка - двумерный массив со 0 и 1 значением). Не могу понять, что упускаю. Буду благодарен, если поможете ответить. P.S. Сырцы на джаве тут (отсюда и прыгал) https://github.com/kevinsheehan/jps/tree/master/src/org/ksdev/jps

READ ALSO
Не работает удаление через ExecuteNonQuery

Не работает удаление через ExecuteNonQuery

В коде есть следующий участок:

210
Сделать Builder exe

Сделать Builder exe

Имеется проект visual studio на C#, хочу сделать билдер, чтобы вводить некоторые данные, которые нужно изменить в коде и скомпилировать программу...

214
c# - крон на каждый день в 2 часа ночи

c# - крон на каждый день в 2 часа ночи

Как будет крон в ровно 2 часа ночи ежедневно на языке C# ?

236
Локальное вращение

Локальное вращение

Я хочу заствить куб поворачиватся на 90 градусов каждый раз когда я нажимаю на одну из половин экрана(С нажатием и определением сторон экрана...

192