So I have some recursive code which works fine on my desktop, but when I use it in an android app and push the limits of it, I get a StackOverflow exception (I guess the stack in Android is smaller than on my desktop, which is why I'm only getting the problem on Android).
So, I need to figure out how to make this method non-recursive. The method itself is not too complex. I commented the code, so it can be more easily followed.
For reference: the Island and Bridge classes both extend the HashiSymbol class. Also, a Bridge can only exist between two Islands. A Bridge can exist in memory between two Islands, but not be visible to the user if the Bridge.getUserType() method returns a value less than 1. Islands are considered "connected" if a Bridge visibly exists between them.
Also: the getConnectingIslands() method must accept a start Island, due to it being used in situations other than the one shown below.
public List<Island> getConnectingIslands(Island start) { List<Island> ret = new ArrayList<>(); ret.add(start); // SymbolMode.FLOW is used to indicate that an Island has been visited start.setMode(SymbolMode.FLOW); /* This method retrieves a map of size 0 to 4, which represents the HashiSymbol * immediately adjacent in each direction: NORTH, SOUTH, EAST, WEST */ Map<Direction,HashiSymbol> adjacent = Utilities.getAdjacentSymbols(this.puzzle, start.getLocation()); // Loops through the map for(Direction dir : adjacent.keySet()) { // If the adjacent symbol is anything other than a bridge, we ignore it if(adjacent.get(dir) instanceof Bridge) { Bridge bridge = (Bridge)adjacent.get(dir); // The bridge has to have a user type greater than 0 for it allow connections if(bridge.getUserType()<1) { continue; } // The bridge must be VERTICAL for directions NORTH or SOUTH of the start Island if(dir == Direction.NORTH || dir==Direction.SOUTH) { if(bridge.getUserDirection()!=BridgeDirection.VERTICAL) { continue; } } // The bridge must be HORIZONTAL for directions EAST or WEST of the start Island else { if(bridge.getUserDirection()!=BridgeDirection.HORIZONTAL) { continue; } } // Finds the Island object on the other end of the Bridge Island directionalIsland = getIslandInDirectionFrom(start,dir); // Checks if the Island has already been visited by seeing if its mode is FLOW if(directionalIsland.getMode()!=SymbolMode.FLOW) { // Makes the recursive call to add all the islands ret.addAll(getConnectingIslands(directionalIsland)); } } } // Returns the created array of connected islands return ret; } /** * @return {@code true} if the puzzle is solved, {@code false} if it is not */ public boolean isSolved() { // Two conditions need to be met before bother to even check if(!checkIslands() || Data.isTryMode()) { return false; } // Make the call to the recursive method List<Island> connectingIslands = getConnectingIslands(this.islands.get(0)); // The puzzle is solved if the number of connecting island is equal to the number of total islands boolean isSolved = connectingIslands.size()==this.islands.size(); // Reset mode values resetIslandMode(null); // Return true or false, depending on whether or not the puzzle is solved return isSolved; }
Does anyone have any design ideas for this? I can think of a few things, but none of them are particularly clean or fast.