Algorithm 使用递归方法查找闭合路径或区域

Algorithm 使用递归方法查找闭合路径或区域,algorithm,recursion,lua,coronasdk,Algorithm,Recursion,Lua,Coronasdk,我有一个二维数组中的对象,我想穿过它们,从上到左,从右,我想检查是否有循环,或者更好的方法,形成闭合区域。请参阅此图片以获得更好的解释 实际上,我有一个X X Y的插槽,当用户触摸任何区域时,它会在那里添加砖块,所以我想做的是,每次用户添加砖块时,检查它是否正在创建一个闭合路径 我已经为此编写了递归函数,但它工作得不好,它总是只针对顶部,而不是右侧和左侧。这是密码 function checkTrap(y,x) if all_tiles[y][x].state == "changed" th

我有一个二维数组中的对象,我想穿过它们,从上到左,从右,我想检查是否有循环,或者更好的方法,形成闭合区域。请参阅此图片以获得更好的解释

实际上,我有一个X X Y的插槽,当用户触摸任何区域时,它会在那里添加砖块,所以我想做的是,每次用户添加砖块时,检查它是否正在创建一个闭合路径

我已经为此编写了递归函数,但它工作得不好,它总是只针对顶部,而不是右侧和左侧。这是密码

function checkTrap(y,x)

if all_tiles[y][x].state == "changed" then --if brick is added at that location

 last_move_y = y
 last_move_x = x

  --check for top
  y = y - 1
  if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to top at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for bottom
  y = y + 1
  if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to bottom at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for left
  x = x - 1
  if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to left at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for right
  x = x + 1
  if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to right at"..y..", "..x)
    return checkTrap(y, x)
  end        

elseif all_tiles[y][x] == object then
  print("it's a loop"..y..", "..x)
  return true;

else
  print("not changed")
  return false
end

end
功能检查陷阱(y,x)
如果所有的_tile[y][x].state==“已更改”,那么——如果在该位置添加了砖
最后一步
最后一步x=x
--检查顶部
y=y-1

如果(y>=1和y=1和y=1和x=1和x实现的结构不会递归到其他方向,因为只调用了第一个分支;不知何故,应该包括所有的邻居。显然,您试图在数组上实现一种。这种方法似乎绝对正确,但必须将一个单元的所有邻居都考虑在内计数。最有帮助的可能是进行连接组件分析并填充所有接触边界的连接组件。

编辑:
相反,如果使用黑色单元格进行搜索,我们应该使用白色单元格进行搜索,因为您的目标是找到由黑色单元格包围的区域,即使是对角相邻的区域。我们应该找到一组仅由黑色单元格包围的白色单元格,而不是整个主网格的边框。这应该满足您的目的

JS小提琴:

这是我提出的修正算法:

for each cell and until closed area not found
     if white and visitedValue = -1
        push cell to stack
        while stack has values and closed area not found
            pop cell from stack
            if invalid cell // Cell coordinates are invalid
                this area is not closed, so break from the while
            else
                if white
                    if visitedValue = -1
                    {
                        mark visited
                        push neighboring four cells to the stack
                    }
                    else
                        if visitedValue > currVisitNumber // The current cells are part of previous searched cell group, which was not a closed group.
                            this area is not closed, so break from the while
if closed area found
    show message
使用JQuery编程:

    function findArea() {
        var currFlag = -1, isvisited = [], isClosed = false;
        for (var k = 0; k < rows; k++) {  // Initialize the isvisited array
            isvisited[k] = [];
            for (var m = 0; m < cols; m++)
                isvisited[k][m] = -1;
        }
        for (var k = 0; k < rows && !isClosed; k++)
            for (var m = 0; m < cols && !isClosed; m++) {
                if (!isblack[k][m] && isvisited[k][m] == -1) { // Unvisited white cell
                    var cellsi = [k], cellsj = [m];
                    currFlag++;
                    isClosed = true;
                    while (cellsi.length > 0 && isClosed) { // Stack has cells and no closed area is found
                        var p = cellsi.pop(), q = cellsj.pop();
                        if (p >= 0 && p < rows && q >= 0 && q < cols) { // The cell coord.s are valid
                            if (!isblack[p][q])
                                if (isvisited[p][q] == -1) {
                                    isvisited[p][q] = currFlag; // Mark visited
                                    cellsi.push(p - 1);         // Push the coord.s of the four adjacent cells
                                    cellsj.push(q);
                                    cellsi.push(p + 1);
                                    cellsj.push(q);
                                    cellsi.push(p);
                                    cellsj.push(q + 1);
                                    cellsi.push(p);
                                    cellsj.push(q - 1);
                                }
                                else
                                    if (isvisited[p][q] < currFlag) // The current group of white cells was part of a previous group of white cells which were found to be unbound by the black cells. So, skip this group.
                                        isClosed = false;
                        }
                        else
                            isClosed = false; // The current cell is out of border. Hence skip the whole group.
                    }
                }
            }
        if (isClosed)
            alert('Closed area found');
    }
函数findArea(){
var currFlag=-1,isvisited=[],isClosed=false;
对于(var k=0;k0&&isClosed){//堆栈有单元格,未找到闭合区域
var p=cellsi.pop(),q=cellsj.pop();
如果(p>=0&&p=0&&q

JS Fiddle:

您说过实现的结构不是递归的,您能建议对这种方法进行任何更改吗?我对Lua的了解最多不过是肤浅的;返回类型是什么(在非正式意义上)在函数
的checkTrap
?checkTrap返回布尔值之后,递归调用不应立即返回其调用的值,但应存储结果,并将所有结果由
组合。您好,感谢您的帮助,但代码工作不正常。在类似[1,2,3]、[4,5,6]的场景中,[7,8,9]如果我在位置5处触摸,那么在位置7处这表示这是一个循环。希望你理解我在这里试图传达的内容?嗨,我尝试了你的新算法,但它不起作用。请看我编辑
    function findArea() {
        var currFlag = -1, isvisited = [], isClosed = false;
        for (var k = 0; k < rows; k++) {  // Initialize the isvisited array
            isvisited[k] = [];
            for (var m = 0; m < cols; m++)
                isvisited[k][m] = -1;
        }
        for (var k = 0; k < rows && !isClosed; k++)
            for (var m = 0; m < cols && !isClosed; m++) {
                if (!isblack[k][m] && isvisited[k][m] == -1) { // Unvisited white cell
                    var cellsi = [k], cellsj = [m];
                    currFlag++;
                    isClosed = true;
                    while (cellsi.length > 0 && isClosed) { // Stack has cells and no closed area is found
                        var p = cellsi.pop(), q = cellsj.pop();
                        if (p >= 0 && p < rows && q >= 0 && q < cols) { // The cell coord.s are valid
                            if (!isblack[p][q])
                                if (isvisited[p][q] == -1) {
                                    isvisited[p][q] = currFlag; // Mark visited
                                    cellsi.push(p - 1);         // Push the coord.s of the four adjacent cells
                                    cellsj.push(q);
                                    cellsi.push(p + 1);
                                    cellsj.push(q);
                                    cellsi.push(p);
                                    cellsj.push(q + 1);
                                    cellsi.push(p);
                                    cellsj.push(q - 1);
                                }
                                else
                                    if (isvisited[p][q] < currFlag) // The current group of white cells was part of a previous group of white cells which were found to be unbound by the black cells. So, skip this group.
                                        isClosed = false;
                        }
                        else
                            isClosed = false; // The current cell is out of border. Hence skip the whole group.
                    }
                }
            }
        if (isClosed)
            alert('Closed area found');
    }