我有一个可行的解决方案,但我确信必须有更好的实施方案。在坚果壳中,问题是:
我正在开发一个连接> = 3,宝石迷阵风格的益智游戏。当'板'的状态发生变化时,我将所有部分分组,这样如果它们在水平或垂直方向上“连接”,它们就会共享一个ID。这就是我目前的做法:
[伪]
for all( array object* )
{
if !in_a_group() check_neighbours( this )
}
void check_neighbours( ID )
{
if ( check_is_same_type( left ) )
{
if !in_a_group() this.ID = ID ; check_neighbours( ID )
else if( in_a_group ) change_IDs(this.ID, ID )
}
same for right ...
up ...
down ...
}
这是我所做的非常虚伪的伪版本。 我递归调用check_neighbours,向前传递第一个分支的ID(我使用这个指针作为ID而不是生成一个)。
如果我找到一个具有不同ID的连接件,我会用新ID覆盖所有具有该ID的件(我这里有一个ASSERT,因为它实际上不应该发生。它在很多测试中还没有到目前为止)
除非作品没有ID,否则我不会在原始分支处check_neighbours。
这很好用,虽然我的伪可能缺少一些小逻辑。 我的问题是它有可能使用许多分支(这可能是我正在处理的硬件上的问题)。我已经解决了这个问题,现在我看不到另一种解决方案了。你是否觉得自己错过了一些非常明显的东西?
我也是stackoverflow的新手,对编程很新,对礼节等方面的任何建议都很受欢迎。
答案 0 :(得分:0)
您如何建议避免递归?
据我所知,你的算法基本上是一个“泛滥填充”,但有一点点扭曲。
无论如何,为了避免递归,您需要分配数组来存储未处理项的坐标并使用queue或fifo。因为你知道网格的维度(因为它是宝石迷阵式(?)游戏,你应该能够在任何地方预先分配它。
任何泛洪填充类型递归算法的伪代码。
struct Coord{
int x, y;
}
typedef std::queue<Coord> CoordQueue;
bool validCoord(Coord coord){
return (coord.x >= 0) && (coord.y >= 0)
&& (coord.x < boardSizeX) && (coord.y < boardSizeY);
}
bool mustProcessCoord(Coord coord);
void processAll(){
CoordQueue coordQueue;
Coord startPoint = Coord(0, 0);
coordQueue.pushBack(startPoint);
while (!coordQueue.empty()){
const Coord &curCoord = coordQueue.front();
//do something with current coordinates.
processCoord(curCoord);
const int numOffsets = 4;
const int offsets[numOffsets][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
for (int offsetIndex = 0; offsetIndex < numOffsets; offsetIndex++){
Coord neighborCoord = Coord(curCoord.x + offsets[offsetIndex][0],
curCoord.y + offsets[offsetIndex][1]);
if (!isValidCoord(neighborCoord) || !mustProcessCoord(neighborCoord))
continue;
coordQueue.push_back(neighborCoord);
}
coordQueue.pop_front();
}
}
看?没有递归,只是一个循环。几乎任何递归函数都可以打包成类似的东西。
如果您的底层平台是限制性的并且您没有std :: queue,则使用array(实现为数组的环形缓冲区可以像fifo队列一样)。因为您知道电路板的大小,所以可以预先计算阵列的大小。其余的应该很容易。