I am trying to code an algorithm that solves a maze problem but I am facing some difficulty to apply it correctly.
The algorithm runs over the walls instead of changing the direction after finding the valid point.
Complete Code on Github
I do not understand clearly how to check for the previousPoint and then from that point check for the next valid move.
Could someone help me giving me some tips on which direction I could go?
class MapPathFinder
{
public bool[,] correctPath = new bool[12,12];
public int[,] previousPoint = new int[12, 12];
public bool startPointFound = false;
public bool nextValidMove(MapFile map, int y, int x)
{
if ((y == map.width) && (x == map.height)) {
return false; //Checks if at the edge and terminates the method
}
if ((map.Matrix[y, x]) == 1 ) {
return true; // check if at a wall and terminate the method
}
if (y != 0)
{
if (nextValidMove(map, y-1,x))
{
map.Matrix[y, x] = 9; //changes the color of the position
correctPath[y, x] = true;
return correctPath[y, x];
}
if (y != map.width - 1) //check if at the limit of the map
{
if (nextValidMove(map,y + 1, x))
{
map.Matrix[y, x] = 9;
correctPath[y, x] = true;
return correctPath[y, x];
}
}
if (x != 0)
{
if (nextValidMove(map, y, x - 1))
{
map.Matrix[y, x] = 9;
correctPath[y, x] = true;
return correctPath[y, x];
}
}
if (x != map.height - 1)
{
if (nextValidMove(map, y, x + 1))
{
map.Matrix[y, x] = 9;
correctPath[y, x] = true;
return correctPath[y, x];
}
}
}
return false;
}
public bool PathFinder(MapFile map)
{
for (int y = 1; y < map.width; y++)
{
for (int x = 1; x < map.height; x++)
{
var status = MapDisplay.DisplayMap(map);
if (status)
{
nextValidMove(map, x, y);
}
}
}
return true;
}
I tried to implement the answer given by Paul but could not really get anywhere from it and I am completely lost.
That is what I got from your answer:
public bool nextValidMove(MapFile map, int y, int x)
{
if ((y == map.width) || (x == map.height)) return false;
if(y<0 || x<0) return false;
if ((map.Matrix[y, x]) == 1) return true; // check if at a wall and terminate the method
if (map.Matrix[y, x] == 5) return map.end;
if (y - 1 >= 0 && map.Matrix[y-1, x] == 2 && !nextValidMove(map, y-1, x))
{
map.Matrix[y, x] = 9;
previousPoint[y, x] = map.Matrix[y, x];
return false;
}
// Test the East wall...
if (x + 1 <= map.width - 1 && map.Matrix[y + 1, x] == 2 && !nextValidMove(map, y, x+1))
{
map.Matrix[y, x] = 9;
previousPoint[y, x] = map.Matrix[y, x];
return false;
}
// Test the South wall...
if (y + 1 <= map.height - 1 && map.Matrix[y, x + 1] == 2 && !nextValidMove(map, y+1,x))
{
map.Matrix[y, x] = 9;
previousPoint[y, x] = map.Matrix[y, x];
return false;
}
// Test the West wall...
if (x - 1 >= 0 && map.Matrix[y, x - 1] == 2 && !nextValidMove(map, y, x-1))
{
map.Matrix[y, x] = 9;
previousPoint[y, x] = map.Matrix[y, x];
return false;
}
return false;
}
When I run it I get a stack overflow error.
When I am checking the possible points and calling the function recursively with
!nextValidMove(map, y-1, x)
I don't really understand why I am checking the nextValidMove(y-1,x) since it was already true at the begining of my if statement:
if(map.Matrix[y-1, x] == 2 && !nextValidMove(y-1,x))
I thought of checking the previousPoint together, like this:
if(nextValidMove(map, y - 1, x)&&!previousPoint[y-1,x])
But I am getting a stackoverflow error. I have no clue how to get out of there anymore.
I have rewriten your MapPathFinder class to make it work.
class MapPathFinder
{
public const byte WALL = 1;
public const byte ROAD = 2;
public const byte START = 3;
public const byte FINISH = 5;
public const byte ALREADY_THERE = 9;
public bool NextValidMove(MapFile map, int x, int y)
{
// Check edges
if (x < 0 || x > map.width || y < 0 || y > map.height)
return false;
byte currentPosition = map.Matrix[x, y];
// Check walls or already there
if (currentPosition == WALL || currentPosition == ALREADY_THERE)
return false;
// Print
var status = MapDisplay.DisplayMap(map);
if (status)
{
// Check finish
if (currentPosition == FINISH)
{
return true; // We've arrived!
}
// Road
//
// Set ALREADY THERE
map.Matrix[x, y] = ALREADY_THERE;
// Left
if (NextValidMove(map, x - 1, y))
return true;
// Right
if (NextValidMove(map, x + 1, y))
return true;
// Up
if (NextValidMove(map, x, y - 1))
return true;
// Down
if (NextValidMove(map, x, y + 1))
return true;
// Not the correct path..
map.Matrix[x, y] = ROAD;
}
return false;
}
public bool PathFinder(MapFile map)
{
// Looking for start point
for (int x = 0; x < map.width; x++)
{
for (int y = 0; y < map.width; y++)
{
if (map.Matrix[x, y] == START)
return NextValidMove(map, x, y);
}
}
return false;
}
}
However I left some work for you:
Your walls are determined by there being a #
in any of the adjacent cells or a .
for the floor, S
start and F
finish.
In that case, you want to simply check on a rotational basis, starting at, say, North, then move onto the next position round, until you arrive back at North. Each check should be pushed on the stack and popped off when it gets nowhere. That way, at least, you'll be able to trace your way backward each time.
// Test to see if we've found Utopia...
if(map.Matrix[x, y] == 'F') return true;
// Test the North wall...
if(y-1>=0 && map.Matrix[x, y-1]=='.' && !nextValidMove(map, x, y-1)) return false;
// Test the East wall...
if(x+1<=map.width && map.Matrix[x+1, y]=='.' && !nextValidMove(map, x+1, y)) return false;
// Test the South wall...
if(y+1<=map.height && map.Matrix[x, y+1]=='.' && !nextValidMove(map, x, y+1)) return false;
// Test the West wall...
if(x-1>=0 && map.Matrix[x-1, y]=='.' && !nextValidMove(map, x-1, y)) return false;
The recursive calls should then unwind naturally.
Note that you'll need to look at the success criteria a little better than I have there, and you may need to play with how the routine unwinds. The code here gives a demonstration, though, of how to check your adjoining walls.
Notice that &&
only performs the next check if the prior one was successful in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With