我正在努力避免无限循环,并且无法弄清楚什么是错误的。这应该是为3x2拼图板找到解决方案。我怀疑问题可能出在我的被覆盖的equals方法上,但我不确定。遇到两个问题:
1)它不断重新探索已经探索过的节点。
2)在找到解决方案之前队列为空,导致错误。
驱动程序类:
import java.util.*;
public class Driver {
public static void main(String[] args){
Node test = new Node(new int[]{1, 4, 2, 5, 3, 0}, null);
BFS(test);
System.out.println("done");
}
public static void BFS(Node initial){
Queue<Node> queue = new LinkedList<>();
ArrayList<Node> explored = new ArrayList<>();
queue.add(initial);
Node current = initial;
while (!current.isGoal()){
current = queue.remove();
for (Node child: current.getChildren()){
if (!explored.contains(child)) queue.add(child);
}
explored.add(current);
current.print();
}
System.out.println("DONEDONEDONE");
current.printTrace();
}
public static void DFS(Node initial){
}
}
节点类:
import java.lang.reflect.Array;
import java.util.*;
public class Node {
int[] state;
Node parent;
public Node(int[] initialState, Node parent){
this.parent = parent;
this.state = initialState;
}
public boolean isGoal(){
int[] goal = {0,1,2,3,4,5};
return Arrays.equals(this.state, goal);
}
public ArrayList<Node> getChildren(){
ArrayList<Node> children = new ArrayList<>();
Integer[] newInt = new Integer[getState().length];
for (int i = 0; i < getState().length; i++) {
newInt[i] = Integer.valueOf(getState()[i]);
}
int position = Arrays.asList(newInt).indexOf(0);
switch(position){
case 0:
children.add(new Node(switchPos(0,3), this));
children.add(new Node(switchPos(0,1), this));
break;
case 1:
children.add(new Node(switchPos(1,0), this));
children.add(new Node(switchPos(1,4), this));
children.add(new Node(switchPos(1,2), this));
break;
case 2:
children.add(new Node(switchPos(2,1), this));
children.add(new Node(switchPos(2,5), this));
break;
case 3:
children.add(new Node(switchPos(3,0), this));
children.add(new Node(switchPos(3,4), this));
break;
case 4:
children.add(new Node(switchPos(4,3), this));
children.add(new Node(switchPos(4,5), this));
children.add(new Node(switchPos(4,1), this));
break;
case 5:
children.add(new Node(switchPos(5,2), this));
children.add(new Node(switchPos(5,4), this));
break;
}
return children;
}
public int[] getState(){
return this.state;
}
public int[] switchPos(int index1, int index2){
int[] newer = getState().clone();
int temp = newer[index1];
newer[index1] = newer[index2];
newer[index2] = temp;
return newer;
}
public void print(){
System.out.println("---------");
System.out.println(Arrays.toString(Arrays.copyOfRange(getState(), 0, 3)));
System.out.println(Arrays.toString(Arrays.copyOfRange(getState(), 3, 6)));
System.out.println("---------");
}
public void printTrace(){
Stack<Node> stack = new Stack<>();
Node current = this;
while (current.parent != null){
stack.push(current);
current = current.parent;
}
while (!stack.isEmpty()){
stack.pop().print();
}
}
@Override
public boolean equals(Object object){
Node node2 = (Node) object;
return (Arrays.equals(node2.getState(), this.getState()));
}
}
答案 0 :(得分:0)
您的代码中唯一真正的错误是您不会在while
条件下检查队列是否为空,因此假设所有状态都可以从任何初始状态获得(这是#s;只是不正确)。
我还应该提到将节点标记为&#34;探索&#34;处理节点后不是最佳策略,因为在处理任何节点之前,可能会将重复节点排入队列(来自不同的父节点)。请注意,它们都将打印为current
,尽管它们的所有子项都已处理完毕 - 这可能看起来您的算法正在重新探索相同的节点。事实上,它并没有。它只是浪费周期,这就是全部。
这是一个更好的驱动程序版本,它不允许在队列中重复:
Queue<Node> queue = new LinkedList<>();
ArrayList<Node> explored = new ArrayList<>();
queue.add(initial);
Node current = initial;
explored.add(initial);
while (!queue.isEmpty() && !current.isGoal()){
current = queue.remove();
for (Node child: current.getChildren()){
if (!explored.contains(child)) {
queue.add(child);
explored.add(child);
}
}
current.print();
}
必不可少的是,每个节点都标记为&#34;探索&#34;当它第一次被推入队列时。但是,它仍未达到&#34;目标&#34;,因为 从这个特殊的初始状态来看,它真的无法实现。