用java代码实现A*算法解决八数码难题
时间: 2023-07-20 13:08:00 浏览: 155
好的,以下是使用Java实现A*算法解决八数码问题的示例代码。
```java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
public class EightPuzzleSolver {
// 定义目标状态
private static final int[] GOAL_STATE = {1, 2, 3, 4, 5, 6, 7, 8, 0};
// 定义空白格子的移动方向
private static final int[] dx = {0, 0, -1, 1};
private static final int[] dy = {-1, 1, 0, 0};
// 定义节点类
private static class Node {
int[] state; // 当前状态
int zeroPos; // 空白格子的位置
int h; // 启发式函数的值
int g; // 到达当前状态的代价
Node parent; // 父节点
int move; // 移动方向
Node(int[] state, int zeroPos, int g, Node parent, int move) {
this.state = Arrays.copyOf(state, state.length);
this.zeroPos = zeroPos;
this.g = g;
this.parent = parent;
this.move = move;
this.h = calcHeuristicValue();
}
// 计算启发式函数的值
private int calcHeuristicValue() {
int sum = 0;
for (int i = 0; i < 9; i++) {
if (state[i] == 0) continue;
int x = (state[i] - 1) / 3;
int y = (state[i] - 1) % 3;
sum += Math.abs(x - i / 3) + Math.abs(y - i % 3);
}
return sum;
}
// 判断当前状态是否是目标状态
boolean isGoal() {
return Arrays.equals(state, GOAL_STATE);
}
// 列出所有可能的下一步状态
ArrayList<Node> expand() {
ArrayList<Node> nextNodes = new ArrayList<>();
int x = zeroPos / 3, y = zeroPos % 3;
for (int d = 0; d < 4; d++) {
int nx = x + dx[d], ny = y + dy[d];
if (nx < 0 || nx >= 3 || ny < 0 || ny >= 3) continue;
int newPos = nx * 3 + ny;
int[] newState = Arrays.copyOf(state, state.length);
newState[zeroPos] = newState[newPos];
newState[newPos] = 0;
nextNodes.add(new Node(newState, newPos, g + 1, this, d));
}
return nextNodes;
}
}
// A*算法
public static int[] solve(int[] startState) {
PriorityQueue<Node> pq = new PriorityQueue<>(Comparator.comparingInt(node -> node.h + node.g));
pq.offer(new Node(startState, getZeroPos(startState), 0, null, -1));
while (!pq.isEmpty()) {
Node node = pq.poll();
if (node.isGoal()) {
return getResult(node);
}
for (Node next : node.expand()) {
pq.offer(next);
}
}
return null;
}
// 获取空白格子的位置
private static int getZeroPos(int[] state) {
for (int i = 0; i < 9; i++) {
if (state[i] == 0) return i;
}
return -1;
}
// 获取结果路径
private static int[] getResult(Node node) {
int[] result = new int[node.g];
int i = node.g - 1;
while (node.parent != null) {
result[i--] = node.move;
node = node.parent;
}
return result;
}
public static void main(String[] args) {
int[] startState = {2, 8, 3, 1, 6, 4, 7, 0, 5};
int[] result = EightPuzzleSolver.solve(startState);
if (result != null) {
System.out.println("Steps: ");
for (int move : result) {
switch (move) {
case 0:
System.out.println("Up");
break;
case 1:
System.out.println("Down");
break;
case 2:
System.out.println("Left");
break;
case 3:
System.out.println("Right");
break;
}
}
} else {
System.out.println("No solution found.");
}
}
}
```
该代码使用了优先队列来实现A*算法,并且定义了节点类来表示八数码问题中的一个状态。在节点类中,使用了启发式函数来评估当前状态的优劣,并且列出了所有可能的下一步状态。在主函数中,可以通过调用`solve`方法来解决八数码问题,并且获取结果路径。
阅读全文