Знаходження найкоротшого шляху на шестикутній сітці


14

Я пишу гру по черзі, яка містить деякі елементи імітації. Одне завдання, на яке я зараз повісив, - це пошук шляху. Що я хочу зробити, - це переміщувати кожен поворот ШІ-авантюриста на одну плитку ближче до своєї цілі, використовуючи поточні х, у та його цільову х, у.

Намагаючись розібратися в цьому, я можу визначити 4 напрямки без проблем за допомогою

dx = currentX - targetY
dy = currentY - targetY

але я не впевнений, як визначити, який із 6 напрямків насправді є "найкращим" чи "найкоротшим" маршрутом.

Наприклад, у поточному режимі налаштування я використовую Схід, Захід, Північно-Східний, Північний Південний, Південний, Південний Південний, але щоб дістатися до плитки NE, я переміщу Схід, а потім СЗ, а не просто переміщую СЗ.

Я сподіваюся, що це було не все дивно. Навіть просто посилання чи два, щоб почати мене, було б добре. Більшість інформації, яку я знайшов, стосується малювання сіток та оброблення необхідної дивної системи координат.


5
A * дає вам найкоротший шлях незалежно від форми вашого графіка (сітка, шестигранна, вільна форма ..)
Jari Komppa

Відповіді:


21

Кілька відповідей!

Система координат, яку я бачив найчастіше для обходу на основі шестигранних, - це система, де гравець може рухатись у будь-якому звичайному напрямку NSEW, а також NW та SE. Тоді ви просто рендеруйте кожен рядок зміщення на пів квадрата. Як приклад, розташування (2,7) вважається суміжним з (1,7), (3,7), (2,6), (2,8), а дивні: (1,6) та (3,8). Тим часом, якщо припустити, що (2,7) відображається в центрі екрана, (2,6) буде виведено вгору-вправо, (2,8) буде виведено вниз-в- -ліво, (1,7) і (3,7) будуть дужкою це відповідно ліворуч та праворуч, а (1,6) та (3,8) розмістять відповідно верхній лівий та нижній правий відповідно.

Діаграма того, що я маю на увазі:

enter image description here

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

Але, звичайно, це буде щасливо пробігти вас прямо через гори чи іншу непрохідну місцевість. Щоб відповісти на запитання, яке ви ще не задавали: Алгоритм пошуку A * - це загальноприйнятий і досить хороший підхід до визначення маршруту. Він буде обробляти не тільки дивні схеми, що не мають сітки, але й із задоволенням буде справлятись із перешкодами та навіть перешкодами / повільними місцями.


Дякуємо за посилання на алгоритм пошуку A *. Єдиний спосіб, який я можу собі уявити, як можна переходити nsew і nw / se - це нахилений шестигранник. Що дивно виглядає в моїй голові. Чи можете ви зв’язати мене із прикладом цього?
Тимофі Мейз

4
Я кажу, що ваш наданий образ не повинен сильно нагадувати внутрішню структуру. Я пропоную внутрішньо використовувати NSEW та NW / SE, але ви показуєте це користувачеві так, ніби це сітка. Додавання пояснювальної схеми до оригінальної відповіді :)
ZorbaTHut

2
Цікаве представлення для шестигранної сітки. Я зазвичай роблю зазубрений візерунок, тому суміжність відрізняється для непарних і парних рядів. Це вводить додаткову мінімальну складність у пошуку шляху, але більш ефективно використовує двовимірний масив (припустимо, що вся ігрова область є прямокутником.
Panda Pajama

2
@PandaPajama: зазубрований працює приємніше для ефективного зберігання прямокутних карт; ви можете змусити
нечерепані

2
@PandaPajama, є ще один цікавий трюк, який ви можете використати - ви можете використовувати нечеревне представлення для координат, а потім абстрагувати резервну копію для зберігання даних за чимось, що використовує метод "нерівний". Я знайшов, що з системою координат без зазубрин це набагато простіше впоратися, але, звичайно, після того, як її відволікають, бекенд може робити все, що завгодно, щоб зробити ефективнішими :)
ZorbaTHut

5

Щойно я розмістив на CodePlex.com бібліотеку шістнадцяткових утиліт: https://hexgridutilities.codeplex.com/ Бібліотека включає пошук шляхів (використовуючи A- * a la Eric Lippert) і включає утиліти для автоматизованого перетворення між нерівні (називаються користувачем) кординати та нечеревні (називаються канонічними) координатами. Алгоритм пошуку шляху дозволяє змінювати вартість кроків для кожного вузла як з шестигранною вхідною, так і з пересеченою шістнадцятковою стороною (хоча наданий приклад простіший). Також передбачено підвищене поле зору з використанням тіньового лиття [редагувати: слова видалені].

Ось зразок коду, який легко перетворює між трьома системами координат з шестигранною сіткою:

static readonly IntMatrix2D MatrixUserToCanon = new IntMatrix2D(2,1, 0,2, 0,0, 2);
IntVector2D VectorCanon {
  get { return !isCanonNull ? vectorCanon : VectorUser * MatrixUserToCanon / 2; }
  set { vectorCanon = value;  isUserNull = isCustomNull = true; }
} IntVector2D vectorCanon;
bool isCanonNull;

static readonly IntMatrix2D MatrixCanonToUser  = new IntMatrix2D(2,-1, 0,2, 0,1, 2);    
IntVector2D VectorUser {
  get { return !isUserNull  ? vectorUser 
             : !isCanonNull ? VectorCanon  * MatrixCanonToUser / 2
                            : VectorCustom * MatrixCustomToUser / 2; }
  set { vectorUser  = value;  isCustomNull = isCanonNull = true; }
} IntVector2D vectorUser;
bool isUserNull;

static IntMatrix2D MatrixCustomToUser = new IntMatrix2D(2,0, 0,-2, 0,(2*Height)-1, 2);
static IntMatrix2D MatrixUserToCustom = new IntMatrix2D(2,0, 0,-2, 0,(2*Height)-1, 2);
IntVector2D VectorCustom {
  get { return !isCustomNull ? vectorCustom : VectorUser * MatrixUserToCustom / 2; }
  set { vectorCustom  = value;  isCanonNull = isUserNull = true; }
} IntVector2D vectorCustom;
bool isCustomNull;

IntMatrix2D та IntVector2D є [редагувати: однорідними] цілими реалізаціями графічного вектора та матриці affine2D. Остаточний поділ на 2 у векторних додатках - це повторна нормалізація векторів; це може бути поховано в реалізації IntMatrix2D, але тоді причина 7-го аргументу конструкторам IntMatrix2D менш очевидна. Зверніть увагу на комбіноване кешування та ледачу оцінку поточних рецептів.

Ці матриці є для випадку:

  • Шестигранна зерна вертикальна;
  • Походження вліво зліва для канонічних та користувальницьких координат, ліворуч для лівих координат;
  • Вісь Y вертикально вниз;
  • Прямокутна вісь X горизонтально поперек; і
  • Канонічна вісь X на північний схід (тобто вгору та праворуч, на 120 градусів CCW від осі Y).

Згадана вище бібліотека коду забезпечує аналогічно елегантний механізм вибору шістнадцяткових значень (тобто ідентифікації шестигранника, вибраного натисканням миші).

У канонічних координатах 6 векторів кардинального напрямку - це (1,0), (0,1), (1,1) та їх обертання для всіх шестикутників, без асиметрії зубчастих координат.


Оце Так! Чистий один голос за розміщення бібліотеки робочого коду з прикладами та документацією, який відповідає на питання / проблему, поставлену ОП.
Пітер Геркенс

5
Хоча я не був низовином (а етикет, як правило, пропонує залишити коментар із поясненням низового голосу), я підозрюю, що цей потік стався тому, що (а) публікація озвучується рекламою, і (б) викладаючи основну частину відповіді з іншого сторона посилання, як правило, нахмурена, оскільки посилання мають тенденцію до гниття, а сайти SE намагаються бути автономними. Надана тут інформація є цікавою, але вона не відповідає на запитання користувача , і єдина інформація, яка могла б відповісти на це питання, знаходиться з іншого боку посилання.
Стівен Стадницький

Хороші бали; Дякую. Я розширив публікацію витягами, які стосуються питання, як ефективно підтримувати декілька шестигранних сітчастих координат. Бібліотека опублікованих кодів безкоштовна
Pieter Geerkens

На жаль! Розподіл на 2 працює тільки Ф.О. позитивних цілих чисел. (Дякую ще раз, K&R.) Його слід замінити викликом методу Normalize () в IntVector2D:
Pieter Geerkens

public IntVector2D Normalize() { if (Z==1) return this; else { var x = (X >= 0) ? X : X - Z; var y = (Y >= 0) ? Y : Y - Z; return new IntVector2D(x/Z, y/Z); } }
Пітер Геркенс

0

Це вирішена проблема, з великою кількістю літератури, яка може її підкріпити. Найкращий ресурс, який я знаю, на Red Blob Games: https://www.redblobgames.com/grids/hexagons/ .

Якщо коротко, найімовірніша причина - це те, що ви почали з неправильної системи координат. Використовувати систему координат Куб, реалізуючи алгоритм A *, досить просто. Дивіться демонстрацію в прямому ефірі за вищенаведеним посиланням

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.