Search code examples
javarecursionstack-overflow

StackOverflow on Recursive Function


I have the following function which is supposed to yield all coordinates in a cartesian plane I can reach from an origin in n steps:

The origin is 'location' and the number of steps is 'strength' which is an int 1-10. However, I keep getting a stackoverflow error. Every time I call it I then call clear on the ArrayList positions. Thoughts?

Updated code:

// Returns all positions reachable in 'strength' steps
    public ArrayList<Int2D> findEscapeSpace(Int2D location, Field f) {
        // Are we still within the given radius?
        if((Math.abs(location.getX() - this.location.getX()) + Math.abs(location.getY() - this.location.getY())) < strength) {
            System.out.println("Starting on " + location);
            // If this position is not contained already, and if it doesn't contain a wall
            if(!positions.contains(location) && f.wallField.getObjectsAtLocation(location) == null) {
                positions.add(location);
                System.out.println("added " + location);
            }

            // Getting neighboring positions
            ArrayList<Int2D> neigh = findNeighPos(location, f);

            for(Int2D pos : neigh) {
                System.out.println("looking into " + pos + " at depth " + (Math.abs(location.getX() - this.location.getX()) + Math.abs(location.getY() - this.location.getY())) + " and strength " + strength);

                if(!positions.contains(pos))
                    findEscapeSpace(pos, f);

            }

        }
        System.out.println(positions.size());
        return positions;

    }

Old code

public ArrayList<Int2D> positions = new ArrayList<Int2D>();

    // Returns all positions reachable in 'strength' steps
    public ArrayList<Int2D> findEscapeSpace(Int2D location, Field f) {

        // Are we still within the given radius?
        if((Math.abs(location.getX() - this.location.getX()) + Math.abs(location.getY() - this.location.getY())) < strength) {
            // If this position is not contained already, and if it doesn't contain a wall
            if(!positions.contains(location) && f.wallField.getObjectsAtLocation(location) == null)
                positions.add(location);

            // Getting neighboring positions
            ArrayList<Int2D> neigh = findNeighPos(location, f);

            for(Int2D pos : neigh) {

                findEscapeSpace(pos, f);

            }

        }

        return positions;

    }

public ArrayList<Int2D> findNeighPos(Int2D currentP, Field f) {

        ArrayList neighPositions = new ArrayList<Int2D>();

        int cx = currentP.getX();
        int cy = currentP.getY();

        int maxY = f.HEIGHT-1;
        int maxX = f.WIDTH-1;

        // A few checks to make sure we're not going off tack (literally)

        if(cx > 0 && cy < maxY)
            neighPositions.add(new Int2D(cx-1, cy+1));

        if(cy < maxY)
            neighPositions.add(new Int2D(cx, cy+1));

        if(cx < maxX && cy < maxY)
            neighPositions.add(new Int2D(cx+1, cy+1));

        if(cx > 0)
            neighPositions.add(new Int2D(cx-1, cy));

        if(cx < maxX)
            neighPositions.add(new Int2D(cx+1, cy));

        if(cx > 0 && cy > 0)
            neighPositions.add(new Int2D(cx-1, cy-1));

        if(cy > 0)
            neighPositions.add(new Int2D(cx, cy-1));

        if(cx < maxX && cy > 0)
            neighPositions.add(new Int2D(cx+1, cy-1));

        return neighPositions;

    }

Solution

  • Your recursion does not appear to have a termination condition. It looks like you may want to pass strength as an argument to findEscapeSpace(), and when that method recurses for it to pass a value one less than the one passed to it.

    Other than that, your algorithm looks fairly inefficient, as it is likely to generate and test many of the reachable cells many times each, and, moreover, it will be comparatively expensive to check whether each one has already been found. But that's the next problem to overcome.