シナリオはターンベースの状況で、プレイヤーはソース ロケーション A からロケーション B に向かって移動する必要がありますが、最大量のユニットしか移動できません。
たとえば、B は A から 24 ユニット離れており (BFS を使用して計算)、スコアは 12 でした。12 移動ユニットしか離れていない B への最適なパスを見つけるにはどうすればよいでしょうか?
ノート:
- 斜め移動不可
- 大きな障害物がある
編集:これは Clue / Cluedo に似たゲーム用ですが、テキストのみであるため、プレイヤーは「向かう」方向を選択します。
これが私が試したものです:
グリッドの例: (◘ は障害物、○ は障害物ではありません)
○○○○○○○○○○
○○○○○○○○◘◘
○○○◘◘◘○○◘◘
○○○◘◘◘○○B◘
○A○◘◘◘○○◘◘
アルゴリズム:
if paces == 0, return
try moving col closer to dest.col:
if col == dest.col, move row closer to dest.row
else if adjacent is blocked, move row away from start
これは紙の上では問題なく機能しますが、私が窮地に追い込まれた場合を除きます。
○A→◘◘○○◘◘◘
○○↓◘◘○○B◘◘
○○↓◘◘○○◘◘◘
○○↓◘◘○○↑◘◘
○○↓→→→→→◘◘
解決:
public ArrayList<Location> shortestPath(final Location start, final Location dest) {
HashSet<Location> visits = new HashSet<>();
HashMap<Location, Location> links = new HashMap<>();
PriorityQueue<Location> queue = new PriorityQueue<>(Board.GRID_COLS * Board.GRID_ROWS,
new Comparator<Location>() {
@Override
public int compare(Location a, Location b) {
return Integer.compare(getHeuristic(a, dest), getHeuristic(b, dest));
}
});
queue.add(start);
while (!queue.isEmpty()) {
Location current = queue.remove();
if (current.equals(dest)) {
ArrayList<Location> path = reconstruct(current, new LinkedList<Location>(), links);
path.add(dest);
return path;
}
visits.add(current);
for (Location neighbour : getNeighbours(current)) {
if (!visits.contains(neighbour)) {
queue.add(neighbour);
visits.add(neighbour);
links.put(neighbour, current);
}
}
}
return null; // failed
}
// Manhattan distance
private int getHeuristic(Location src, Location dest) {
return Math.abs(dest.row - src.row) + Math.abs(dest.col - src.col);
}
private ArrayList<Location> reconstruct(Location current, LinkedList<Location> list, HashMap<Location, Location> links) {
if (links.containsKey(current)) {
list.addFirst(links.get(current));
return reconstruct(links.get(current), list, links);
} else {
return new ArrayList<>(list);
}
}
private ArrayList<Location> getNeighbours(Location current) {
ArrayList<Location> neighbours = new ArrayList<>();
if (current.row < GRID_ROWS - 1) {
Location n = LOCATIONS[current.row + 1][current.col];
if (isAccessible(n, current)) neighbours.add(n);
}
if (current.row > 0) {
Location n = LOCATIONS[current.row - 1][current.col];
if (isAccessible(n, current)) neighbours.add(n);
}
if (current.col < GRID_COLS - 1) {
Location n = LOCATIONS[current.row][current.col + 1];
if (isAccessible(n, current)) neighbours.add(n);
}
if (current.col > 0) {
Location n = LOCATIONS[current.row][current.col - 1];
if (isAccessible(n, current)) neighbours.add(n);
}
return neighbours;
}