I'm a fairly beginner/novice JavaScript coder, without much CS/math experience, trying to program part of a web-based game to check for the "longest road" across all possible paths, e.g. the longest road score in Catan.
I've tried to do this using a probably-wrong implementation of an iterative depth-first search using a stack. It's supposed to walk each possible path, then when it hits a dead end, check whether the current path is longer than the previous longest path, and overwrite if so.
My code doesn't quite work, though; it doesn't seem to actually walk/check all possible paths when hitting intersections or other variations.
I have done all kinds of research into DFS and these kinds of algorithms and have had an extremely rough time trying to get my head around it; this is the closest I've come to something that works. I'm sure the code could be made more elegant via recursion or somesuch, but at this point I just want to understand why what I've written here isn't functional.
Relevant code below. I'm sure it's a mess in many different ways, but hopefully at least the function names and such are clear enough that this is enough context to figure out what's ultimately going wrong:
function walkAllPaths(node, network, t) {
var stack = [ node ];
var path = new Array();
var visited = new Array();
while (stack.length) {
var curr = stack.pop();
visited.push(curr);
var moveNorth = myNeighbor(curr, "north");
var moveSouth = myNeighbor(curr, "south");
var moveWest = myNeighbor(curr, "west");
var moveEast = myNeighbor(curr, "east");
if (isValidMove(network, visited, t, moveNorth)) { stack.push(moveNorth); }
else if (isValidMove(network, visited, t, moveWest)) { stack.push(moveWest); }
else if (isValidMove(network, visited, t, moveSouth)) { stack.push(moveSouth); }
else if (isValidMove(network, visited, t, moveEast)) { stack.push(moveEast); }
else {
if (visited.length > path.length) {
path.length = 0;
for (var i = 0; i < visited.length; i++) {
path.push(visited[i]);
}
}
visited.pop();
}
console.log(visited);
}
return path;
}
I actually managed to figure out what was going on! I am still fairly positive that this is not at all an optimal solution, but it now does exactly what it's supposed to -- walk all valid paths and then return an array containing the longest path it walked. Here's the final code:
function walkAllPaths(node, network, t) {
var stack = [ node ];
var path = [];
var visited = [];
var longPath = [];
while (stack.length) {
var curr = stack.pop();
visited.push(curr);
if (curr !== path[path.length - 1]) { path.push(curr); }
var moveNorth = myNeighbor(curr, "north");
var moveSouth = myNeighbor(curr, "south");
var moveWest = myNeighbor(curr, "west");
var moveEast = myNeighbor(curr, "east");
if (isValidMove(network, visited, t, moveNorth)) { stack.push(moveNorth); }
else if (isValidMove(network, visited, t, moveWest)) { stack.push(moveWest); }
else if (isValidMove(network, visited, t, moveSouth)) { stack.push(moveSouth); }
else if (isValidMove(network, visited, t, moveEast)) { stack.push(moveEast); }
else {
if (path.length > longPath.length) {
longPath.length = 0;
for (var i = 0; i < path.length; i++) {
longPath.push(path[i]);
}
}
path.pop();
if (path.length) { stack.push(path[path.length - 1]); }
}
}
return longPath;
}
Thanks to those who offered thoughts/suggestions!