Following is a Java implementation of a random walk on the 2d grid, with no intersections. A few notes about it:
1) Instead of repeating the code that handles different directions, i'm using a predefined list of 4 directions ([-1,0],[0,1],[1,0],[0,-1]) and shuffle it each time I scan all the possible directions to continue with.
2) Your solution seems to fail because it doesn't involve any backtracking - each time you reach a dead end, you should go back to the previous step and try taking another direction. I'm using recursion to make backtracking simple.
3) The algorithm is recursive, so it may fail with StackOverflowError for long paths. If you need it to work for long paths, consider using a stack to simulate the recursion.
4) The algorithm doesn't deal with the bounding rectangle. This requires minor changes.
public class RandomPathCreator {
private final static List<Location> DIRECTIONS = Arrays.asList(new Location[]{new Location(-1, 0), new Location(0, -1), new Location(1, 0), new Location(0, 1)});
public static Path randomPath(int len) {
Path path = new Path();
path.append(new Location(0,0)); //The random walk starts from [0,0]
findPath(len, path);
return path;
}
///////////////////////////////
// The main logic is here
///////////////////////////////
private static boolean findPath(int len, Path path) {
if (path.size() == len)
return true;
Location lastPos = path.getLast();
Collections.shuffle(DIRECTIONS);
for (Location dir : DIRECTIONS) {
Location newPos = lastPos.add(dir);
if (path.append(newPos)) {
if (findPath(len, path))
return true;
path.removeLast();
}
}
return false;
}
private static class Location {
public final int x;
public final int y;
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public Location add(Location other) {
return new Location(x + other.x, y + other.y);
}
@Override
public int hashCode() {
return 31 * (31 + x) + y;
}
@Override
public boolean equals(Object obj) {
Location other = (Location) obj;
return (x == other.x && y == other.y);
}
@Override
public String toString() {
return "Location [x=" + x + ", y=" + y + "]";
}
}
private static class Path {
private List<Location> list = new ArrayList<Location>();
private Set<Location> set = new HashSet<Location>();
public boolean append(Location l) {
if (set.add(l)) {
list.add(l);
return true;
}
return false;
}
public Location getLast() {
return list.get(list.size() - 1);
}
public void removeLast() {
Location last = list.remove(list.size() - 1);
set.remove(last);
}
public int size() {
return list.size();
}
@Override
public String toString() {
return list.toString();
}
}
}