冰滑动拼图路径发现

问题描述 投票:3回答:2

我为这个有点模糊的标题道歉,我不确定你会把这个拼图称为什么。

我正在寻找一种路径寻找方法,以找到行动最少的路线,而不是行进的距离。

游戏规则很简单,你必须从橙色方块移动到绿色方块,但是你只能沿着一条直线移动,并且不能停止朝那个方向移动,直到你到达一个边界(竞技场的墙壁或一个障碍,好像它们在冰上滑行。

示例地图,除非我弄错了,所需的路径(8个移动)

Arena.java:https://gist.github.com/CalebWhiting/3a6680d40610829b1b6d

ArenaTest.java:https://gist.github.com/CalebWhiting/9a4767508831ea5dc0da

我假设这最好用Dijkstras或A *路径查找算法处理,但是我不仅对这些算法不是很有经验,而且我也不知道如何定义路径规则。

感谢您提前提供的任何帮助。

java path-finding
2个回答
0
投票

我认为最好的解决方案可能是BFS,你可以用一个带有以下参数的“状态”对象来表示电路板的状态:到目前为止所做的移动次数和坐标。它还应该有一个方法来找到可达到的下一个状态(这应该相当容易编码,只需要去N,S,E,W并返回第一个阻塞点的数组)。

Create initial state (0 moves with initial coordinates)
Put in a priority queue (sorting by number moves)
while(priority queue has more states):
    Remove node
    if it is a goal state:
        return the state
    Find all neighbors of current state
    Add them to priority queue (remembering to increment number of moves by 1)

这使用隐式图表示。由于优先级队列,保证了最优性;当找到目标状态时,将以最少的动作达到目标状态。如果整个优先级队列已用尽且未返回任何状态,则不存在解决方案。由于优先级队列,此解决方案需要O(V ^ 2logV)时间,但我认为这是最简单的代码。一个直接的O(V)BFS解决方案是可能的,但是您必须跟踪您已经或尚未访问过的状态以及到达它们的移动次数最少,这将需要O(V)内存。


0
投票

这是我的解决方案(Java),以防有人仍然感兴趣。正如@tobias_k在他上面的comment中所建议的,确实BFS是要走的路:

import java.util.LinkedList;

public class PokemonIceCave {
    public static void main(String[] args) {
        int[][] iceCave1 = {
                {0, 0, 0, 1, 0},
                {0, 0, 0, 0, 1},
                {0, 1, 1, 0, 0},
                {0, 1, 0, 0, 1},
                {0, 0, 0, 1, 0}
        };
        System.out.println(solve(iceCave1, 0, 0, 2, 4));
        System.out.println();

        int[][] iceCave2 = {
                {0, 0, 0, 1, 0},
                {0, 0, 0, 0, 1},
                {0, 1, 1, 0, 0},
                {0, 1, 0, 0, 1},
                {0, 0, 0, 1, 0},
                {0, 0, 0, 0, 0}
        };
        System.out.println(solve(iceCave2, 0, 0, 2, 5));
    }

    public static int solve(int[][] iceCave, int startX, int startY, int endX, int endY) {
        Point startPoint = new Point(startX, startY);

        LinkedList<Point> queue = new LinkedList<>();
        Point[][] iceCaveColors = new Point[iceCave.length][iceCave[0].length];

        queue.addLast(new Point(0, 0));
        iceCaveColors[startY][startX] = startPoint;

        while (queue.size() != 0) {
            Point currPos = queue.pollFirst();
            System.out.println(currPos);
            // traverse adjacent nodes while sliding on the ice
            for (Direction dir : Direction.values()) {
                Point nextPos = move(iceCave, iceCaveColors, currPos, dir);
                System.out.println("\t" + nextPos);
                if (nextPos != null) {
                    queue.addLast(nextPos);
                    iceCaveColors[nextPos.getY()][nextPos.getX()] = new Point(currPos.getX(), currPos.getY());
                    if (nextPos.getY() == endY && nextPos.getX() == endX) {
                        // we found the end point
                        Point tmp = currPos;  // if we start from nextPos we will count one too many edges
                        int count = 0;
                        while (tmp != startPoint) {
                            count++;
                            tmp = iceCaveColors[tmp.getY()][tmp.getX()];
                        }
                        return count;
                    }
                }
            }
            System.out.println();
        }
        return -1;
    }

    public static Point move(int[][] iceCave, Point[][] iceCaveColors, Point currPos, Direction dir) {
        int x = currPos.getX();
        int y = currPos.getY();

        int diffX = (dir == Direction.LEFT ? -1 : (dir == Direction.RIGHT ? 1 : 0));
        int diffY = (dir == Direction.UP ? -1 : (dir == Direction.DOWN ? 1 : 0));

        int i = 1;
        while (x + i * diffX >= 0
                && x + i * diffX < iceCave[0].length
                && y + i * diffY >= 0
                && y + i * diffY < iceCave.length
                && iceCave[y + i * diffY][x + i * diffX] != 1) {
            i++;
        }

        i--;  // reverse the last step

        if (iceCaveColors[y + i * diffY][x + i * diffX] != null) {
            // we've already seen this point
            return null;
        }

        return new Point(x + i * diffX, y + i * diffY);
    }

    public static class Point {
        int x;
        int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public String toString() {
            return "Point{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    public enum Direction {
        LEFT,
        RIGHT,
        UP,
        DOWN
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.