首先:这不是家庭作业,而是属于我的业余爱好项目。
背景 对于我的Java益智游戏,我使用一个非常简单的递归算法来检查“地图”上的某些空格是否在放置一块之后变得孤立。在这种情况下隔离意味着:没有任何部件可以放入。
当前算法:
public int isolatedSpace(Tile currentTile, int currentSpace){
if(currentTile != null){
if(currentTile.isOpen()){
currentTile.flag(); // mark as visited
currentSpace += 1;
currentSpace = isolatedSpace(currentTile.rightNeighbor(),currentSpace);
currentSpace = isolatedSpace(currentTile.underNeighbor(),currentSpace);
currentSpace = isolatedSpace(currentTile.leftNeighbor(),currentSpace);
currentSpace = isolatedSpace(currentTile.upperNeighbor(),currentSpace);
if(currentSpace < 3){currentTile.markAsIsolated();} // <-- the problem
}
}
return currentSpace;
}
这段代码返回起始tile所属的空白空间的大小。代码的那部分工作是有意的。但是我遇到了关于标记瓷砖的问题,这就是使这个问题的标题相关的原因;)
问题: 问题是某些磁贴永远不会“重新访问”(它们会返回一个值并终止,因此永远不会从后来的版本中获取返回值来更新空白区域的大小)。这些“遗忘”的磁贴可以是大空间的一部分,但仍然标记为隔离,因为当 currentSpace 值较低时,它们在进程开始时被访问过。
问题: 如何改进此代码,以便为瓷砖设置正确的值而不会产生太多开销?我可以想到丑陋的解决方案,比如重新访问所有标记的磁贴,如果它们具有正确的值,则检查邻居是否具有相同的值,如果没有更新等等。但我确信Stack Overflow上有很多优秀的人有更好的想法; )
更新 我做了一些改变。
public int isolatedSpace(Tile currentTile, int currentSpace, LinkedList<Tile> visitedTiles){
if(currentTile != null){
if(currentTile.isOpen()){
// do the same as before
visitedTiles.add();
}
}
return currentSpace;
}
标记函数(仅在返回的spaceize小于给定值时调用)
marktiles(visitedTiles){
for(Tile t : visitedTiles){
t.markAsIsolated();
}
}
这种方法符合雷克斯克尔的答案,至少如果我理解他的想法。
答案 0 :(得分:2)
这不是一般解决方案,但如果它们出现在两个或更少空格的区域中,则只将空格标记为已隔离。你不能简化这个测试,“如果(a)它没有开放的邻居或者(b)恰好是一个开放的邻居,而且该邻居没有其他开放的邻居,那么这个空间是孤立的。”
答案 1 :(得分:1)
您需要有两个步骤:收集有关空间是否隔离的信息,然后单独标记为隔离。因此,您需要首先计算所有空间(使用一个递归函数),然后在标准通过时标记所有连接的空格(使用不同的递归函数)。