开发者

Recursive Searching in Java

开发者 https://www.devze.com 2023-02-28 01:59 出处:网络
So I\'ve been writing a program for the game boggle. I create a little board for the user to use, but the problem is I don\'t know how to check if that word is on the board recursively. I want to be a

So I've been writing a program for the game boggle. I create a little board for the user to use, but the problem is I don't know how to check if that word is on the board recursively. I want to be able to check if the word the entered is indeed on the board, and is valid. By valid I mean, the letters of the word must be adjacent to each other. For those who have played boggle you'll know what I mean. All I want to do is check if the word is on the board.

This is what I have so far ....

import java.io.*;
public class boggle {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    private String s = "";
    private int [][] lettersNum = new int [5][5];
    private char [][] letters = new char [5][5];
    private char [] word = new char [45]; // Size at 45, because the longest word in the dictionary is only 45 letters long 
    private char [] temp; 

    public void generateNum()
    {
        for (int row = 0; row < 5; row ++)
        {
            for (int col = 0; col < 5; col++)
            {
                lettersNum [row][col] = (int) (Math.random() * 26 + 65);
            }
        }
    }

    public void numToChar()
    {
        for (int row = 0; row < 5; row ++)
        {
            for (int col = 0; col < 5; col++)
            {
                letters [row][col] = (char)(lettersNum[row][col]);
            }
        }
    }

    public void display()
    {
        for (int row = 0; row < 5; row ++)
        {
            for (int col = 0; col < 5; col++)
            {
                System.out.print(letters[row][col]);
            }
            System.out.println("");
        }
    }

    public void getInput() throws IOException
    {
        System.out.println("Please enter a word : ");
        s=br.readLine();
        s=s.toUpperCase();
        word = s.toCharArray();
    }

    public int search(int row, int col)
    {
        if((row <0) || (row >= 5) || (col < 0) || (col >= 5))
        {
            return (0);
        }
        else
        {
            temp = word;
            return (1+ search(row +1, col) +
             开发者_Python百科       search(row -1, col) + 
                    search(row, col + 1) + 
                    search(row, col-1) +
                    search(row +1, col +1)+
                    search(row +1, col -1)+
                    search(row -1, col +1)+
                    search(row -1, col -1));
        }
    }


}

The search was my searching algorithm to check if the word is on the board but I don't know if it is correct or if it will work. Furthermore, I don't know how to actually tell the user that the word is valid !

Thanks for all the help :)

SO I tried to use what you suggested below but I dont really understand the int [5][5] thing. So this is what I tried, but I keep getting out of bounds errors ! Here is the soruce ...

    public void locate()
{
    temp = word[0];
    for (int row = 0; row <5; row++)
    {
        for (int col = 0; col <5; col++)
        {
            if(temp == letters[row][col])
            {
                search(row,col);
            }
        }
    }
}

public int search(int row, int col)
{
    if(letters[row][col-1]==word[count]) // Checks the letter to the left
    {
        count++;
        letters[row][col-1] = '-'; // Just to make sure the program doesn't go back on itself
        return search(row, col-1);
    }
    else if (letters[row][col+1] == word[count])// Checks the letter to the right
    {
        count++;
        letters[row][col+1] = '-';// Just to make sure the program doesn't go back on itself
        return search(row, col +1);
    }
    else if (letters[row+1][col]== word[count])// Checks the letter below
    {
        count++;
        letters[row+1][col] = '-';// Just to make sure the program doesn't go back on itself
        return search(row +1 , col);
    }
    else if (letters[row-1][col]== word[count])// Checks the letter above 
    {
        count++;
        letters[row-1][col] = '-';// Just to make sure the program doesn't go back on itself
        return search(row -1 , col);
    }
    else if (letters[row-1][col-1]== word[count])// Checks the letter to the top left
    {
        count++;
        letters[row-1][col-1] = '-';// Just to make sure the program doesn't go back on itself
        return search(row -1 , col-1);
    }
    else if (letters[row-1][col+1]== word[count])// Checks the letter to the top right
    {
        count++;
        letters[row-1][col+1] = '-';// Just to make sure the program doesn't go back on itself
        return search(row -1 , col+1);
    }
    else if (letters[row+1][col-1]== word[count])// Checks the letter to the bottom left
    {
        count++;
        letters[row+1][col-1] = '-';// Just to make sure the program doesn't go back on itself
        return search(row +1 , col-1);
    }
    else if (letters[row+1][col+1]== word[count])// Checks the letter to the bottom right
    {
        count++;
        letters[row+1][col+1] = '-';// Just to make sure the program doesn't go back on itself
        return search(row +1 , col+1);
    }
    return 0;
}

private int count = 0; (was declared at the top of the class, in case you were wondering where I got the word[count] from


Your current search function doesn't actually do anything. I'm assuming this is homework so, no free lunch ;)

The simplest approach would be to have two recursive functions:

public boolean findStart(String word, int x, int y)

This will do a linear search of the board looking for the first character in word. If your current location doesn't match, you call yourself with the next set of coords. When it finds a match, it calls your second recursive function using word, the current location, and a new, empty 4x4 matrix:

public boolean findWord(String word, int x, int y, int[][] visited)

This function first checks to see if the current location matches the first letter in word. If it does, it marks the current location in visited and loops through all the adjoining squares except ones marked in visited by calling itself with word.substring(1) and those coords. If you run out of letters in word, you've found it and return true. Note that if you're returning false, you need to remove the current location from visited.

You can do this with one function, but by splitting out the logic I personally think it becomes easier to manage in your head. The one downside is that it does do an extra comparison for each first letter in a word. To use a single function you would need to keep track of what "mode" you were in either with a boolean or a depth counter.

Edit: Your longest word should only be 16. Boggle uses a 4x4 board and a word can't use the same location twice. Not that this really matters, but it might for the assignment. Also note that I just did this in my head and don't know that I got it 100% right - comments appreciated.

Edit in response to comments:

Here's what your iterative locate would look like using the method I outline above:

public boolean locate(String word) 
{ 
    for (int row = 0; row < 4; row++) 
    {  
        for (int col =0; col < 4; col++) 
        { 
            if (word.charAt(0) == letters[row][col])
            {
                boolean found = findWord(word, row, col, new boolean[4][4]);
                if (found) 
                    return true;
            } 
        } 
     }
     return false;
}    

The same thing recursively looks like the following, which should help:

public boolean findStart(String word, int x, int y)
{
    boolean found = false;
    if (word.charAt(0) == letters[x][y])
    {
        found = findWord(word, x, y, new boolean[4][4]);
    } 

    if (found)
        return true;
    else 
    {
        y++;
        if (y > 3)
        {
            y = 0;
            x++;
        }

        if (x > 3)
           return false;    
    }

    return findStart(word, x, y);
}        

So here's findWord() and a helper method getAdjoining() to show you how this all works. Note that I changed the visited array to boolean just because it made sense:

public boolean findWord(String word, int x, int y, boolean[][] visited)
{
    if (letters[x][y] == word.charAt(0))
    {
        if (word.length() == 1) // this is the last character in the word
            return true;
        else
        {
            visited[x][y] = true;
            List<Point> adjoining = getAdjoining(x,y,visited);

            for (Point p : adjoining)
            {
                boolean found = findWord(word.substring(1), p.x, p.y, visited);
                if (found)
                    return true;
            }
            visited[x][y] = false;
        }

    }
    return false;
}

public List<Point> getAdjoining(int x, int y, boolean[][] visited)
{
    List<Point> adjoining = new LinkedList<Point>();

    for (int x2 = x-1; x2 <= x+1; x2++)
    {
        for (int y2 = y-1; y2 <= y+1; y2++)
        {
            if (x2 < 0 || x2 > 3 ||
                y2 < 0 || y2 > 3 ||
                (x2 == x && y2 == y) ||
                visited[x2][y2])
            {
                continue;
            }

            adjoining.add(new Point(x2,y2));

        }
    }

    return adjoining;
}

So now, after you get input from the user as a String (word), you would just call:

boolean isOnBoard = findStart(word,0,0);

I did this in my head originally, then just went down that path to try and show you how it works. If I were to actually implement this I would do some things differently (mainly eliminating the double comparison of the first letter in the word, probably by combining the two into one method though you can do it by rearranging the logic in the current methods), but the above code does function and should help you better understand recursive searching.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号