Решено! См. Мой собственный ответ.
Я создаю приложение, в котором есть карта на основе гекса.Для перемещения между гексами требуется определенное количество времени, и я пытаюсь реализовать способ нажать на любой действительный гекс и получить оптимальный путь (если возможно) из текущей позиции игроков.
Вотхитрая часть, только несколько из гексов являются допустимыми местами перемещения, поэтому мне нужно найти путь, чтобы можно было пропустить пустые гексы.В зависимости от «досягаемости» игроков им разрешено пропускать недопустимые пробелы.Так что, если игроки достигли, было франц.3, им разрешено перемещаться на 1, 2 или 3 пробела за один «ход», даже если гексы между ними недопустимы (пусто), но им не разрешено «останавливаться» на недопустимых гексах.
Пример:
![Example image](https://i.imgur.com/KuZFXlY.png)
До сих пор я реализовал скрипт поиска пути A * с помощью следующих ссылок:
Но я не уверен, как реализовать функцию «Прыжки» или «Прыжки» Iищу.Я специально избегал использования «крайних» затрат, потому что это потребовало бы большого количества изменений в моей текущей реализации, а направление вообще не имеет значения.
Моя версия функции A * в третьей ссылкессылка:
public void AStarSearch(MapHex startHex, MapHex goalHex)
{
if (goalHex.empty)
{
Debug.Log("Goal empty.");
return;
}
SimplePriorityQueue<MapHex> frontier =
new SimplePriorityQueue<MapHex>();
frontier.Enqueue(startHex, 0);
cameFrom.Add(startHex, startHex);
costSoFar.Add(startHex, 0);
while (frontier.Count > 0)
{
MapHex current = frontier.Dequeue();
if (current.Equals(goalHex)) break;
foreach (MapHex neighbor in GetNeighbors(current))
{
float newCost = costSoFar[current] + 1;
if (!costSoFar.ContainsKey(neighbor) ||
newCost < costSoFar[neighbor])
{
if (costSoFar.ContainsKey(neighbor))
{
costSoFar.Remove(neighbor);
cameFrom.Remove(neighbor);
}
costSoFar.Add(neighbor, newCost);
cameFrom.Add(neighbor, current);
float priority = newCost +
HexHeuristicDistance(neighbor, goalHex);
frontier.Enqueue(neighbor, priority);
}
}
}
}
Я просто не знаю, как расширить поиск по другим непроходимым гексам или подобным.Мне нужно, чтобы конечный результат был кратчайшим путем до конечного гекса (если возможно), чтобы отобразить маршрут и пройденное расстояние.Любая помощь приветствуется:)
Редактировать: Хорошо, согласно предложению Рузима, я пытаюсь расширить свою функцию "GetNeighbors", чтобы достичь своей цели.Чтобы получить всех «соседей» в диапазоне максимальной скорости, я пытаюсь реализовать код из раздела «Диапазон движения» руководства по шестигранным сеткам Red Blob Games: https://www.redblobgames.com/grids/hexagons/#range (Второй фрагмент кода)
Преобразование из Python оказывается сложной задачей, и я, кажется, создал неэффективного монстра, который может или не может работать:
public IEnumerable<MapHex> GetNeighbors(MapHex hex, int distanceOffset)
{
if (distanceOffset == 0)
{
foreach (Vector2 dir in oddQDirections)
{
MapHex next = allMapHexes.Find(item => item.coordinate == new Vector2(hex.coordinate.x + dir.x, hex.coordinate.y + dir.y));
if (next != null)
{
yield return next;
}
}
}
else
{
List<MapHex> neighbors = new List<MapHex>();
List<MapHex> closeHexesX = new List<MapHex>();
Vector3 hexCubeCoord = OddQToCube(hex.coordinate);
foreach (MapHex closeHex in allMapHexes.FindAll(item => !item.empty && -(distanceOffset + 1) <= -OddQToCube(item.coordinate).x && -OddQToCube(item.coordinate).x <= distanceOffset + 1))
{
closeHexesX.Add(closeHex);
}
foreach (MapHex closeHex in closeHexesX.FindAll(item => Mathf.Max(-(distanceOffset + 1), -OddQToCube(item.coordinate).x - (distanceOffset + 1)) <= -OddQToCube(item.coordinate).y && -OddQToCube(item.coordinate).x <= Mathf.Min((distanceOffset + 1), -OddQToCube(item.coordinate).x + (distanceOffset + 1))))
{
Vector3 cubeCoord = OddQToCube(closeHex.coordinate);
cubeCoord.z = -cubeCoord.x - cubeCoord.y;
neighbors.Add(closeHexesX.Find(item => item.coordinate == CubeToOddQ(hexCubeCoord + cubeCoord)));
}
}
}
Может быть, мне лучше просто запустить GetDistance для каждого гекса ивернуть те, у которых есть расстояние <=, чтобы "достичь" ..? </p>