问题描述
我正在创建一个二维自上而下的游戏,敌人的AI会不断跟随玩家并避开障碍物。我对路径查找算法进行了一些研究,并决定实施广度优先搜索,但是由于某种原因,即使网格正确,路径的xy坐标也会反转。
代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BFSTest {
// 1 = normal node
// 0 = obstacle
// S = start
// D = destination
private static char[][] nodes = {
{'S','1','1'},{'0','0',{'1','D'}
};
public static void main(String[] args) {
shortestPath();
}
public static List<Node> shortestPath() {
// key node,value parent
Map<Node,Node> parents = new HashMap<Node,Node>();
Node start = null;
Node end = null;
// find the start node
for (int row = 0; row < nodes.length; row++) {
for (int column = 0; column < nodes[row].length; column++) {
if (nodes[row][column] == 'S') {
start = new Node(row,column,nodes[row][column]);
break;
}
}
}
if (start == null) {
throw new RuntimeException("can't find start node");
}
// traverse every node using breadth first search until reaching the destination
List<Node> temp = new ArrayList<Node>();
temp.add(start);
parents.put(start,null);
boolean reachDestination = false;
while (temp.size() > 0 && !reachDestination) {
Node currentNode = temp.remove(0);
List<Node> children = getChildren(currentNode);
for (Node child : children) {
// Node can only be visited once
if (!parents.containsKey(child)) {
parents.put(child,currentNode);
char value = child.getValue();
if (value == '1') {
temp.add(child);
} else if (value == 'D') {
temp.add(child);
reachDestination = true;
end = child;
break;
}
}
}
}
if (end == null) {
throw new RuntimeException("can't find end node");
}
// get the shortest path
Node node = end;
List<Node> path = new ArrayList<Node>();
while (node != null) {
path.add(0,node);
node = parents.get(node);
}
printPath(path);
return path;
}
private static List<Node> getChildren(Node parent) {
List<Node> children = new ArrayList<Node>();
int x = parent.getX();
int y = parent.getY();
if (x - 1 >= 0) {
Node child = new Node(x - 1,y,nodes[x - 1][y]);
children.add(child);
}
if (y - 1 >= 0) {
Node child = new Node(x,y - 1,nodes[x][y - 1]);
children.add(child);
}
if (x + 1 < nodes.length) {
Node child = new Node(x + 1,nodes[x + 1][y]);
children.add(child);
}
if (y + 1 < nodes[0].length) {
Node child = new Node(x,y + 1,nodes[x][y + 1]);
children.add(child);
}
return children;
}
private static void printPath(List<Node> path) {
for (int row = 0; row < nodes.length; row++) {
for (int column = 0; column < nodes[row].length; column++) {
String value = nodes[row][column] + "";
// mark path with X
for (int i = 1; i < path.size() - 1; i++) {
Node node = path.get(i);
if (node.getX() == row && node.getY() == column) {
value = "X";
break;
}
}
if (column == nodes[row].length - 1) {
System.out.println(value);
} else {
System.out.print(value + " ");
}
}
}
System.out.println("Path: " + path);
}
}
class Node {
private int x;
private int y;
private char value;
public Node(int x,int y,char value) {
this.x = x;
this.y = y;
this.value = value;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public char getValue() {
return value;
}
@Override
public String toString() {
return "(x: " + x + " y: " + y + ")";
}
@Override
public int hashCode() {
return x * y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
Node node = (Node) o;
return x == node.x && y == node.y;
}
/* Output:
* S X X X
* 0 0 0 X
* 0 0 0 X
* 1 1 1 D
* Path: [(x: 0 y: 0),(x: 0 y: 1),(x: 0 y: 2),(x: 0 y: 3),(x: 1 y: 3),(x: 2 y: 3),(x: 3 y: 3)]
*/
}
谢谢!
解决方法
考虑一下。请记住,您的第一个数组索引是row
,第二个是column
。现在,按照常规的x
和y
:
-
y
索引始终引用行(因为您是垂直计数行); -
x
索引始终引用列(因为您是水平计数列)。
因此,索引网格的正确方法是nodes[y][x]