简体   繁体   中英

Java: Remembering a result from a previous step in a recursive method

I'm working on a Boggle game and some people told me the best way to search words is using recursion. I'm trying out a searchWord method to search the word. If the first letter is found, the method calls itself and drops the first letter. The method returns true when the length == 0 (word is found) or false (when the letter is not found). Problem is sometimes in boggle one "dice" has a same letter multiple times around it... To solve that I need to count that letter and if it's there more than once, it should search for the next appearance of that letter (search for the same word without dropping first letter). I need a way to memorize that letter and the index of the letter around which the multiple letters bound so it can be used when the letter is not found to check if there would be other possibilities. Since it's a recursive method I have no idea how to put these in a variable because they would be changed whenever the method calls itself...

Hope you guys can help! Here's the method:

public boolean searchWord(String word, int i, int j) {
    boolean res;
    if (word.length() == 0) {
        res = true;
    } else {
        String theWord = word.toUpperCase();
        int[] indexes = searchLetter(Character.toString(theWord.charAt(0)), i, j);
        if (indexes[0] > -1) {
            res = searchWord(theWord.substring(1), indexes[0], indexes[1]);
        } else if(countLetter(Character.toString(/*The value that has to be memorized*/), /*index 1 that has been memorized*/, /*index 2 that has been memorized*/) > 1) {
            res = searchWord(theWord, i, j);
        } else {
            res = false;
        }
    }
    return res;
}

Note: yes I use Strings which is weird because chars may be a better option but I could change that later.

In principle, you could pass any such values as additional parameters. That way, the parameter/call stack is acting as your stack.

Just add another parameter to your method. You can, eg, create an object that simply holds the letter and an int. Since Java only passes the reference to this object when making the recursive call (but does not copy the object itself), the parameter will always point to the same object. You might want to use Java's pair class (if I remember correctly, it's used in maps).

Goal: to see if a word exists on a Boggle board

Assumptions:

  • Each position (ie cube) can only be used once per word

  • Each letter must be adjacent (vertically, horizontally, or diagonally)

Here's my attempt at the pseudocode for doing this with recursion (where the boggle board is a 2D array of characters - which should already be populated with the characters prior to calling this method):

// searches for a single occurence of a word on the boggle board
boolean searchWord(String word, char[][] board)
    for each position on the board (x,y)
        boolean[][] visited = new boolean[width][height] // all false
        if (searchWord(x,y,board,visited))
            return true
    return false

// searches a position on the board
boolean searchWord(String word, int x, int y, char[][] board, boolean[][] visited)
    if x and y are valid (0 >= x < width and 0 >= y < height)
        if visited[x][y] == false
            visited[x][y] = true
            if the letter at x,y equals the 1st char of the search word
                if word.length() == 1
                    return true
                else
                    for each surrounding position (x2, y2)
                        if searchWord(word.substring(1),x2,y2,board,visited)
                            return true
    return false

As you can see recursion is a good choice for path-finding (finding boggle words). You just need to pass the current state (the visited array in this case) so you know where you've already been.

I've used parameters to store the state, but you can use instance variables if you really want. I would recommend using parameters as it aligns with the functional programming paradigm, and is far less likely to suffer unexpected side-effects.

Explicitly using a stack isn't really necessary here. Stacks are great when values have scope (like local variables in Java) and should be accessed in a particular order, which doesn't really help here. FYI by using recursion you're making use of Java's call stack anyway and if you're not careful you can recurse forever and you'll get a StackOverflowException ;)

You should rewrite this to use a Stack. Recursion is almost always better done with a Stack. Then you can store some information about the context and just push things onto the stack that need more processing and pop things off when you are ready to process them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM