好的,所以我正在编写一个3 x 3跳汰机益智游戏,我坚持使用解决方法。
public Piece[][] solve(int r, int c) {
if (isSolved())
return board;
board[r][c] = null;
for (Piece p : pieces) {
if (tryInsert(p, r, c)) {
pieces.remove(p);
break;
}
}
if (getPieceAt(r, c) != null)
return solve(nextLoc(r, c).x, nextLoc(r, c).y);
else {
pieces.add(getPieceAt(prevLoc(r, c).x, prevLoc(r, c).y));
return solve(prevLoc(r, c).x, prevLoc(r, c).y);
}
}
我知道我没有提供有关这个谜题的更多信息,但我的算法无论具体细节如何都应该有效。我已经测试了所有辅助方法,片段是所有未使用的片段的列表,tryInsert尝试以所有可能的方向插入片段,如果片段可以插入,它将是。不幸的是,当我测试它时,我得到StackOverflow Error。
答案 0 :(得分:3)
您的DFS样式解算法算法永远不会将Piece对象重新添加到pieces
变量中。这不是合理的,很容易导致无限递归。
例如,假设您有一个简单的两件式拼图,一个2x1网格,其中唯一有效的拼图排列是[2,1]。这就是你的算法所做的:
1)将第1件放入插槽1中
2)它适合!删除这件,现在件= {2}。解决nextLoc()问题
3)现在尝试将第2件装入插槽2中......不起作用
4)解决prevLoc()
5)将件2放入槽1中
6)它适合!删除这件,件现在是空的。解决nextLoc()问题
7)没有尝试,所以我们失败了。解决prevLoc()
8)没有尝试的东西,所以我们失败了。解决prevLoc()
9)没有尝试,所以我们失败了。解决prevLoc()
无限重复广告...
正如评论者提到的那样,这可能只是问题的一部分。您的帖子中缺少很多关键代码,也可能是错误。
答案 1 :(得分:2)
我认为你需要以不同的方式构建递归。我也不确定从列表的不同位置添加和删除件是安全的;就像我宁愿避免在递归中分配一样,创建列表副本或扫描电路板可能是最安全的 到目前为止,同一件事件的例子,以避免重复使用。
public Piece[][] solve(int r, int c, List<Piece> piecesLeft) {
// Note that this check is equivalent to
// 'have r and c gone past the last square on the board?'
// or 'are there no pieces left?'
if (isSolved())
return board;
// Try each remaining piece in this square
for (Piece p : piecesLeft) {
// in each rotation
for(int orientation = 0; orientation < 4; ++orientation) {
if (tryInsert(p, r, c, orientation)) {
// It fits: recurse to try the next square
// Create the new list of pieces left
List<Piece> piecesLeft2 = new ArrayList<Piece>(piecesLeft);
piecesLeft2.remove(p);
// (can stop here and return success if piecesLeft2 is empty)
// Find the next point
Point next = nextLoc(r, c);
// (could also stop here if this is past end of board)
// Recurse to try next square
Piece[][] solution = solve(next.x, next.y, piecesLeft2);
if (solution != null) {
// This sequence worked - success!
return solution;
}
}
}
}
// no solution with this piece
return null;
}
答案 2 :(得分:1)
StackOverflowError
意味着您要么缺少有效的递归停止条件,要么尝试解决太大的问题,而应该尝试使用迭代算法。包含9件的拼图不是太大问题所以首先必须是这样的。
结束递归的条件是完成董事会。你只是试图在for
循环中插入一个片段,所以问题可能是tryInsert()
方法没有插入片段或者它没有被调用。由于您确定此方法正常,我建议您从
break;
if (p.equals(prev[r][c]))
{
System.out.println("Hello");
break;
}
因为它是唯一可能阻止插入该部件的东西。我仍然不确定我是否理解prev
角色。