imported and translated java code

starting to implement algorithms
This commit is contained in:
Simon O'Shea
2023-08-08 15:27:37 -04:00
parent f825ec9c27
commit 3ac2b11494
4 changed files with 257 additions and 180 deletions
@@ -6,10 +6,16 @@ public class AStar : MonoBehaviour
{ {
LogicGrid world; LogicGrid world;
List<int[][]> obstacles;
List<int[][]> samples;
int heuristic; // 0 = h0 |
public void setWorld(LogicGrid world) public AStar(LogicGrid world, int heuristic)
{ {
this.world = world; this.world = world;
this.obstacles = world.obstacles;
this.samples = world.samples;
this.heuristic = heuristic;
} }
void Start() void Start()
@@ -18,6 +18,12 @@ public class LogicGrid
// Debug Grid Array used for updating the text-objects // Debug Grid Array used for updating the text-objects
private TextMesh[,] debugTextArray; private TextMesh[,] debugTextArray;
// Coordinates for pathfinding
public int[] agent;
public List<int[][]> obstacles;
public List<int[][]> samples;
public event EventHandler<OnGridValueChangedEventArgs> OnGridValueChanged; public event EventHandler<OnGridValueChangedEventArgs> OnGridValueChanged;
public class OnGridValueChangedEventArgs : EventArgs public class OnGridValueChangedEventArgs : EventArgs
{ {
@@ -97,6 +103,46 @@ public class LogicGrid
x = x, x = x,
y = y y = y
}); });
// If deleting a cell's value, remove coord from set
if (value == 0)
{
// make behavior to check for -1 values in coords
if (agent[0].Equals(x) && agent[1].Equals(y))
{
agent[0] = -1;
agent[1] = -2;
}
}
// Add coordinate to obstacle array
if (value == 1)
{
int[][] coord = new int[2][];
coord[0][0] = x;
coord[1][0] = y;
obstacles.Add(coord);
}
// Add coordinate to sample array
if (value == 2)
{
int[][] coord = new int[2][];
coord[0][0] = x;
coord[1][0] = y;
samples.Add(coord);
}
// Add coordinate to obstacle array
if (value == 3)
{
agent[0] = x;
agent[1] = y;
}
} }
} }
@@ -137,6 +183,10 @@ public class LogicGrid
{ {
gridArray = new int[width, height]; gridArray = new int[width, height];
agent = new int[2];
obstacles = new List<int[][]>();
samples = new List<int[][]>();
if (OnGridValueChanged != null) if (OnGridValueChanged != null)
OnGridValueChanged(this, new OnGridValueChangedEventArgs OnGridValueChanged(this, new OnGridValueChangedEventArgs
{ {
+17 -7
View File
@@ -16,7 +16,12 @@ public class Main : MonoBehaviour
void Start() void Start()
{ {
// Create world // Create world
world = new LogicGrid(100, 100, 5f, new Vector3(-110, -110)); int width = 100;
int height = 100;
float cellSize = 5f;
Vector3 origin = new Vector3(-110, -110);
world = new LogicGrid(width, height, cellSize, origin);
// Set default placement to Obstacle // Set default placement to Obstacle
placementValue = 1; placementValue = 1;
@@ -28,11 +33,16 @@ public class Main : MonoBehaviour
} }
// Update is called once per frame public void StartAStar()
{
AStar astar = new AStar(world, 0);
}
// Update contains keyboard shortcut options
void Update() void Update()
{ {
// Change Placement Modes: // Change Placement Mode Keyboard Shortcuts:
////////////////////////////////
// Place Obstacle in grid // Place Obstacle in grid
if (Input.GetKeyDown("o")) if (Input.GetKeyDown("o"))
{ {
@@ -59,15 +69,16 @@ public class Main : MonoBehaviour
{ {
ResetGrid(); ResetGrid();
} }
//////////////////////////
// Update Cell: // Update Cell:
// Change cell to obstacle // Place value in cell based on selected placementValue with left click
if (Input.GetMouseButton(0)) if (Input.GetMouseButton(0))
{ {
world.SetValue(CodeMonkey.Utils.UtilsClass.GetMouseWorldPosition(), placementValue); world.SetValue(CodeMonkey.Utils.UtilsClass.GetMouseWorldPosition(), placementValue);
} }
// Clear cell // Clear cell with right click
if (Input.GetMouseButton(1)) if (Input.GetMouseButton(1))
{ {
world.SetValue(CodeMonkey.Utils.UtilsClass.GetMouseWorldPosition(), 0); world.SetValue(CodeMonkey.Utils.UtilsClass.GetMouseWorldPosition(), 0);
@@ -79,7 +90,6 @@ public class Main : MonoBehaviour
} }
public void SetModeObstacle() public void SetModeObstacle()
{ {
placementValue = 1; placementValue = 1;
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
class Node : IComparable<Node> class Node : IComparable<Node>
@@ -15,7 +16,7 @@ using UnityEngine;
char lastMove; // for output/animation char lastMove; // for output/animation
int distanceTraveled; // for calculating f(n) value int distanceTraveled; // for calculating f(n) value
double heuristic; double heuristic;
double fn; // distance traveled + heuristic value public double fn; // distance traveled + heuristic value
bool canSample; // for expansion bool canSample; // for expansion
// construct node :) // construct node :)
@@ -23,7 +24,7 @@ using UnityEngine;
{ {
this.parent = parent; this.parent = parent;
this.agent = agent; this.agent = agent;
this.samples = new ArrayList<int[]>(samples); this.samples = new List<int[]>(samples);
this.lastMove = lastMove; this.lastMove = lastMove;
this.distanceTraveled = distanceTraveled; this.distanceTraveled = distanceTraveled;
this.heuristic = heuristic; this.heuristic = heuristic;
@@ -33,16 +34,16 @@ using UnityEngine;
// determine valid moves and collect children to be sent back to search // determine valid moves and collect children to be sent back to search
public List<Node> expand(int depth) public List<Node> expand(int depth)
{ {
List<Node> children = new ArrayList<Node>(); List<Node> children = new List<Node>();
if (this.distanceTraveled >= depth && depth != -1) if (this.distanceTraveled >= depth && depth != -1)
return children; return children;
// document expansion of node and get ready to collect this node's children // document expansion of node and get ready to collect this node's children
SampleWorld.expansions++; // SampleWorld.expansions++;
int[] onSample = new int[2]; int[] onSample = new int[2];
// since this state is being currently visited (expanded), put in closed list // since this state is being currently visited (expanded), put in closed list
SampleWorld.closed.add(this.getState()); // SampleWorld.closed.add(this.getState());
//////////////////////////////////// ////////////////////////////////////
// BEGIN CHECKING FOR VALID MOVES // // BEGIN CHECKING FOR VALID MOVES //
@@ -59,62 +60,64 @@ using UnityEngine;
{ {
// if move is valid, create that new node/state and document // if move is valid, create that new node/state and document
Node child = new Node(this, up, this.samples, 'U', this.distanceTraveled + 1, this.heuristic); Node child = new Node(this, up, this.samples, 'U', this.distanceTraveled + 1, this.heuristic);
SampleWorld.nodesGenerated++; //SampleWorld.nodesGenerated++;
// make sure that we have not already made that move // make sure that we have not already made that move
if (!child.getState().inClosed()) if (!child.getState().inClosed())
children.add(child); children.Add(child);
} }
// same idea but for the different potential moves // same idea but for the different potential moves
if (isOpen(down)) if (isOpen(down))
{ {
Node child = new Node(this, down, this.samples, 'D', this.distanceTraveled + 1, this.heuristic); Node child = new Node(this, down, this.samples, 'D', this.distanceTraveled + 1, this.heuristic);
SampleWorld.nodesGenerated++; //SampleWorld.nodesGenerated++;
if (!child.getState().inClosed()) if (!child.getState().inClosed())
children.add(child); children.Add(child);
} }
if (isOpen(left)) if (isOpen(left))
{ {
Node child = new Node(this, left, this.samples, 'L', this.distanceTraveled + 1, this.heuristic); Node child = new Node(this, left, this.samples, 'L', this.distanceTraveled + 1, this.heuristic);
SampleWorld.nodesGenerated++; //SampleWorld.nodesGenerated++;
if (!child.getState().inClosed()) if (!child.getState().inClosed())
children.add(child); children.Add(child);
} }
if (isOpen(right)) if (isOpen(right))
{ {
Node child = new Node(this, right, this.samples, 'R', this.distanceTraveled + 1, this.heuristic); Node child = new Node(this, right, this.samples, 'R', this.distanceTraveled + 1, this.heuristic);
SampleWorld.nodesGenerated++; //SampleWorld.nodesGenerated++;
if (!child.getState().inClosed()) if (!child.getState().inClosed())
children.add(child); children.Add(child);
} }
// CHECK IF CAN SAMPLE // CHECK IF CAN SAMPLE
onSample = canSample(); onSample = CanSample();
if (onSample[0] == 1) if (onSample[0] == 1)
{ {
Node child = new Node(this, this.agent, this.samples, 'S', this.distanceTraveled + 1, this.heuristic); Node child = new Node(this, this.agent, this.samples, 'S', this.distanceTraveled + 1, this.heuristic);
child.samples.remove(onSample[1]);
SampleWorld.nodesGenerated++; // PROBLEM?
children.add(child); child.samples.RemoveAt(onSample[1]);
//SampleWorld.nodesGenerated++;
children.Add(child);
} }
return children; return children;
} }
// helper for expand, verifies whether potential move is legal // helper for expand, verifies whether potential move is legal
public boolean isOpen(int[] position) public bool isOpen(int[] position)
{ {
// check that agent is not trying to move into an obstacle // check that agent is not trying to move into an obstacle
for (int i = 0; i < SampleWorld.obstacles.size(); i++) for (int i = 0; i < SampleWorld.obstacles.size(); i++)
{ {
if (Arrays.compare(SampleWorld.obstacles.get(i), position) == 0) if (Enumerable.SequenceEqual(SampleWorld.obstacles.get(i), position) == 0)
return false; return false;
} }
@@ -128,20 +131,21 @@ using UnityEngine;
// returns the coordinates of the sample closest to the agent's current location // returns the coordinates of the sample closest to the agent's current location
public int[] nearestSample() public int[] nearestSample()
{ {
if (samples.size() == 0) if (samples.Count == 0)
return agent; return agent;
int[] s = samples.get(0); // PROBLEM?
double lowest = distance(agent, samples.get(0)); int[] s = samples[0];
double distance; double lowest = distance(agent, samples[0]);
double dist;
for (int i = 1; i < samples.size(); i++) for (int i = 1; i < samples.Count; i++)
{ {
distance = distance(agent, samples.get(i)); dist = distance(agent, samples[i]);
if (distance < lowest) if (dist < lowest)
{ {
lowest = distance; lowest = dist;
s = samples.get(i); s = samples[i];
} }
} }
return s; return s;
@@ -151,7 +155,7 @@ using UnityEngine;
{ // _________________________ { // _________________________
// distance between 2D points = √(y2 - y1)^2 + (x2 - x1)^2 // distance between 2D points = √(y2 - y1)^2 + (x2 - x1)^2
double total = (((b[row] - a[row]) * (b[row] - a[row])) + ((b[col] - a[col]) * (b[col] - a[col]))); double total = (((b[row] - a[row]) * (b[row] - a[row])) + ((b[col] - a[col]) * (b[col] - a[col])));
total = Math.sqrt(total); total = Math.Sqrt(total);
return total; return total;
} }
@@ -161,16 +165,17 @@ using UnityEngine;
// returns two pieces of information if true: // returns two pieces of information if true:
// [0] is 1 to indicate agent can sample // [0] is 1 to indicate agent can sample
// [1] is the index of the valid sample in the list // [1] is the index of the valid sample in the list
public int[] canSample() public int[] CanSample()
{ {
// default to false // default to false
int[] result = new int[2]; int[] result = new int[2];
result[0] = 0; result[0] = 0;
result[1] = -1; result[1] = -1;
for (int i = 0; i < this.samples.size(); i++) for (int i = 0; i < this.samples.Count; i++)
{ {
if ((this.agent[row] == samples.get(i)[row]) && (this.agent[col] == samples.get(i)[col])) // PROBLEM?
if ((this.agent[row] == samples[i][row]) && (this.agent[col] == samples[i][col]))
{ {
result[0] = 1; result[0] = 1;
result[1] = i; result[1] = i;
@@ -188,8 +193,7 @@ using UnityEngine;
} }
// we use to override comparisons for priorityQueues so that our heuristic calculations are actually used // we use to override comparisons for priorityQueues so that our heuristic calculations are actually used
@Override public int CompareTo(Node other)
public int compareTo(Node other)
{ {
if (this.fn > other.fn) if (this.fn > other.fn)
return 1; return 1;
@@ -200,11 +204,10 @@ using UnityEngine;
} }
// helper class for Node // helper class for Node
class NodeComparator implements Comparator<Node> class NodeComparator : Comparer<Node>
{ {
// used to sort nodes based on sum of distance traveled + heuristic estimation of work left // used to sort nodes based on sum of distance traveled + heuristic estimation of work left
@Override public override int Compare(Node a, Node b)
public int compare(Node a, Node b)
{ {
if (a.fn > b.fn) if (a.fn > b.fn)
return 1; return 1;
@@ -220,17 +223,19 @@ using UnityEngine;
public State(int[] agent, List<int[]> samples) public State(int[] agent, List<int[]> samples)
{ {
// PROBLEM?
this.agent = agent; this.agent = agent;
this.samples = new int[samples.size()][]; this.samples = new int[samples.Count][];
// convert List<int[]> into 2D array of ints [][] // convert List<int[]> into 2D array of ints [][]
for (int i = 0; i < samples.size(); i++) for (int i = 0; i < samples.Count; i++)
{ {
this.samples[i] = samples.get(i).clone(); // PROBLEM??
this.samples[i] = samples[i];
} }
} }
public boolean inClosed() public bool inClosed()
{ {
for (int i = 0; i < SampleWorld.closed.size(); i++) for (int i = 0; i < SampleWorld.closed.size(); i++)
{ {
@@ -242,17 +247,23 @@ using UnityEngine;
return false; return false;
} }
public boolean equals(State other) public bool equals(State other)
{ {
if (this.samples.length != other.samples.length) if (this.samples.Length != other.samples.Length)
return false; return false;
if (Arrays.compare(this.agent, other.agent) != 0) // PROBLEM?
if (!this.agent[0].Equals(other.agent[0]) && !this.agent[1].Equals(other.agent[1]))
return false; return false;
for (int i = 0; i < this.samples.length; i++) for (int i = 0; i < this.samples.Length; i++)
{ {
if (Arrays.compare(this.samples[i], other.samples[i]) != 0) //if (Arrays.compare(this.samples[i], other.samples[i]) != 0)
// PROBLEM?
if (!(this.samples.Rank == other.samples.Rank) &&
!(Enumerable.Range(0, this.samples.Rank).All(dimension => this.samples.GetLength(dimension) == other.samples.GetLength(dimension))) &&
!(this.samples.Cast<double>().SequenceEqual(other.samples.Cast<double>())))
return false; return false;
} }