C
C#4mo ago
YouWouldnt

✅ Dictionary not returning Value

HashCode keys are the same however its for some reason not returning the value from the dictionary Pathfinding Class
c#
public List<PathNode>? findPath(int startPointX, int startPointY, int endPointX, int endPointY)
{
PathNode startNode = getNode(startPointX, startPointY);
PathNode endNode = getNode(endPointX, endPointY);
Debug.WriteLine("[Birds Eye] New Pathfinding Begun");
{
openList.Add(startNode);

for (int x = 0; x < panelWidth; x++)
{
for (int y = 0; y < panelHeight; y++)
{
PathNode pathNode = getNode(x, y);
pathNode.gCost = int.MaxValue;
pathNode.calculateFCost();
pathNode.cameFromNode = null;
}
}
startNode.gCost = 0;
Debug.WriteLine("[Birds Eye] G Cost Initialized");
startNode.hCost = calculatDistanceCost(startNode, endNode);
Debug.WriteLine("[Birds Eye] H Cost Initialized");
startNode.calculateFCost();
Debug.WriteLine("[Birds Eye] F Cost Initialized");

while (openList.Count > 0)
{
PathNode currentNode = getLowestFCostNode(openList);
Debug.WriteLine("[Birds Eye] Current Node Initialized");
if (currentNode == endNode)
{
return finalPath(endNode);
}
openList.Remove(currentNode);
closedList.Add(currentNode);
Debug.WriteLine("[Birds Eye] Searching Neighbours");
foreach (PathNode neighbourNode in getNeighbour(currentNode))
{

Debug.WriteLine("[Birds Eye] New Panel Node Reached");
if (closedList.Contains(neighbourNode)) continue;
int tentativeGCost = currentNode.gCost + calculatDistanceCost(currentNode, neighbourNode);
if (tentativeGCost < currentNode.gCost)
{

neighbourNode.cameFromNode = currentNode;
neighbourNode.gCost = tentativeGCost;
neighbourNode.hCost = calculatDistanceCost(neighbourNode, endNode);
neighbourNode.calculateFCost();

if (!openList.Contains(neighbourNode))
{
openList.Add(neighbourNode);
Debug.WriteLine("[Birds Eye] Added Neighbour to Open List");

}
}
}
}
Debug.WriteLine("[Birds Eye] No Path Found");
return null;
}
}
c#
public List<PathNode>? findPath(int startPointX, int startPointY, int endPointX, int endPointY)
{
PathNode startNode = getNode(startPointX, startPointY);
PathNode endNode = getNode(endPointX, endPointY);
Debug.WriteLine("[Birds Eye] New Pathfinding Begun");
{
openList.Add(startNode);

for (int x = 0; x < panelWidth; x++)
{
for (int y = 0; y < panelHeight; y++)
{
PathNode pathNode = getNode(x, y);
pathNode.gCost = int.MaxValue;
pathNode.calculateFCost();
pathNode.cameFromNode = null;
}
}
startNode.gCost = 0;
Debug.WriteLine("[Birds Eye] G Cost Initialized");
startNode.hCost = calculatDistanceCost(startNode, endNode);
Debug.WriteLine("[Birds Eye] H Cost Initialized");
startNode.calculateFCost();
Debug.WriteLine("[Birds Eye] F Cost Initialized");

while (openList.Count > 0)
{
PathNode currentNode = getLowestFCostNode(openList);
Debug.WriteLine("[Birds Eye] Current Node Initialized");
if (currentNode == endNode)
{
return finalPath(endNode);
}
openList.Remove(currentNode);
closedList.Add(currentNode);
Debug.WriteLine("[Birds Eye] Searching Neighbours");
foreach (PathNode neighbourNode in getNeighbour(currentNode))
{

Debug.WriteLine("[Birds Eye] New Panel Node Reached");
if (closedList.Contains(neighbourNode)) continue;
int tentativeGCost = currentNode.gCost + calculatDistanceCost(currentNode, neighbourNode);
if (tentativeGCost < currentNode.gCost)
{

neighbourNode.cameFromNode = currentNode;
neighbourNode.gCost = tentativeGCost;
neighbourNode.hCost = calculatDistanceCost(neighbourNode, endNode);
neighbourNode.calculateFCost();

if (!openList.Contains(neighbourNode))
{
openList.Add(neighbourNode);
Debug.WriteLine("[Birds Eye] Added Neighbour to Open List");

}
}
}
}
Debug.WriteLine("[Birds Eye] No Path Found");
return null;
}
}
15 Replies
YouWouldnt
YouWouldnt4mo ago
Panel Grid Class/Dictionary Creation
c#
public class PanelGrid
{
private double width;
private double height;
private int[,] gridArray;
public Dictionary<panelTuple, PathNode> panelNodes = new Dictionary<panelTuple, PathNode>();
public PanelGrid(Canvas panelImport)
{
width = panelImport.Width;
height = panelImport.Height;
gridArray = new int[(int)width, (int)height];

for (int x = 0; x < gridArray.GetLength(0); x++)
{
for (int y = 0; y < gridArray.GetLength(1); y++)
{
panelNodes.Add(new panelTuple(x, y), new PathNode(x, y));
if (x == 0 && y == 420)
{
Debug.WriteLine("HashCode for (0,420) is: " + HashCode.Combine(x, y));
}

}
}
Debug.WriteLine("[Birds Eye] Panel Nodes Dictionary Created");
}
}
c#
public class PanelGrid
{
private double width;
private double height;
private int[,] gridArray;
public Dictionary<panelTuple, PathNode> panelNodes = new Dictionary<panelTuple, PathNode>();
public PanelGrid(Canvas panelImport)
{
width = panelImport.Width;
height = panelImport.Height;
gridArray = new int[(int)width, (int)height];

for (int x = 0; x < gridArray.GetLength(0); x++)
{
for (int y = 0; y < gridArray.GetLength(1); y++)
{
panelNodes.Add(new panelTuple(x, y), new PathNode(x, y));
if (x == 0 && y == 420)
{
Debug.WriteLine("HashCode for (0,420) is: " + HashCode.Combine(x, y));
}

}
}
Debug.WriteLine("[Birds Eye] Panel Nodes Dictionary Created");
}
}
PathNode getNode Function
c#
private PathNode? getNode(int xNode, int yNode)
{
Debug.WriteLine("[Birds Eye] Attempting to Find Node: " + xNode + ", " + yNode);
panelTuple getPanelNode = new panelTuple(xNode, yNode);
Debug.WriteLine("[Birds Eye] Key Value Searching by Hash Code: " + getPanelNode.GetHashCode());
return panelGrid.panelNodes[getPanelNode];
}
c#
private PathNode? getNode(int xNode, int yNode)
{
Debug.WriteLine("[Birds Eye] Attempting to Find Node: " + xNode + ", " + yNode);
panelTuple getPanelNode = new panelTuple(xNode, yNode);
Debug.WriteLine("[Birds Eye] Key Value Searching by Hash Code: " + getPanelNode.GetHashCode());
return panelGrid.panelNodes[getPanelNode];
}
Debug Output
HashCode for (0,420) is: -1765100707
[Birds Eye] Panel Nodes Dictionary Created
[Birds Eye] Attempting to Find Node: 0, 420
[Birds Eye] Key Value Searching by Hash Code: -1765100707
HashCode for (0,420) is: -1765100707
[Birds Eye] Panel Nodes Dictionary Created
[Birds Eye] Attempting to Find Node: 0, 420
[Birds Eye] Key Value Searching by Hash Code: -1765100707
Error Output
System.Collections.Generic.KeyNotFoundException: 'The given key 'Birds_Eye.Views.Resources.Functions.panelTuple' was not present in the dictionary.'
System.Collections.Generic.KeyNotFoundException: 'The given key 'Birds_Eye.Views.Resources.Functions.panelTuple' was not present in the dictionary.'
Jimmacle
Jimmacle4mo ago
what is the definition of panelTuple?
YouWouldnt
YouWouldnt4mo ago
Panel Tuple Class
c#
namespace Birds_Eye.Views.Resources.Functions
{
public class panelTuple
{
public int x;
public int y;
private int _hashCode;
public panelTuple(int x, int y)
{
this.x = x;
this.y = y;
_hashCode = HashCode.Combine(x, y);
}
public override int GetHashCode()
{
return _hashCode;
}
}
}
c#
namespace Birds_Eye.Views.Resources.Functions
{
public class panelTuple
{
public int x;
public int y;
private int _hashCode;
public panelTuple(int x, int y)
{
this.x = x;
this.y = y;
_hashCode = HashCode.Combine(x, y);
}
public override int GetHashCode()
{
return _hashCode;
}
}
}
Jimmacle
Jimmacle4mo ago
you don't have an equality implementation defined https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=net-8.0#remarks
Dictionary<TKey,TValue> requires an equality implementation to determine whether keys are equal. You can specify an implementation of the IEqualityComparer<T> generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic equality comparer EqualityComparer<T>.Default is used. If type TKey implements the System.IEquatable<T> generic interface, the default equality comparer uses that implementation.
Dictionary<TKey,TValue> requires an equality implementation to determine whether keys are equal. You can specify an implementation of the IEqualityComparer<T> generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic equality comparer EqualityComparer<T>.Default is used. If type TKey implements the System.IEquatable<T> generic interface, the default equality comparer uses that implementation.
YouWouldnt
YouWouldnt4mo ago
oh.... more reading now to do 😦
Jimmacle
Jimmacle4mo ago
a hash code isn't guaranteed to be unique to a particular object, it's just used to store/find values more efficiently 2 different objects could have the same hash code also, your object should be immutable because as it is now you could modify x and y the simplest solution is to use a record instead of writing a class yourself, it implements value-type semantics for you
public record panelTuple(int x, int y);
public record panelTuple(int x, int y);
YouWouldnt
YouWouldnt4mo ago
im so confused cuz im quite new to dictionaries....would you be able to walk me through it?
Jimmacle
Jimmacle4mo ago
basically, the dictionary uses the hash to store items in one of several "buckets" then when you look up a key, it computes the hash code of the key to find the same bucket the object should be stored in but the buckets can hold more than one item, so there is still an element of looping over that bucket and checking if the key is really there
YouWouldnt
YouWouldnt4mo ago
oh yea i know what the dictionary does and how it get values, im just not sure about this IEquality thingy how do i implement that?
Jimmacle
Jimmacle4mo ago
implement System.IEquatable<T> for a case like this you'd check if the x and y of both arguments are equal
YouWouldnt
YouWouldnt4mo ago
dont know how to implement that
Jimmacle
Jimmacle4mo ago
your IDE will prompt you if you specify the interface on your type also, if you look it up you'll see docs
YouWouldnt
YouWouldnt4mo ago
c#
public Dictionary<panelTuple, PathNode> panelNodes = new Dictionary<panelTuple, PathNode>(IEquatable<T>);
c#
public Dictionary<panelTuple, PathNode> panelNodes = new Dictionary<panelTuple, PathNode>(IEquatable<T>);
i have no idea what to do lol do i chuck this in the panelTuple Class? I have no idea what im doing
YouWouldnt
YouWouldnt4mo ago
Yep I got it now. Much more simple than the docs showed it to be. Thank you for your help! Just gotta wait for the battery to recharge now so I can see it in action 😂