连通房

时间:2011-07-31 05:45:32

标签: javascript algorithm

我为我正在研究的游戏创建了一个简单的算法,创建了类似洞穴的结构。该算法输出表示开放区域的2维位数组。例如:

000000000000000000000000
010010000000000111100000
011110000000011111111000
011111110000011111111100
011111111001111111111110
011000000000001111000000
000000000000000000000000

(0代表墙,1代表开放区域)

问题是该算法有时可以创建一个具有2个非连接部分的洞穴(如上例所示)。我写了一个函数,给我一个数组,包含每个区域的开放点的所有x,y位置

我的问题是,给定一些列表,其中包含每个开放区域的所有x,y坐标,“连接”这些区域的最快方式是最小宽度为2的走廊。

(我在javascript中写这个,但即使只是伪代码也会帮助我)

我已经尝试比较一个区域中每个点到另一个区域中每个其他区域的距离,找到距离最近的两个点然后从这两个点切出一条路径,但这种方法是缓慢的我希望还有另一种方式。

3 个答案:

答案 0 :(得分:0)

给定两个洞穴A和B,选择A中的点x和B中的y(随机选择,两个最接近或局部最近的更好)。在A和B之间钻一个厚度为2的走廊(使用Bresenham's algorithm)。如果您有多个断开连接的洞穴,请对所有洞穴图形的最小生成树的每条边(A,B)执行上述操作(边缘权重是您选择此边缘时将钻取的道路长度)。

修改编辑以估算两个洞穴之间的距离,您可以使用hill climbing。它将返回O(n)中凸凹洞的全局最小值,而不是天真的O(n 2 )。对于非凸洞穴,进行多次爬山迭代,随机选择初始猜测。

答案 1 :(得分:0)

如果您需要完全最小的解决方案,您可以考虑首先构建洞穴的边界,然后应用O(nm)算法。这样就无需比较洞穴内部点之间的距离。然后,只要您知道每对洞穴之间的距离,就可以构建最小的生成树,然后钻取隧道。

答案 2 :(得分:0)

由于我对你的描述不太了解,这里有一些我会考虑的提示:

你如何寻找这对最近的点?你是否使用天真的蛮力方法,因此获得O(n*n)的运行时间?或者您使用的是更有效的变体taking O(n log n) time

如果您已获得最近的分数,我会使用简单的line-drawing algorithm

另一种方法可能是您生成的结构肯定只有一个连接区域。因此,您可以执行以下操作:首先,您将随机单元格(x,y)设置为1。然后,您遍历所有邻居,并为每个邻居将其随机设置为1或将其保留在0。对于设置为1的每个单元格,您也会这样做,即您遍历它的邻居并将它们随机设置为10。这可以保证您不会有两个独立的区域。

确保这一点的算法可以是以下(在python中):

def setCell(x,y,A):
    if x>=len(A) or y>=len(A[0]) or x<0 or y<0:
        return
    A[x][y] = 1

def getCell(x,y,A):
    if x>=len(A) or y>=len(A[0]) or x<0 or y<0:
        return 1
    return A[x][y]

def generate(height, width):
    A = [[0 for _ in xrange(width)] for _ in xrange(height)]
    from random import randint
    import Queue
    (x,y) = (randint(0, height-1), randint(0, width-1))
    setCell (x,y,A)
    q = Queue.Queue()
    q.put((x,y))
    while not q.empty():
        (x,y) = q.get()
        for (nx, ny) in [(x+1,y), (x-1,y), (x,y+1), (x,y-1)]:
            if randint(0,8)<=6:
                if getCell(nx,ny,A)==0:
                    setCell(nx,ny,A)
                    if randint(0,2)<=1:
                        q.put((nx,ny))
    return A

def printField(A):
    for l in A:
        for c in l:
            print (" " if c==1 else "X"), 
        print ""

然后printField(generate(20,30))完成这项工作。可能你必须调整随机内容的参数,以满足你的需求。