Initial commit
This commit is contained in:
198
Game/Assets/Scripts/Utils/Algorithms/GridTraverseAlgorithm.cs
Normal file
198
Game/Assets/Scripts/Utils/Algorithms/GridTraverseAlgorithm.cs
Normal file
@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace TransportGame.Utils.Algorithms
|
||||
{
|
||||
[Flags]
|
||||
public enum TravelDirections
|
||||
{
|
||||
North = 0x1,
|
||||
NorthEast = 0x2,
|
||||
East = 0x4,
|
||||
SouthEast = 0x8,
|
||||
South = 0x10,
|
||||
SouthWest = 0x20,
|
||||
West = 0x40,
|
||||
NorthWest = 0x80,
|
||||
NESW = North | East | West | South,
|
||||
All = North | NorthEast | East | SouthEast | South | SouthWest | West | NorthWest,
|
||||
}
|
||||
|
||||
public abstract class GridTraverseAlgorithm<T>
|
||||
{
|
||||
protected class TraverseVisitItem<TItem>
|
||||
{
|
||||
public TItem Item { get; private set; }
|
||||
public int X { get; private set; }
|
||||
public int Y { get; private set; }
|
||||
|
||||
public TraverseVisitItem(TItem item, int x, int y)
|
||||
{
|
||||
Item = item;
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateDirections(out int[] dx, out int[] dy, TravelDirections dirs)
|
||||
{
|
||||
List<int> ddx = new List<int>();
|
||||
List<int> ddy = new List<int>();
|
||||
|
||||
if ((dirs & TravelDirections.North) > 0)
|
||||
{
|
||||
ddx.Add(0);
|
||||
ddy.Add(1);
|
||||
}
|
||||
if ((dirs & TravelDirections.NorthEast) > 0)
|
||||
{
|
||||
ddx.Add(1);
|
||||
ddy.Add(1);
|
||||
}
|
||||
if ((dirs & TravelDirections.East) > 0)
|
||||
{
|
||||
ddx.Add(1);
|
||||
ddy.Add(0);
|
||||
}
|
||||
if ((dirs & TravelDirections.SouthEast) > 0)
|
||||
{
|
||||
ddx.Add(1);
|
||||
ddy.Add(-1);
|
||||
}
|
||||
if ((dirs & TravelDirections.South) > 0)
|
||||
{
|
||||
ddx.Add(0);
|
||||
ddy.Add(-1);
|
||||
}
|
||||
if ((dirs & TravelDirections.SouthWest) > 0)
|
||||
{
|
||||
ddx.Add(-1);
|
||||
ddy.Add(-1);
|
||||
}
|
||||
if ((dirs & TravelDirections.West) > 0)
|
||||
{
|
||||
ddx.Add(-1);
|
||||
ddy.Add(0);
|
||||
}
|
||||
if ((dirs & TravelDirections.NorthWest) > 0)
|
||||
{
|
||||
ddx.Add(-1);
|
||||
ddy.Add(1);
|
||||
}
|
||||
|
||||
dx = ddx.ToArray();
|
||||
dy = ddy.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns element at specified position in the map
|
||||
/// </summary>
|
||||
/// <param name="x">X</param>
|
||||
/// <param name="y">Y</param>
|
||||
/// <returns>Element</returns>
|
||||
protected abstract T ElementAt(int x, int y);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified coordinates are valid (e.g. inside the map)
|
||||
/// </summary>
|
||||
/// <param name="x">X</param>
|
||||
/// <param name="y">Y</param>
|
||||
/// <returns>True if coordinates are valid</returns>
|
||||
protected abstract bool CoordinatesValid(int x, int y);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specified item on the map can be visited
|
||||
/// </summary>
|
||||
/// <param name="toVisit">Item to visit</param>
|
||||
/// <param name="previous">Previous node</param>
|
||||
/// <returns>True if can be visited</returns>
|
||||
protected abstract bool CanVisit(TraverseVisitItem<T> toVisit, TraverseVisitItem<T> previous);
|
||||
|
||||
/// <summary>
|
||||
/// Called when an item enqueued to be visited later
|
||||
/// </summary>
|
||||
/// <param name="toVisit">Item to visit</param>
|
||||
/// <param name="current">Previous node</param>
|
||||
/// <returns>True if can be visited</returns>
|
||||
protected virtual void OnEnqueued(TraverseVisitItem<T> toVisit, TraverseVisitItem<T> previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an item is visited
|
||||
/// </summary>
|
||||
/// <param name="item">Visited item</param>
|
||||
protected virtual void OnVisit(TraverseVisitItem<T> item)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traverses a grid map
|
||||
/// </summary>
|
||||
/// <param name="originX">X coordinate of traversal starting point</param>
|
||||
/// <param name="originY">Y coordinate of traversal starting point</param>
|
||||
/// <param name="travelDirections">Possible traversal directions</param>
|
||||
public virtual void Traverse(IEnumerable<int> originsX, IEnumerable<int> originsY, TravelDirections travelDirections = TravelDirections.NESW)
|
||||
{
|
||||
// Get directions
|
||||
int[] dx, dy;
|
||||
GenerateDirections(out dx, out dy, travelDirections);
|
||||
|
||||
// Queue
|
||||
var toVisit = new Queue<TraverseVisitItem<T>>();
|
||||
|
||||
// Enqueue origins
|
||||
var itX = originsX.GetEnumerator();
|
||||
var itY = originsY.GetEnumerator();
|
||||
|
||||
while (itX.MoveNext() && itY.MoveNext())
|
||||
{
|
||||
if (CoordinatesValid(itX.Current, itY.Current))
|
||||
{
|
||||
var origin = new TraverseVisitItem<T>(ElementAt(itX.Current, itY.Current), itX.Current, itY.Current);
|
||||
toVisit.Enqueue(origin);
|
||||
}
|
||||
}
|
||||
|
||||
// Visit nodes in queue
|
||||
while (toVisit.Count > 0)
|
||||
{
|
||||
var item = toVisit.Dequeue();
|
||||
|
||||
// Visit item
|
||||
OnVisit(item);
|
||||
|
||||
// Enqueue neighbours in each direction
|
||||
for (int k = 0; k < dx.Length; k++)
|
||||
{
|
||||
int newx = item.X + dx[k];
|
||||
int newy = item.Y + dy[k];
|
||||
|
||||
if (CoordinatesValid(newx, newy))
|
||||
{
|
||||
var newitem = new TraverseVisitItem<T>(ElementAt(newx, newy), newx, newy);
|
||||
|
||||
if (CanVisit(newitem, item))
|
||||
{
|
||||
toVisit.Enqueue(newitem);
|
||||
OnEnqueued(newitem, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Traverses a grid map
|
||||
///// </summary>
|
||||
///// <param name="originX">X coordinate of traversal starting point</param>
|
||||
///// <param name="originY">Y coordinate of traversal starting point</param>
|
||||
///// <param name="travelDirections">Possible traversal directions</param>
|
||||
//public virtual void Traverse(int originX, int originY, TravelDirections travelDirections = TravelDirections.NESW)
|
||||
//{
|
||||
// Traverse(Enumerable.Repeat(originX, 1), Enumerable.Repeat(originY, 1), travelDirections);
|
||||
//}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 033176dc0e4c5594bbf5d1ec0034fbad
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
Reference in New Issue
Block a user