Zig-zag填充算法?

时间:2016-01-08 04:08:24

标签: algorithm fill game-maker

如何使zig-zag算法填充任意大小的网格,如下图所示?

Visual representation. Arrows show which direction it should go to.

这是我的算法,它不起作用。 (从左下角到右上角开始):

x1 = 0;
y1 = grid_h-1;
var a = 0;
put(x1,y1);

while(!((x1 = grid_w-1) and (y1 = 0))) { //If it isn't at the top right corner
    if a = 2 {
        x1 += 1;
        put(x1,y1);
        while(x1 != grid_w-1) { //While x1 isn't at the right
            //Go diagonally down
            x1 += 1;
            y1 += 1;
            put(x1,y1);
        }
        y1 -= 1;
        put(x1,y1);
        while(y1 != 0) { //While y1 isn't at the top
            //Go diagonally up
            x1 -= 1;
            y1 -= 1;
            put(x1,y1);
        }
    } else if a = 1 {
        while(x1 != grid_w-1) { //While x1 isn't at the right
            //Go diagonally down
            x1 += 1;
            y1 += 1;
            put(x1,y1);
        }
        y1 -= 1;
        put(x1,y1);
        while(y1 != 0) { //While y1 isn't at the top
            //Go diagonally up
            x1 -= 1;
            y1 -= 1;
            put(x1,y1);
        }
        x1 += 1;
        put(x1,y1);
    } else {
        y1 -= 1;
        if (y1 = 0) { a = 1; } //At top?
        put(x1,y1);
        while(y1 != grid_h-1) { //While y1 isn't at the bottom
            //Go diagonally down
            x1 += 1;
            y1 += 1;
            put(x1,y1);
        }

        x1 += 1;
        put(x1,y1);
        while(x1 != 0) { //While x1 isn't at the left
            //Go diagonally up
            x1 -= 1;
            y1 -= 1;
            put(x1,y1);
            if (y1 = 0) { a = 2; } //At top?
        }
    }
}

更简单的方法吗?

3 个答案:

答案 0 :(得分:2)

这里的关键观察是,当左上方的Manhattan distance为奇数时,你会向东北方向移动,否则就是西南方。

当然,你必须考虑击中其中一个边缘。例如,当你向西南方向行走并撞到底部或南边时,你向东移动;当你向左或向西边缘时,你向南移动。您可以捕捉三种情况(南边,西边,无限制的移动),也可以在走出界限时移动并纠正您的位置。

击中一个adge之后,你的新位置应该让你移动另一个方向。也就是说,每次校正涉及奇数个步骤。 (这里的步骤是您正常走向的点与最终点之间的曼哈顿距离。)

如果您的zigzagging算法正常工作,您将最终访问每个单元格一次。那就是你让 h × w 移动,其中 h w 是高度和宽度。您可以将此作为终止标准,而不是检查您是否在最后一个方格中。

以下是此解决方案的示例代码。附加布尔参数down指定第一步是向下还是向左。

function zigzag(width, height, down) {
    var x = 0;
    var y = 0;
    var n = width * height;

    if (down === undefined) down = false;

    while (n--) {
        var even = ((x + y) % 2 == 0);

        put(x, y);

        if (even == down) {             // walk southwest
            x--;
            y++;

            if (y == height) {
                y--; x += 2;
            }
            if (x < 0) x = 0;
        } else {                        // walk northeast
            x++;
            y--;

            if (x == width) {
                x--; y += 2;
            }
            if (y < 0) y = 0;
        }
    }

    return res;
}

答案 1 :(得分:0)

这是滥用if语句的解决方案。

x1 = 0;
y1 = 0;
put(x1,y1);

var a = 0;
while(!((x1 = grid_w-1) and (y1 = grid_h-1))) {
    switch(a) { //Down, Right-Up, Right, Left-Down
        case 0: y1++; break;
        case 1: x1++;y1--; break;
        case 2: x1++; break;
        case 3: x1--;y1++; break;
    }
    put(x1,y1);
    if (a = 2) { //If moved right.
        if (x1 = grid_w-1) or (y1 = 0) { //If at the right or top edge. Go left-down.
            a = 3
        } else if (y1 = grid_h-1) { //At bottom edge. Go right-up.
            a = 1
        }
    } else if (y1 = 0) { ///At top edge.
        if (x1 = grid_w-1) { //If at the right corner. Go down.
            a = 0;
        } else { //Go right.
            a = 2;
        }
    } else if (a = 3) { ///If moved left-down.
        if (y1 = grid_h-1) { //At bottom n edge. Go right.
            a = 2
        } else if (x1 = 0) { //At left edge and not bottom. Go down.
            a = 0
        }
    } else if (a = 0) { //If moved down.
        if (x1 = 0) { //If at the left corner. Go right-up.
            a = 1
        } else if (x1 = grid_w-1) { //If at the right corner. Go left-down.
            a = 3
        } else { //Go right
            a = 2
        }
    } else if (a = 1) { //If right-up.
        if (x1 = grid_w-1) {  //If at the right corner.
            if (a = 2) { //If moved right. Go left-down.
                a = 3
            } else { //Go down.
                a = 0
            }
        }
    }
}

如果大小为1,则效果不佳。

答案 2 :(得分:0)

基本上我们可以使用状态图和递归来解决这个问题。

permitted_directions = {
"start":["down", "side"], 
"down":["north_east", "south_west"], 
"north_east":["north_east", "side","down"], 
"side":["north_east", "south_west"], 
"south_west":["south_west","down", "side"]
}

def is_possible(x, y, pos):
    if pos == "down":
        if x+1 < row and y >=0 and y < col:
            return (True, x+1, y)
    if pos == "side":
        if x >= 0 and x < row and y+1 >=0 and y+1 < col:
            return (True, x, y+1)
    if pos == "north_east":
        if x-1 >= 0 and x-1 < row and y+1 >= 0 and y+1 < col:
            return (True, x-1, y+1)
    if pos == "south_west":
        if x+1 >= 0 and x+1 < row and y-1 >= 0 and y-1 < col:
            return (True, x+1, y-1)
    return (False, 0, 0)

def fill_the_grid(grid, x, y, position, prev):
    grid[x][y] = prev
    prev = (x, y)
    for pos in permitted_directions[position]:
        possible, p, q = is_possible(x, y, pos)
        if possible:
            return fill_the_grid(grid, p, q, pos, prev)
    return grid