这个BFS的目标是找到一个3x2益智游戏的解决方案(0是空格,你只能将棋子移动到那个空间)
启动:
目标:
问题是我的队列在找到解决方案之前变空了,这怎么可能?搜索树中的一个路径必须在此处返回解决方案。如果我能澄清任何事情,请告诉我。
节点类(代表游戏状态):
mport java.lang.reflect.Array;
import java.util.*;
public class Node {
public int[] state = new int[6];
private 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(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(right());
children.add(down());
break;
case 1:
children.add(down());
children.add(left());
children.add(right());
break;
case 2:
children.add(down());
children.add(left());
break;
case 3:
children.add(up());
children.add(right());
break;
case 4:
children.add(up());
children.add(left());
children.add(right());
break;
case 5:
children.add(up());
children.add(left());
break;
}
return children;
}
public int[] getState(){
return this.state;
}
public int getBlankIndex() {
for (int i = 0; i < state.length; i++)
if (state[i] == 0) return i;
return -1;
}
public Node up(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex - 3];
newer[blankIndex] = temp;
newer[blankIndex - 3] = 0;
return new Node(newer, this);
}
public Node down(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex + 3];
newer[blankIndex] = temp;
newer[blankIndex + 3] = 0;
return new Node(newer, this);
}
public Node left(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex - 1];
newer[blankIndex] = temp;
newer[blankIndex - 1] = 0;
return new Node(newer, this);
}
public Node right(){
int[] newer = state.clone();
int blankIndex = getBlankIndex();
int temp = newer[blankIndex + 1];
newer[blankIndex] = temp;
newer[blankIndex + 1] = 0;
return new Node(newer, this);
}
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){
if (object instanceof Node) {
Node node2 = (Node) object;
return (Arrays.equals(node2.getState(), this.getState()));
}
return false;
}
@Override
public int hashCode() {
return this.hashCode();
}
}
驱动程序类:
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 (!queue.isEmpty() && !current.isGoal()){
current = queue.remove();
for (Node child: current.getChildren()){
if (!explored.contains(child)) {
queue.add(child);
explored.add(current);
}
}
}
System.out.println("DONEDONEDONE");
current.printTrace();
}
}
答案 0 :(得分:1)
这是一个非常令人惊讶的问题!
我还没看过代码,看起来或多或少都没问题。 我将改为解决这个问题: 问题是我的队列在找到解决方案之前变空了 这怎么可能?
代码不是问题。 问题是你的谜题无法解决。
有趣的是
parity(permutation) * (-1)^{manhattanMetric(positionOfZeroTile)}
是在整个游戏中保留的不变量。
让我简单解释一下它的含义。 (它与此处的论点基本相同:https://en.wikipedia.org/wiki/15_puzzle)
排列的奇偶校验是(-1)^{numberOfTranspositions}
。
转置的数量基本上只是交换的数量
冒泡排序需要对序列进行排序。
零区块位置的曼哈顿度量是零区块的x坐标
添加了零区块的y坐标。
每次将磁贴交换为0时,置换的奇偶校验都会发生变化 标志。
同时,左上角和左上角之间的曼哈顿度量
零区块的位置改变+1或-1。在这两种情况下,
(-1)^{manhattanDist}
也会更改标志。
因此,奇偶校验和(-1)^{manhattanDist}
的乘积是常数。
如果你现在看看已解决的游戏
0 1 2
3 4 5
然后换位次数为0,奇偶校验为1,曼哈顿距离为0。 因此,不变量是(+1)。
但是,如果你看一下:
1 4 2
5 3 0
然后你可以计算出换位数是偶数(冒泡它!),
奇偶校验为(+1),曼哈顿距离为2 + 1 = 3,因此不均匀。
因此,不变量是(+1) * (-1)^3 = (-1)
。
但是(-1)不是(+1)。因此,无论如何,您的游戏原则上无法解决 你的BFS有多好。
另一种(更直观但不那么严谨)的方式可以快速看到你的谜题被打破了#34; 是在开头交换两个非零的瓷砖。
1 4 2
3 5
这几乎可以立即解决:
1 4 2 1 2 1 2
3 5 3 4 5 3 4 5
所以,如果你不想浪费任何时间寻找那些不存在的bug, 下次不要跳过小组理论讲座;)
答案 1 :(得分:0)
我能找到的一个错误是,如果它不包含child,你只会向探索列表中添加当前值。此外,您通过子项循环执行此操作,因此也可能是多次添加它。 (虽然这不应该影响你的结果)