平面地图上最快的路径

时间:2016-02-10 20:55:19

标签: arrays unity3d path shortest-path a-star

我正在努力让单位农场木材然后把它带回营地。我正在使用包含在二维数组中的随机生成的地图。见这里:Randomly generate blocks on a flat map

我做了一些我写过的BFS,我保留了一个二维前辈阵列,我还使用一个二维数组来标记我已经检查过的位置。当我找到我正在寻找的块(木头)时,我使用前一个阵列创建了最快的路径。

此代码效果很好,直到单位数达到约100(当木材远离时,它也会变慢)。

有50个单位: enter image description here

有100个单位我得到小冻结: enter image description here

这是“BFS”:

void findPathTo<T>() {
    Queue q = new Queue();
    // Set position
    int x = (int)transform.position.x;
    int y = (int)transform.position.z;
    // Set marked array to false
    for (int i = 0; i < gm.mapSizex; i++) {
        for (int j = 0; j < gm.mapSizey; j++)
            marked[i][j] = false;
    }
    // Set predecessor array to -1
    for (int i = 0; i < gm.mapSizex; i++) {
        for (int j = 0; j < gm.mapSizey; j++) {
            for (int k = 0; k < 2; k++)
                predecessor[i][j][k] = -1;
        }
    }
    // Add element adjacent to current pos
    marked[x][y] = true;
    int[,] pos = new int[4,2] { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };
    for (int i = 0; i < 4; i++) {
        int[] l1 = { x - pos[i,0], y - pos[i,1] };
        if (l1[0] < gm.mapSizex && l1[1] < gm.mapSizey && l1[0] >= 0 && l1[1] >= 0 && !marked[l1[0]][l1[1]]) {
            q.Enqueue(l1);
            predecessor[l1[0]][l1[1]][0] = x;
            predecessor[l1[0]][l1[1]][1] = y;
        }
    }
    // For each added element 
    while (q.ToArray().Length != 0) {
        int[] l = (int[])q.Dequeue();
        if (!marked[l[0]][l[1]]) {
            marked[l[0]][l[1]] = true;
            // If the block we're searching is found create the path and exit
            if (gm.map[l[0]][l[1]] != null && gm.map[l[0]][l[1]].GetType() == typeof(T)) {
                dest = (ObjectInterface)gm.map[l[0]][l[1]];
                if(gm.map[l[0]][l[1]].isFarmable())
                    gm.map[l[0]][l[1]] = null;
                int i = l[0];
                int j = l[1];
                // Set the path
                while (i >= 0 && j >= 0 && predecessor[i][j][0] != -1 && predecessor[i][j][1] != -1) {
                    path.Push(predecessor[i][j]);
                    i = predecessor[i][j][0];
                    j = predecessor[i][j][1];
                }
                int[] next = (int[])path.Pop();
                destX = next[0];
                destY = next[1];
                break;
            }
            // If we can move on this surface add unmarked adjacent blocks
            if (gm.map[l[0]][l[1]] == null) {
                for (int i = 0; i < 4; i++) {
                    int[] l1 = { l[0] - pos[i, 0], l[1] - pos[i, 1] };
                    if (l1[0] < gm.mapSizex && l1[1] < gm.mapSizey && l1[0] >= 0 && l1[1] >= 0 && !marked[l1[0]][l1[1]]) {
                        q.Enqueue(l1);
                        predecessor[l1[0]][l1[1]][0] = l[0];
                        predecessor[l1[0]][l1[1]][1] = l[1];
                    }
                }
            }
        }
    }
}

BFS的想法不能支持大量的单位,所以我可能应该使用A *(我还没有读过很多)。但是我也考虑过制作一个二维阵列(对于木材,我将不得不再添加一个金色......),其中包含了去往最近的木块的继承者,但它必须经常更新所以这可能不是一个好主意。

您怎么看?

0 个答案:

没有答案