Java—编写2d数组的搜索算法,该算法通过在任何排序块中移动1步来查找所有路径
我正在调试我的类。这个类正在通过一个boggle board并找到每一条可用的路径。路径包括水平、垂直和对角线。你不能重复一步。我现在有很多打印语句试图找出我的错误,但我似乎找不到。我把这些留在家里了。我想这与我的当前路径[]有关。任何提示都将不胜感激Java—编写2d数组的搜索算法,该算法通过在任何排序块中移动1步来查找所有路径,java,arrays,search,stack,Java,Arrays,Search,Stack,我正在调试我的类。这个类正在通过一个boggle board并找到每一条可用的路径。路径包括水平、垂直和对角线。你不能重复一步。我现在有很多打印语句试图找出我的错误,但我似乎找不到。我把这些留在家里了。我想这与我的当前路径[]有关。任何提示都将不胜感激 public class FindWords { String [][] board; final int LAST_LETTER = 2; final int BEEN_THERE = 1; final int AVAILABLE = 0; B
public class FindWords {
String [][] board;
final int LAST_LETTER = 2;
final int BEEN_THERE = 1;
final int AVAILABLE = 0;
BoggleDictionary Dictionary;
private StackADT<SearchWords> searchStack = new ArrayStack<SearchWords>();
public StackADT<SearchWords> foundStack = new ArrayStack<SearchWords>();
public FindWords (String [][] board) throws Exception {
this.board = board;
this.Dictionary = new BoggleDictionary();
//this.foundStack = null;
}
public void startSearch(){
for (int i = 0; i < board.length; i++){
for (int j = 0; j < board[0].length; j++){
System.out.println(board[i][j]);
String firstLetter = "";
int [][] pathBoard = makeBlankBoard();
pathBoard[i][j] = LAST_LETTER;
System.out.println(">>" + Arrays.deepToString(pathBoard));
firstLetter = board[i][j];
System.out.println("first letters : " + firstLetter + " <====");
SearchWords thisPath = new SearchWords(pathBoard, firstLetter);
searchStack.push(thisPath);
}
}
Search();
}
private boolean Search(){
while (!searchStack.isEmpty())
{
SearchWords searchObj = searchStack.pop();
int [][] currentPath = searchObj.getPath();
int [][] array = new int [currentPath.length][currentPath[0].length];
for (int i = 0; i <currentPath.length; i++){
for (int j = 0; j <currentPath[0].length; j++){
array[i][j] = currentPath[i][j];
}
}
String makingString = searchObj.getString();
if (makingString.length() > 2){
if (Dictionary.contains(makingString)){
foundStack.push(searchObj);
}
}
for (int i = 0; i < array.length; i ++){
for (int j = 0; j < array[0].length; j++){
if (array[i][j] == LAST_LETTER){ //finding the last position in the string
int x = i;
int y = j;
//array[i][j] = BEEN_THERE;
pushPosition(searchObj, x+1, y+1, i, j); //lower left then going counter-clockwise
pushPosition(searchObj, x, y+1, i, j);
pushPosition(searchObj, x-1, y+1, i, j);
pushPosition(searchObj, x-1, y, i, j);
pushPosition(searchObj, x-1, y-1, i, j);
pushPosition(searchObj, x, y-1, i, j);
pushPosition(searchObj, x+1, y-1, i, j);
pushPosition(searchObj, x+1, y, i, j);
}
}
}
}
return true;
}
private void pushPosition (SearchWords obj, int x, int y, int i, int j){
int [][] currentPath = obj.getPath();
String makingString = obj.getString();
System.out.println("In push method: " + Arrays.deepToString(currentPath) +x+y+i+j);
if (validPosition(x, y, currentPath)){
currentPath[x][y] = LAST_LETTER;
currentPath[i][j] = BEEN_THERE;
System.out.println("after valid ch: "+ Arrays.deepToString(currentPath));
makingString = makingString + board[x][y];
SearchWords newPath = new SearchWords(currentPath, makingString);
System.out.println("is string getting longer: " + makingString);
System.out.println("Stack size: " + searchStack.size());
System.out.println("pushing back on stack"+ Arrays.deepToString(currentPath));
searchStack.push(newPath);
}
}
private boolean validPosition (int x, int y, int [][] path){
boolean result = false;
if (x >= 0 && x < board.length && y >= 0 && y < board[x].length){
if (path[x][y] == AVAILABLE){
System.out.println("Checked position : " + x + y);
result = true;
}
}
return result;
}
private int [][] makeBlankBoard(){
int row = board.length;
int col = board[0].length;
int [][] blankBoard = new int [row][col];
for (int i = 0; i < board.length; i++){
for (int j = 0; j < board[0].length; j++){
blankBoard[i][j] = AVAILABLE;
}
}
return blankBoard;
}
如注释中所述,您遇到的具体问题似乎是多个路径共享同一个数组,该数组描述了您在其中搜索的路径。这会产生bug,其中它们的搜索历史会相互覆盖,在
currentPath
数组中留下一组不太有用的信息
为每个被推送的路径执行数组复制可能会解决这个问题(代码中可能还有其他问题,但我没有发现任何问题)
我主张使用不同的方法来存储路径数组,因为实际上没有必要每次都复制整个网格。相反,您可以按以下方式跟踪每条路径:
- 路径中最后一个字母的位置(对于在路径中执行下一步非常有用,如在算法中)
- 指向该点的上一条路径(将是同一类型的对象)
在初始循环(
startSearch
)中,您将推送没有优先路径的对象(newsearchpath(i,j,board,null)
)。在search
循环中,您将弹出其中一个,然后推送一个新的搜索路径(SearchPath.x-1,SearchPath.y,board,SearchPath)
检查新的x/y坐标是否未通过contains
方法使用后。(请注意,可能也不需要使用堆栈来存储搜索路径,因为您只需进行递归搜索调用即可获得相同的搜索模式。)你能更深入地了解预期的行为吗?我看到的一个错误是,在搜索
方法的每次迭代中,你都会复制一份当前路径数组,但在随后的pushPosition
调用中会重复使用此副本8次。这就是为什么你会看到很多2(最后一个字母
)在您的currentPath
Yes中。这只是一个小2x2数组。我将每个元素作为起始位置推送。然后我的搜索将找到所有有效移动(每个元素有3个)在那个位置抓取信件,更新它的位置以及它抓取的最后一封信的位置,然后将它推回到堆栈上。然后我会再次弹出并做同样的事情,直到我抓取了所有路径。这有帮助吗?我想我明白你的意思,但我不确定修复方法。我应该在每次打电话之前复制一份吗?谢谢你。我喜欢这个,但在我等待的时候,我接受了你的初始评论,决定将我的大部分类都删除并重新启动。在调用push方法之前,我创建了一个新方法,该方法创建了数组的精确副本。而且…它可以工作!!感谢你的帮助。我现在明白了我是如何使用相同的路径板的。我将标记你的答案为正确(我也没有测试过,但看起来应该测试过)我也会在下面为所有观众发布我的更改。
private void Search(){
while (!searchStack.isEmpty())
{
System.out.println("stack size in search: " + searchStack.size());
SearchWords searchObj = searchStack.pop();
int lastLetterRow = searchObj.getRow();
int lastLetterCol = searchObj.getCol();
String stringSoFar = searchObj.getString();
int [][] pathBoard = searchObj.getPath();
System.out.println ("row then Col: " + lastLetterRow + lastLetterCol);
System.out.println ("string so far: " + stringSoFar);
System.out.println("Path board so far in search: " + Arrays.deepToString(pathBoard)+ "\n");
if (stringSoFar.length() > 2){
if (Dictionary.contains(stringSoFar)){
foundStack.push(searchObj);
System.out.println("Found word!! " + stringSoFar);
}
}
System.out.println("made it past if dict");
//lower left then going counter-clockwise
pushPosition (pathBoard, stringSoFar, lastLetterRow+1, lastLetterCol+1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition (pathBoard, stringSoFar, lastLetterRow, lastLetterCol+1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow, lastLetterCol+1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow-1, lastLetterCol+1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow-1, lastLetterCol, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow-1, lastLetterCol-1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow, lastLetterCol-1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow+1, lastLetterCol-1, lastLetterRow, lastLetterCol);
pathBoard = makeCopy(pathBoard);
pushPosition(pathBoard, stringSoFar, lastLetterRow+1, lastLetterCol, lastLetterRow, lastLetterCol);
}
System.out.println("FOUND WORDS:");
while(!foundStack.isEmpty()){
SearchWords foundWords = foundStack.pop();
System.out.println(foundWords.getString());
}
}
class SearchPath {
int x, y;
String string;
SearchPath prior;
// x,y are most recent position; prior is the path up to this point, or null
public SearchPath(int x, int y, String board, SearchPath prior) {
this.x = x;
this.y = y;
this.string = (prior != null ? prior.string : "") + board[x][y];
this.prior = prior;
}
// To check if an x,y location collides with this path
public contains(int x, int y) {
if (this.x == x && this.y == y) {
return true;
} else if (prior == null) {
return false;
} else {
return prior.contains(x,y);
}
}
}