Почему поиск пути A* иногда идет по прямой, а иногда по диагонали? (Ява)

Я нахожусь в процессе разработки простой сим-игры на основе 2D-сетки, и у меня есть полнофункциональный поиск пути.

Я использовал ответ, найденный в моем предыдущем вопросе, в качестве основы для реализации поиска пути A *. (Нахождение 2D-игры Java?).

Чтобы показать вам действительно то, о чем я прошу, мне нужно показать вам этот видеозахват экрана, который я сделал. Я просто проверял, как человек будет перемещаться в локацию и обратно, и вот результат...

http://www.screenjelly.com/watch/Bd7d7pObyFo

Разный выбор пути в зависимости от направления, неожиданный результат. Любые идеи?


person Relequestual    schedule 25.07.2009    source источник
comment
Согласен, видео отличная идея.   -  person Mike Burton    schedule 25.07.2009
comment
Да, Screenjelly отлично подходит для таких вещей!   -  person Relequestual    schedule 25.07.2009
comment
Кому интересно, screenjelly позволяет записывать прямо из вашего браузера с помощью веб-апплета Java! а затем связывается с вашей учетной записью Twitter для идентификации. Умная!   -  person Relequestual    schedule 25.07.2009
comment
Вы почти наверняка читали мой ответ и не будете читать его снова, поэтому я вставлю сюда свое последнее редактирование, потому что я думаю, что это, вероятно, самый простой способ помочь себе понять поведение, которое вы видите: если вы Если вы действительно заинтересованы в том, чтобы узнать, что происходит, я бы предложил отобразить этапы поиска A*. Учитывая ваш вопрос, он может быть очень откровенным для вас.   -  person Mike Burton    schedule 25.07.2009
comment
В этом случае алгоритм поиска пути с заливкой будет даже быстрее, чем A*. Для этого потребуется только O (k * n).   -  person Georg Schölly    schedule 25.07.2009
comment
Майк, плохой комментарий в вашем ответе. Reg gs, вполне может подойти, но я только примерно понимаю, как работает A*, и я использовал уже работающий пример, который содержал очень простой интерфейс типа API. Пока я буду придерживаться A*, так как использование ЦП не является проблемой. Если со временем я обнаружу, что это занимает слишком много времени, я обязательно посмотрю на это. Благодарность   -  person Relequestual    schedule 25.07.2009
comment
возможный дубликат Как мне найти самый «Естественно прямой маршрут с использованием A-star (A*)   -  person BlueRaja - Danny Pflughoeft    schedule 17.07.2012
comment
Ссылка либо спам, либо битая.   -  person flup    schedule 23.02.2014


Ответы (9)


Если вы ищете простое решение, могу я предложить немного рандомизации?

Я имею в виду следующее: в примере кода cokeandcode есть вложенные циклы for, которые генерируют «состояния преемника» (используя термин AI). Я имею в виду точку, где он зацикливается на квадрате 3x3 вокруг «текущего» состояния, добавляя новые места в кучу для рассмотрения.

Относительно простое исправление будет (должно :)) немного изолировать этот код и, скажем, сгенерировать связанный список узлов до остальной части этапа обработки. Затем Containers.Shuffle (или это Generics.Shuffle?) этого связанного списка и продолжайте обработку там. По сути, есть процедура, скажем, "createNaiveNeighbors(node)", которая возвращает LinkedList = {(node.x-1,node.y), (node.x, node.y-1)... } (пожалуйста, извините за pidgin Java, я пытаюсь (и всегда терплю неудачу) быть кратким.

Однако после того, как вы создадите связанный список, вы сможете просто выполнить «for (Node n : myNewLinkedList)» вместо

for (int x=-1;x<2;x++) {

    for (int y=-1;y<2;y++) {

И по-прежнему используйте тот же самый код тела!

В идеале это должно было бы как бы «встряхнуть» порядок рассматриваемых узлов и создать пути ближе к диагонали, но без изменения эвристики. Пути по-прежнему будут наиболее эффективными, но обычно ближе к диагонали.

Недостатком, конечно, является то, что если вы идете от А к Б несколько раз, вы можете выбрать другой путь. Если это неприемлемо, вам, возможно, придется рассмотреть более радикальное изменение.

Надеюсь это поможет! -Агор

person agorenst    schedule 25.07.2009
comment
вау, спасибо, Агор. Хотя это не может быть выбрано в качестве ответа на мой точный вопрос, это ответ на мой комментарий WalkLikeHumanHeuristic, который я сделал до того, как увидел это. Не могу сказать, что понимаю все, что вы сказали, но общее представление я понимаю. Я обязательно посмотрю на это. Если вы хотите присоединиться к моей команде в этой игре (включая меня...) и реализовать это, я буду рад попробовать! - person Relequestual; 25.07.2009
comment
Без проблем, рад помочь. Я польщен приглашением, но я все еще учусь (и работаю летом), так что вынужден отказаться. Удачи, однако! - person agorenst; 26.07.2009
comment
Я тоже учусь :) хотя и не делаю мастеров в отличие от тебя. Хорошо, конечно, не торопись. Я все еще ищу работу! - person Relequestual; 26.07.2009
comment
Что еще следует учитывать, так это взвешивание. Это может быть так же просто, как разработать лучший маршрут с точки зрения стоимости: прогулка по траве стоит 2, тогда как прогулка по тропе стоит 1, что побуждает ходить по определенным типам местности, или это можно использовать по-другому, чтобы сказать изменение направление стоит 1 и перемещение стоит 1, чтобы стимулировать движение по прямой линии. Вместо подсчета общего количества ходов вы подсчитываете общую «стоимость» (это одно и то же, пока вы не введете другие «стоимости») - person NibblyPig; 06.04.2010

Оба пути имеют одинаковую длину, поэтому алгоритм отлично справляется со своей задачей — находит кратчайший путь. Однако алгоритм A* не указывает, КАКОЙ кратчайший путь он выберет. Реализации обычно выбирают "первый" кратчайший путь. Не видя вашего, невозможно точно знать, почему, но если вы хотите получать одни и те же результаты каждый раз, вам придется добавить какие-то правила приоритета (чтобы желаемый путь был первым в поиске).

person oggy    schedule 25.07.2009
comment
Если вы посмотрите на первую ссылку и последуете ответу на этот вопрос, страница фактически содержит ссылки на весь код поиска пути, который я использовал. Под следствием у меня есть выбор из 4 эвристик. Эвристика A* (только на основе стоимости), Closest, ClosestSquared и Manhattan. Я попробую остальные 3, так как A * по умолчанию. - person Relequestual; 25.07.2009
comment
Что это за эвристика A*, о которой вы говорите? A* использует currentCost + Assessment_of_remainder (уэристический). Closest, ClosestSquared, Manhattan — это эвристики, но я не знаю ни одной эвристики с названием A*. - person Michael Deardeuff; 25.07.2009
comment
Моя ошибка. Это всего лишь интерфейсный класс! Еще многому учусь! :) Это было на ClosestHeuristic. Попробовал другие 2. ClosestSquaredHeuristic иногда работал немного забавно, в то время как ManhattanHeuristic избегал зигзагов, что выглядит лучше. Интересно, есть ли WalkLikeHumanHeuristic... - person Relequestual; 25.07.2009
comment
Людям не свойственно переходить от одного квадрата сетки к другому! - person Kylotan; 28.07.2009
comment
Да, я знаю, но я имею в виду среду, основанную на 2D-сетке. Думаю, рандомизация ближе всего к тому, что я могу получить. - person Relequestual; 28.07.2009

Причина этого на самом деле довольно проста: путь всегда будет пытаться иметь наименьшую возможную эвристику, потому что он выполняет поиск жадным образом. Приближение к цели – оптимальный путь.

Если бы вы позволили диагональное движение, этого бы не произошло.

person rlbond    schedule 25.07.2009
comment
Знаешь, это имело бы смысл. Я не планирую разрешать диагональное движение, так как это вызывает проблемы с углами комнат. Это всего лишь вторая игра, которую я сделал на Java, первая из которых представляет собой плохое исполнение классической вертолетной игры... так что да, учитесь по ходу дела, старайтесь, чтобы она была достаточно простой. Я ожидаю, что открою его и позволю другим разработчикам внести свою лепту, как только у меня будет что-то хорошее. - person Relequestual; 25.07.2009

Причина в пути, по которому должен идти алгоритм.
Я не знаю эвристики, которую использует ваш A*, но в первом случае он должен сначала пройти до конца туннеля, а затем проложить путь с конца. тоннеля к цели.

Во втором случае простейшие ходы к мишеням идут вниз до удара о стену, а затем прокладывают путь от стены к мишени.

Большинство A*, которые я знаю, работают с эвристикой линии прямой видимости или Манхэттенское расстояние в случае блочный мир. Эта эвристика дает вам кратчайший путь, но в случае препятствий, вынуждающих идти по пути, отличному от прямой видимости, пути зависят от вашей начальной точки.
Алгоритм будет идти по линии прямой видимости как можно дольше.

person Janusz    schedule 25.07.2009

Наиболее вероятным ответом будет то, что если идти прямо на юг, то он сначала приблизится к своей цели; Идя в обратном направлении, это не выбор, поэтому он оптимизирует подпуть кусочно, в результате чего чередующиеся движения вверх / поперек рассматриваются как наилучшие.

Если вы хотите, чтобы он шел по диагонали, возвращаясь назад, вам придется определить некоторые точки интереса вдоль пути (например, вход в туннель) и принять их во внимание в вашей эвристике. В качестве альтернативы вы можете учесть их в своем алгоритме, повторно вычислив любой подпуть, который проходит через точку интереса.

Раньше они делали предварительно скомпилированный статический анализ карт и размещали маркеры для поиска пути в узких местах. В зависимости от того, какова ваша конечная цель, это также может быть хорошей идеей.

Если вы действительно заинтересованы в том, чтобы узнать, что происходит, я предлагаю отобразить этапы поиска A*. Учитывая ваш вопрос, он может быть очень откровенным для вас.

person Mike Burton    schedule 25.07.2009
comment
Спасибо, Майк, я очень люблю Стэк и ценю людей, которые публикуют ответы, поэтому я бы перечитал, когда увидел отредактированную заметку. Спасибо :) Я не уверен, что полностью понимаю, что вы имеете в виду, но я думаю, что понимаю, что вы говорите. Поскольку это игра-симулятор, и со временем все может измениться, я не думаю, что смогу использовать маркеры. Я только ТОЛЬКО понимаю, как это работает, и помню веб-сайт, который показывает прогресс A*, на который я посмотрю. Я мог бы реализовать это в своей игре, хотя я думаю, что это может быть слишком много для меня на моем уровне. Я изменил эвристику на манхэттенскую, и оба раза все прошло гладко. - person Relequestual; 25.07.2009

В каждом случае он предпочитает путь, который быстрее приближает его к целевому узлу, для чего и предназначен A*.

person chaos    schedule 25.07.2009

Если я видел правильно, то сфера движется сначала вправо по прямой, потому что она не может попасть прямо к цели (путь перекрыт). Затем он идет по прямой линии к цели. Это только кажется диагональным.

person Burkhard    schedule 25.07.2009
comment
Я думаю, вы упустили суть. Извините, если я не ясно выразился. Я говорил о сравнении пути туда и обратно. - person Relequestual; 25.07.2009
comment
Ах хорошо. Я не видел всего видео. Я на малом интернет-соединении, точно знаю... - person Burkhard; 25.07.2009
comment
не беспокойся. Я благодарю вас за то, что нашли время, чтобы написать ответ на мой вопрос в любом случае :) всегда благодарен! - person Relequestual; 25.07.2009

Ваш поиск смотрит сначала в направлении «вниз»? Это может объяснить алгоритм. Попробуйте изменить его, чтобы сначала искать «вверх», и я уверен, вы увидите противоположное поведение.

person Ben Childs    schedule 25.07.2009

В зависимости от реализации вашего astar вы увидите разные результаты с одной и той же эвристикой, как уже упоминали многие люди. Это происходит из-за связей, когда два или более пути связывают то, как вы упорядочиваете свой открытый набор, будет определять, как будет выглядеть окончательный путь. Вы всегда получите оптимальный путь, если у вас есть допустимая эвристика, но посещаемые узлы будут увеличиваться с увеличением количества связей, которые у вас есть (по сравнению с эвристикой, производящей не так много связей).

Если вы не считаете, что посещение большего количества узлов является проблемой, я бы предложил использовать рандомизацию (которая является вашим текущим принятым ответом). Если вы считаете, что поиск большего количества узлов является проблемой и хотите оптимизировать, я бы предложил использовать какой-то инструмент разрешения конфликтов. Кажется, вы используете манхэттенское расстояние, если вы используете евклидово расстояние, когда два узла связываются в качестве разрешения конфликтов, вы получите больше прямых путей к цели и посетите меньше узлов. Это, конечно же, без ловушек или препятствий на пути к цели.

Чтобы избежать посещения узлов с блокирующими элементами на пути прямой видимости, я бы предложил найти эвристику, учитывающую эти блокирующие элементы. Конечно, новая эвристика не должна выполнять больше работы, чем обычный поиск по звездам.

Я бы предложил просмотреть мой вопрос, так как он может дать некоторые идеи и решения этой проблемы.

person Tore    schedule 06.04.2010