Java:在二维数组中搜索单词

时间:2013-01-21 12:54:41

标签: java search multidimensional-array

我已经学习Java大约4个月了,这是我学习的第一门编程语言。对于学校,我们必须做一个项目,一个基于控制台的游戏。我选择了Boggle。

我有一个带有骰子的ArrayList,每个都得到一个随机的“面朝上”,然后ArrayList被洗牌,一个二维数组充满了每一面的值。此时阵列充满了字符串,字符可能是更好的选择,但是很容易改变。

我面临的问题是我需要能够在数组中找到单词。 Boggle中的单词可以向任何方向移动,每个单独的块只能使用一次,但路径可以交叉,也可以对角搜索。我设法找到数组中是否存在第一个字母。如果不是,则可以中止搜索,如果存在,则需要开始搜索,搜索单词的第二个字符,该字符必须在第一个字符的块周围。

我做了一些数学运算,发现它总是以“i-1和j-1”为例,作为周围区块的左上角。我解决了这个问题,但似乎无法找到单词...而且,如果周围有2个“e”,我不知道如何搜索每个“e”的单词。到目前为止,这是我的代码:

这是我目前最重要的课程,即Gameboard类

public class Gameboard {

private List<Dice> dices = new ArrayList<Dice>();
private final int boardSize;
private String[][] board;
private boolean [][] blocksAvailable;
private Random random = new Random();

public GameBoard() {
    // Making the board with a given size (will be changeable later but is "4" for now)
    boardSize = 4;
    board = new String[boardSize][boardSize];
    blocksAvailable = new boolean[boardSize][boardSize];
    for(int i = 0; i < boardSize; i++) {
        for(int j = 0; j < boardSize; j++) {
            blocksAvailable[i][j] = true;
        }
    }
}

public String[][] getBoard() {
    return board;
}

public int getFullSize() {
    return boardSize*boardSize;
}

public void makeBoard() {
    //random "side up" for each dice
    for(int i = 0; i < dices.size(); i++) {
        dices.get(i).setSideUp();
    }

    // Shuffle all dices
    Collections.shuffle(dices);

    // Fill the board with the values of the dices
    int counter = 0;
    for(int i = 0; i < boardSize; i++) {
        for(int j = 0; j < boardSize; j++) {
            board[i][j] = dices.get(counter++).getSideUp();
        }
    }


}

public String showBoard() {
    //Show the board, each block divided by "|"
    String str = "";
    for(int i = 0; i < boardSize; i++) {
        for(int j = 0; j < boardSize; j++) {
            str += String.format("|%s|", board[i][j].toString());
            if(j == 3) {
                str += "\n";
            }
        }
    }
    return str;
}

public void addDices() {
    dices.add(new dice("R", "I", "F", "O", "B", "X"));
    dices.add(new dice("I", "F", "E", "H", "E", "Y"));
    dices.add(new dice("D", "E", "N", "O", "W", "S"));
    dices.add(new dice("U", "T", "O", "K", "N", "D"));
    dices.add(new dice("H", "M", "S", "R", "A", "O"));
    dices.add(new dice("L", "U", "P", "E", "T", "S"));
    dices.add(new dice("A", "C", "I", "T", "O", "A"));
    dices.add(new dice("Y", "L", "G", "K", "U", "E"));
    dices.add(new dice("Q", "B", "M", "J", "O", "A"));
    dices.add(new dice("E", "H", "I", "S", "P", "N"));
    dices.add(new dice("V", "E", "T", "I", "G", "N"));
    dices.add(new dice("B", "A", "L", "I", "Y", "T"));
    dices.add(new dice("E", "Z", "A", "V", "N", "D"));
    dices.add(new dice("R", "A", "L", "E", "S", "C"));
    dices.add(new dice("U", "W", "I", "L", "R", "G"));
    dices.add(new dice("P", "A", "C", "E", "M", "D"));
}

public boolean searchWord(String word) {
    String wordUp = woord.toUpperCase();
    String firstLetter = Character.toString(wordUp.charAt(0));


    for(int i = 0; i < boardSize;i++) {
        for(int j = 0; j < boardSize;j++) {
            if(firstLetter.equals(board[i][j]) == true) {

                int a = i;
                int b = j;
                String theLetter = "";
                // First letter found, continue search
                for(int h = 1; h < hetWoord.length(); h++) {
                    theLetter = Character.toString(wordUp.charAt(h));
                    int[] values = searchLetter(theLetter, a, b);
                    if(values[0] > -1) {
                        a = values[0];
                        b = values[1];
                    } else {
                        return false;
                    }
                }
                return true;

            }
        }
    }
    return false;
}

public int[] searchLetter(String letter, int i, int j) {
    int[] values = new int[2];

    try{if(board[i-1][j-1].equals(letter) && blocksAvailable[i-1][j-1] == true) {
        values[0] = i-1;
        values[1] = j-1;
        blocksAvailable[i-1][j-1] = false;
    }  else if(board[i-1][j].equals(letter) && blocksAvailable[i-1][j] == true) {
        values[0] = i-1;
        values[1] = j;
        blocksAvailable[i-1][j] = false;
    } else if(board[i-1][j+1].equals(letter) && blocksAvailable[i-1][j+1] == true) {
        values[0] = i-1;
        values[1] = j+1;
        blocksAvailable[i-1][j+1] = false;
    } else if(board[i][j-1].equals(letter) && blocksAvailable[i][j-1] == true) {
        values[0] = i;
        values[1] = j-1;
        blocksAvailable[i][j-1] = false;
    } else if(board[i][j+1].equals(letter) && blocksAvailable[i][j+1] == true) {
        values[0] = i;
        values[1] = j+1;
        blocksAvailable[i][j+1] = false;
    } else if(board[i+1][j-1].equals(letter) && blocksAvailable[i+1][j-1] == true) {
        values[0] = i+1;
        values[1] = j-1;
        blocksAvailable[i+1][j+1] = false;
    } else if(board[i+1][j].equals(letter) && blocksAvailable[i+1][j] == true) {
        values[0] = i+1;
        values[1] = j;
        blocksAvailable[i+1][j] = false;
    } else if(board[i+1][j+1].equals(letter) && blocksAvailable[i+1][j+1] == true) {
        values[0] = i+1;
        values[1] = j+1;
        blocksAvailable[i+1][j+1] = false;
    } else {
        values[0] = -1;  // If not found, negative values, easy to check in searchWord if letter was found
        values[1] = -1;
    }}catch (ArrayIndexOutOfBoundsException e) {

    }

    return values;
}
}

5 个答案:

答案 0 :(得分:7)

这可能会被删除,因为我不会回答你的问题。但是,请相当,请使用:

// instead of: board[i-1][j-1]

public String getBoardValue(int x, int y) {
  if (x<0 || x>=boardSize) return "";
  if (y<0 || y>=boardSize) return "";
  return board[x][y];
}

使用这种帮助方法

  • 确保没有抛出IndexArrayOutOfBoundsException
  • 始终具有非空的纸板值

答案 1 :(得分:0)

嗯,你问的问题有点复杂。你必须查看Array中单词的所有可能方向。我建议你看看迷你项目并查看他们的{{1}评估。你可以在google上找到很多项目。例如http://1000projects.org/java-projects-gaming.html

我不是要求你复制粘贴,而只是想知道以正确的方式做事。 几年前我在logic制作了一个XO游戏,可以给你代码(如果你想的话)检查x和o的组合(你可以看出代码,语法差别不大)。 / p>

答案 2 :(得分:0)

您的方法searchLetter可以重写,以便更容易理解。

public boolean isValid(int x, int y) {
   return x>= 0 && x < boardSize && y >=0 && y < boardSize;
}

public int[] searchLetter(String letter, int i, int j) {

   int[] values = new int[2];
  //initialization as not found.
   values[0] = -1;
   values[1] = -1; 
   for(int ix = i-1; ix <= i+1 ; ix++){
      for(int jx = j-1; jx <= j+1 ; jx++){
         if(i == ix && j == jx)
            //skip the cell from were the search is performed
            continue;

         if(isValid(ix,jx)
            && board[ix][jx].equals(letter) 
            && blocksAvailable[ix][jx] == true) {
              values[0] = ix;
              values[1] = jx;
              blocksAvailable[ix][jx] = false;
              //early return 
              return values;
         }
      }
    return values;
}

即使没有评论,读者也会暗示这是某种邻近搜索。

事实是你的算法应该返回一个可能的下一个位置的列表。上面的代码返回第一次出现。如果您将每对索引放在列表中而不是返回第一个索引,您将看到所有候选字母。在这样做的同时,您将实现Breath first search.

的getNeighbour或adjancentVertexes

答案 3 :(得分:0)

一个提示:一旦找到首字母,而不是逐个查找下一个字母,只需计算从该点可以得到的8个相同长度的单词。您可能会发现少于8个,具体取决于该信函在董事会中的位置。 一旦你能够在一个方向上找到它,就可以更容易地将该逻辑转换为其他可能的方向。 然后你只需要比较这些单词,如果没有匹配,找到首字母并重复相同的过程。

答案 4 :(得分:0)

我在接受采访时被问到这个问题,我没有多少时间,所以我向采访员解释了我将如何解决这个问题。他的回答似乎没问题,甚至没有让我尝试编码,可能是因为他知道这个问题不像看起来那么微不足道,而且我们没有足够的时间。在我的采访结束后,我在家尝试了一下,但我的解决方案有一些错误。一直在思考它并提出我之前发布的想法,然后注意到这篇文章是3岁,所以我决定编写它。该解决方案有效,但仍有改进的余地:

import java.util.LinkedHashSet;
import java.util.Set;


public class StringsArrays {

    public static void main(String[] args) {
        final char[][] matrix = new char[4][4];
        matrix[0] = new char[] { 'G', 'A', 'B', 'C' };
        matrix[1] = new char[] { 'O', 'O', 'E', 'F' };
        matrix[2] = new char[] { 'O', 'H', 'O', 'I' };
        matrix[3] = new char[] { 'J', 'K', 'L', 'D' };


        System.out.println(search("JOOG", matrix)); //N
        System.out.println(search("BEOL", matrix)); //S
        System.out.println(search("AB", matrix));   //E
        System.out.println(search("FE", matrix));   //W
        System.out.println(search("HEC", matrix));  //NE
        System.out.println(search("DOOG", matrix)); //NW
        System.out.println(search("GOOD", matrix)); //SE
        System.out.println(search("FOK", matrix));  //SW        
        System.out.println(search("HO", matrix));

    }

    public static boolean search(final String word, char[][] matrix) {

        final char firstLetter = word.charAt(0);
        for (int y = 0; y < matrix.length; y++) {
            for (int x = 0; x < matrix[y].length; x++) {
                if (matrix[y][x] == firstLetter) {
                    final Set<String> words = readInAllDirections(word.length(), x, y, matrix);
                    if (words.contains(word)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    enum Direction {
        NORTH, SOUTH,
        EAST, WEST,
        NORTH_EAST, NORTH_WEST,
        SOUTH_EAST, SOUTH_WEST
    }

    private static Set<String> readInAllDirections(final int length, final int x, final int y, final char[][] matrix) {
        final Set<String> words = new LinkedHashSet<>();
        for (final Direction direction : Direction.values()) {
            words.add(readWord(length, x, y, matrix, direction));
        }
        return words;
    }

    private static String readWord(final int length, final int xBegin, final int yBegin, final char[][] matrix, final Direction direction) {
        final int xEnd = getXEnd(xBegin, length, direction);
        final int yEnd = getYEnd(yBegin, length, direction);
        int x;
        int y;

        final StringBuilder matrixWord = new StringBuilder();

        if (direction == Direction.SOUTH) {
            if (yEnd > matrix.length-1) {
                return null;
            }
            for (y = yBegin; y <= yEnd; y++) {
                matrixWord.append(matrix[y][xBegin]);
            }
        }
        if (direction == Direction.NORTH) {
            if (yEnd < 0) {
                return null;
            }
            for (y = yBegin; y >= yEnd; y--) {
                matrixWord.append(matrix[y][xBegin]);
            }
        }
        if (direction == Direction.EAST) {
            if (xEnd > matrix[yBegin].length-1) {
                return null;
            }
            for (x = xBegin; x <= xEnd; x++) {
                matrixWord.append(matrix[yBegin][x]);
            }
        }
        if (direction == Direction.WEST) {
            if (xEnd < 0) {
                return null;
            }
            for (x = xBegin; x >= xEnd; x--) {
                matrixWord.append(matrix[yBegin][x]);
            }
        }
        if (direction == Direction.SOUTH_EAST) {
            if (yEnd > matrix.length-1 || xEnd > matrix[yBegin].length-1) {
                return null;
            }
            x = xBegin;
            y = yBegin;
            while (y <= yEnd && x <= xEnd) {
                matrixWord.append(matrix[y][x]);
                y++;
                x++;
            }
        }
        if (direction == Direction.SOUTH_WEST) {
            if (yEnd > matrix.length-1 || xEnd < 0) {
                return null;
            }
            x = xBegin;
            y = yBegin;
            while (y <= yEnd && x >= xEnd) {
                matrixWord.append(matrix[y][x]);
                y++;
                x--;
            }
        }
        if (direction == Direction.NORTH_EAST) {
            if (yEnd < 0 || xEnd > matrix[yBegin].length-1) {
                return null;
            }
            x = xBegin;
            y = yBegin;
            while (y >= yEnd && x <= xEnd) {
                matrixWord.append(matrix[y][x]);
                y--;
                x++;
            }
        }
        if (direction == Direction.NORTH_WEST) {
            if (yEnd < 0 || xEnd < 0) {
                return null;
            }
            x = xBegin;
            y = yBegin;
            while (y >= yEnd && x >= xEnd) {
                matrixWord.append(matrix[y][x]);
                y--;
                x--;
            }
        }

        return matrixWord.toString();
    }

    private static int getYEnd(final int y, final int length, final Direction direction) {
        if (direction == Direction.SOUTH || direction == Direction.SOUTH_EAST || direction == Direction.SOUTH_WEST) {
            // y0 + length + ? = y1
            return y + length - 1;
        }
        if (direction == Direction.NORTH || direction == Direction.NORTH_EAST || direction == Direction.NORTH_WEST) {
            // y0 - length + ? = y1
            return y - length + 1; 
        }

        // direction == Direction.EAST || direction == Direction.WEST)
        return y;
    }

    private static int getXEnd(final int x, final int length, final Direction direction) {
        if (direction == Direction.EAST || direction == Direction.NORTH_EAST || direction == Direction.SOUTH_EAST) {
            // x0 + length + ? = x1
            return x + length - 1;
        }
        if (direction == Direction.WEST || direction == Direction.NORTH_WEST || direction == Direction.SOUTH_WEST) {
            // x0 - length + ? = x1
            return x - length + 1;
        }

        // direction == Direction.NORTH || direction == Direction.SOUTH)
        return x;
    }
}