我正在创建一个深度优先搜索算法,它最终能够解决一个简单的8个谜题。我能够读入文件和目标状态并相应地设置这些变量。
我收到的主要问题是,当我让当前节点的孩子被评估时,我在我的8个谜题中得到2个“空”值,而且我也得到一个超出范围的索引异常。
为了获得给定父级的子节点,我首先必须进行有效移动,然后更新子节点的状态以反映有效移动的结果。
为了执行移动,我检查它是否可行(如果我向左移动它仍然在拼图的范围内),请参阅已发布的代码。
正确打印预期结果时,它可以正常运行前两次,左右移动。
下面是我当前代码执行的输出,你可以看到它正确地向左和向下移动,然后它开始遇到错误。
Start state:
120
345
678
after moving left
102
345
678
Parent: [[C@1b845568
after moving down
125
340
678
Parent: [[C@d032cf5
after moving left
102
340
678
Parent: [[C@d032cf5
after moving down
125
348
670
Parent:
125
340
678
after moving up
125
348
670
Parent: [[C@4b7c8f7f
after moving left
125
304
670
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at dcs.aber.ac.uk.puzzle.PuzzleBoard.swapValues(PuzzleBoard.java:193)
at dcs.aber.ac.uk.puzzle.PuzzleBoard.moveUp(PuzzleBoard.java:142)
at dcs.aber.ac.uk.puzzle.DFSSolver.addChildren(DFSSolver.java:155)
at dcs.aber.ac.uk.puzzle.DFSSolver.search(DFSSolver.java:85)
at dcs.aber.ac.uk.puzzle.DFSSolver.<init>(DFSSolver.java:27)
at dcs.aber.ac.uk.puzzle.Driver.main(Driver.java:86)
如您所见,在前两个之后,其余打印状态不正确。我将发布我的代码,以显示我如何处理电路板的交换和更新,以确定您是否可以识别复杂性出现的位置。
public class Node {
private Node parent;
private char[][] state = new char[3][3];
private double cost;
private double heurCost;
private double funcCost;
private int depth;
public Node() {
parent = null;
}
public Node(Node parent) {
this.parent = parent;
for(int i = 0; i < 3; i++){
for(int j = 0; j< 3; j++){
state[i][j] = parent.getState()[i][j];
}
}
}
public void setParent(Node parent) {
this.parent = parent;
}
public char[][] getState() {
return state;
}
public char[][] copyState(){
char[][] a = new char[3][3];
for(int i = 0; i < 3; i++){
for(int j = 0; j< 3; j++){
a[i][j] = state[i][j];
}
}
return a;
}
}
public class PuzzleBoard {
private char[][] goalState;
private char[][] currentBoard;
private int emptyRow, emptyCol;
private int outOfPlace;
public PuzzleBoard(char[][] currentState, char[][] goal ){
this.setCurrentState(currentState);
this.setGoalState(goal);
trackEmptySqaure();
}
public void setGoalState(char[][] goalState){
this.goalState = goalState;
}
public void setCurrentState(char[][] currentState){
this.currentBoard = currentState;
}
public char[][] getCurrentBoard() {
return currentBoard;
}
public boolean checkIsGoal(char[][] board){
for(int i = 0; i < 9; i ++){
for(int j = 0; j < 3; j ++){
if(!(goalState[i][j] != (board[i][j]))){
return false;
}
}
}
return true;
}
public void trackEmptySqaure() {
for(int i = 0; i < 3; i ++){
for (int j = 0; j < 3; j ++){
if(currentBoard[i][j] == '0'){
emptyCol = j;
emptyRow = i;
}
}
}
}
public int getemptyRow() {
return emptyRow;
}
public int getemptyCol() {
return emptyCol;
}
public Node moveLeft(Node parent){
currentBoard = parent.copyState();
Node result = new Node(parent);
/* check you can move 'empty' left one space*/
if(getemptyCol() > 0){
swapValues(result.getState(),emptyRow, emptyCol, 1);
return result;
}
return null;
}
public Node moveDown(Node parent){
currentBoard = parent.copyState();
Node result = new Node(parent);
/* check you can move 'empty' down one space*/
if(getemptyRow() < 2){
swapValues(result.getState(),emptyRow, emptyCol,2);
return result;
}
return null;
}
public Node moveUp(Node parent){
currentBoard = parent.getState();
Node result = new Node(parent);
/* check you can move 'empty' up one space*/
if(getemptyRow() > 0){
swapValues(result.getState(),emptyRow, emptyCol,2);
return result;
}
return null;
}
public Node moveRight(Node parent){
currentBoard = parent.getState();
Node result = new Node(parent);
/* check you can move 'empty' right one space*/
if(getemptyCol() < 2){
swapValues(result.getState(),emptyRow, emptyCol,2);
return result;
}
return null;
}
public void swapValues (char[][] c,int x, int y, int method){
char empty = '0';
char swapValue = '0'; // should never be kept as 0
if(method == 1){ // left
swapValue= c[emptyRow][emptyCol -1];
c[emptyRow][emptyCol] = swapValue;
c[emptyRow][emptyCol -1] = empty;
trackEmptySqaure();
}
else if(method == 2){ // down
swapValue = c[emptyRow + 1][emptyCol];
c[emptyRow][emptyCol] = swapValue;
c[emptyRow + 1][emptyCol] = empty;
trackEmptySqaure();
}
else if(method == 3){ // up
swapValue = c[emptyRow -1][emptyCol];
c[emptyRow][emptyCol] = swapValue;
c[emptyRow -1][emptyCol] = empty;
trackEmptySqaure();
}
else if(method == 4){// right
swapValue = c[emptyRow][emptyCol + 1];
c[emptyRow][emptyCol] = swapValue;
c[emptyRow ][emptyCol + 1] = empty;
trackEmptySqaure();
}
}
public class DFSSolver {
private ArrayList<Node> closed = new ArrayList<Node>();
private Stack<Node> open = new Stack<Node>();
private PuzzleBoard pb;
private boolean solved;
private int numberOfSteps;
public DFSSolver(PuzzleBoard puzzle) {
pb = puzzle;
numberOfSteps = 0;
solved = false;
Node root = new Node();
root.setState(pb.getCurrentBoard());
addToOpen(root);
checkIfSolved(root);
search();
}
public boolean inOpenList(Node n){
for(Node node: open){
if(node.equals(n)){
return true;
}
}
return false;
}
public boolean inClosedList(Node n){
for(Node node: closed){
if(node.equals(n)){
return true;
}
}
return false;
}
public void addToOpen(Node n){
open.push(n);
}
public void addToClosed(Node n){
closed.add(n);
}
public Node popOpen(){
return open.pop();
}
public void removeFromClosed(Node n){
closed.remove(n);
}
public void search(){
while(!solved){
Node current = popOpen();
if(current != null){
if(!(inClosedList(current))){ // is it previously explored?
checkIfSolved(current);
addChildren(current);
numberOfSteps++;
}
addToClosed(current);
}
}
System.out.println("No of steps: " + numberOfSteps);
}
public void checkIfSolved(Node curr) {
char[][] goal = pb.getGoal();
char[][] current = curr.getState();
for(int i = 0; i < 3; i ++){
for(int j = 0; j < 3; j ++){
char c = current[i][j];
char x = goal[i][j];
if(c != x){
return;
}
}
}
solved = true;
}
public void addChildren(Node parent){
Node newNode = new Node(parent);
newNode = pb.moveLeft(parent);
if(newNode != null){
System.out.println("Parent: " + parent.getState().toString());
System.out.println("atfer moving left");
System.out.println(newNode.toString());
addToOpen(newNode);
}
newNode = pb.moveDown(parent);
if(newNode != null){
System.out.println("Parent: " + parent.getState().toString());
System.out.println("atfer moving down");
System.out.println(newNode.toString());
addToOpen(newNode);
}
newNode = pb.moveRight(parent);
if(newNode != null){
System.out.println("Parent: " + parent.getState().toString());
System.out.println("atfer moving right");
System.out.println(newNode.toString());
addToOpen(newNode);
}
newNode = pb.moveUp(parent);
if(newNode != null){
System.out.println("Parent:\n " + parent.toString());
System.out.println("atfer moving up");
System.out.println(newNode.toString());
addToOpen(newNode);
}
}
答案 0 :(得分:0)
在move up
方法中,您可以像这样调用swap values
:
swapValues(result.getState(),emptyRow, emptyCol,2);
但我猜它应该是:
swapValues(result.getState(),emptyRow, emptyCol,3);
你也想打电话:
swapValues(result.getState(),emptyRow, emptyCol,4);
moveRight
方法中的
答案 1 :(得分:0)
我相信您报告的另一个问题是因为代码关于空方块所在位置的概念并不总是与您当前正在处理的节点相匹配。你在每次交换后调用trackEmptySquare,但更好的地方是在 moveLeft,moveRight等之前在调用它,这样它就会匹配你当前正在查看的节点。
但更好的方法是摆脱跟踪空行和列的变量。每个节点都有自己的空方块。您可以将empty-row / empty-col变量移动到Node类中,并在每次Node状态更改时更新它们。或者根本不添加它们,只需添加一个搜索Node.state
空方块的方法。