[英]Ice Sliding Puzzle Path Finding
我為這個有點模糊的標題道歉,我不確定你會把這個拼圖稱為什么。
我正在尋找一種路徑查找方法,以找到移動最少的路線,而不是行進的距離。
游戲規則很簡單,你必須從橙色方塊移動到綠色方塊,但你只能沿着一條直線移動,並且不能停止朝那個方向移動,直到你到達一個邊界(競技場的牆壁或一個障礙,好像它們在冰上滑行。
示例地圖,除非我弄錯了,所需的路徑(8個移動)
Arena.java: https://gist.github.com/CalebWhiting/3a6680d40610829b1b6d
ArenaTest.java: https://gist.github.com/CalebWhiting/9a4767508831ea5dc0da
我假設這最好用Dijkstras或A *路徑查找算法處理,但是我不僅對這些算法不是很有經驗,而且我也不知道如何定義路徑規則。
感謝您提前提供的任何幫助。
我認為最好的解決方案可能是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)內存。
這是我的解決方案(Java),以防有人仍然感興趣。 正如@tobias_k在上面的評論中所建議的那樣, 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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.