DFS益智游戏求解器(java)

DFS益智游戏求解器(java),java,depth-first-search,Java,Depth First Search,我正在与DFS solver合作进行8字谜游戏。这段代码打印树中的所有子项,直到正确的状态,但我只想打印正确的解决方案 我的输出: 120 345 678 125 340 678 102 345 678 125 348 670 125 304 678 142 305 678 012 345 678 预期产出: 120 345 678 102 345 678 012 345 678 代码: 公共类难题{ public static LinkedHashSet OPEN

我正在与DFS solver合作进行8字谜游戏。这段代码打印树中的所有子项,直到正确的状态,但我只想打印正确的解决方案

我的输出:

120
345
678

125
340
678

102
345
678

125
348
670

125
304
678

142
305
678

012
345
678
预期产出:

120 
345
678

102 
345 
678

012 
345 
678
代码:

公共类难题{
public static LinkedHashSet OPEN=新建LinkedHashSet();
public static HashSet CLOSED=new HashSet();
公共静态布尔状态=false;
公共静态void main(字符串参数[]){
int statesVisited=0;
字符串start=“120345678”;
字符串目标=“012345678”;
字符串X=“”;
字符串temp=“”;
打开。添加(开始);
while(OPEN.isEmpty()==false&&STATE==false){
X=OPEN.iterator().next();
打开。移除(X);
印刷品(X);
int pos=X.indexOf('0');//获取零或空空间的位置
如果(X等于(目标)){
System.out.println(“成功”);
状态=真;
}否则{
//生子
已结束。添加(X);
温度=上升(X,位置);
如果(!(温度等于(“-1”))
打开。添加(临时);
温度=下降(X,位置);
如果(!(温度等于(“-1”))
打开。添加(临时);
温度=左侧(X,位置);
如果(!(温度等于(“-1”))
打开。添加(临时);
温度=右侧(X,位置);
如果(!(温度等于(“-1”))
打开。添加(临时);
}
}
}
/*
*向上移动
*/
公共静态字符串向上(字符串s,int p){
字符串str=s;
如果(!(p<3)){
chara=str.charAt(p-3);
字符串newS=str.substring(0,p)+a+str.substring(p+1);
str=newS.substring(0,(p-3))+'0'+newS.substring(p-2);
}
//如果X的子对象处于打开或关闭状态,则消除其子对象
如果(!OPEN.contains(str)&&CLOSED.contains(str)==false)
返回str;
其他的
返回“-1”;
}
/*
*向下移动
*/
公共静态字符串关闭(字符串s,int p){
字符串str=s;
如果(!(p>5)){
字符a=str.charAt(p+3);
字符串newS=str.substring(0,p)+a+str.substring(p+1);
str=newS.substring(0,(p+3))+'0'+newS.substring(p+4);
}
//如果X的子对象处于打开或关闭状态,则消除其子对象
如果(!OPEN.contains(str)&&CLOSED.contains(str)==false)
返回str;
其他的
返回“-1”;
}
/*
*左移
*/
左公共静态字符串(字符串s,int p){
字符串str=s;
如果(p!=0&&p!=3&&p!=7){
字符a=str.charAt(p-1);
字符串newS=str.substring(0,p)+a+str.substring(p+1);
str=newS.substring(0,(p-1))+'0'+newS.substring(p);
}
//如果X的子对象处于打开或关闭状态,则消除其子对象
如果(!OPEN.contains(str)&&CLOSED.contains(str)==false)
返回str;
其他的
返回“-1”;
}
/*
*运动权
*/
公共静态字符串权限(字符串s,int p){
字符串str=s;
如果(p!=2&&p!=5&&p!=8){
字符a=str.charAt(p+1);
字符串newS=str.substring(0,p)+a+str.substring(p+1);
str=newS.substring(0,(p+1))+'0'+newS.substring(p+2);
}
//如果X的子对象处于打开或关闭状态,则消除其子对象
如果(!OPEN.contains(str)&&CLOSED.contains(str)==false)
返回str;
其他的
返回“-1”;
}
公共静态无效打印(字符串s){
System.out.println(s.substring(0,3));
System.out.println(s.substring(3,6));
System.out.println(s.substring(6,9));
System.out.println();
}
}

DFS返回它找到的第一条路径。要获得最短路径,请使用BFS。
你可以用地图

private static Map<String, List<String>> paths = new HashMap<>();
private static Map path=new HashMap();
要将每个节点(状态)映射到指向它的路径,请执行以下操作:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

public class puzzle {

    private static LinkedHashSet<String> OPEN = new LinkedHashSet<>();
    private static HashSet<String> CLOSED = new HashSet<>();
    private static Map<String, List<String>> paths = new HashMap<>();
    public static boolean STATE = false;


    public static void main(String args[]) {

        String start = "120345678";
        String goal =  "012345678";
        String X = "";
        String temp = "";
        OPEN.add(start);
        paths.put(start, Arrays.asList(start));

        while (OPEN.isEmpty() == false && STATE == false) {
            X = OPEN.iterator().next();
            OPEN.remove(X);
            print(X);


            int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
            if (X.equals(goal)) {
                System.out.println("SUCCESS" +"\n" + paths.get(X));
                STATE = true;
            } else {
                // generate children
                CLOSED.add(X);

                temp = up(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                temp = down(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                    temp = left(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                temp = right(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
            }
        }
    }

    static void updatePaths(String s, List<String> path){

        if(paths.containsKey(s)) return;
        List<String> newPath = new ArrayList<>(path);
        newPath.add(s);
        paths.put(s, newPath);
    }

    /*
     * MOVEMENT UP
     */
    public static String up(String s, int p) {
        String str = s;
        if (!(p < 3)) {
            char a = str.charAt(p - 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p - 3) + '0' + newS.substring(p - 2);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT DOWN
     */
    public static String down(String s, int p) {
        String str = s;
        if (!(p > 5)) {
            char a = str.charAt(p + 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p + 3) + '0' + newS.substring(p + 4);
        }

        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT LEFT
     */
    public static String left(String s, int p) {
        String str = s;
        if (p != 0 && p != 3 && p != 7) {
            char a = str.charAt(p - 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p - 1) + '0' + newS.substring(p);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT RIGHT
     */
    public static String right(String s, int p) {
        String str = s;
        if (p != 2 && p != 5 && p != 8) {
            char a = str.charAt(p + 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p + 1) + '0' + newS.substring(p + 2);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    public static void print(String s) {
       System.out.println(s.substring(0, 3));
       System.out.println(s.substring(3, 6));
       System.out.println(s.substring(6, 9));
       System.out.println();
    }
}
import java.util.ArrayList;
导入java.util.array;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.LinkedHashSet;
导入java.util.List;
导入java.util.Map;
公共类难题{
私有静态LinkedHashSet OPEN=新LinkedHashSet();
私有静态HashSet CLOSED=新HashSet();
私有静态映射路径=new HashMap();
公共静态布尔状态=false;
公共静态void main(字符串参数[]){
字符串start=“120345678”;
字符串目标=“012345678”;
字符串X=“”;
字符串temp=“”;
打开。添加(开始);
path.put(start,Arrays.asList(start));
while(OPEN.isEmpty()==false&&STATE==false){
X=OPEN.iterator().next();
打开。移除(X);
印刷品(X);
int pos=X.indexOf('0');//获取零或空空间的位置
如果(X等于(目标)){
System.out.println(“SUCCESS”+“\n”+path.get(X));
状态=真;
}否则{
//生子
已结束。添加(X);
温度=上升(X,位置);
如果(!temp.等于(“-1”)){
打开。添加(临时);
updatePath(temp,path.get(X));
}
温度=下降(X,位置);
如果(!temp.等于(“-1”)){
打开。添加(临时);
updatePath(temp,path.get(X));
}
温度=左侧(X,位置);
如果(!temp.等于(“-1”)){
打开。添加(临时);
updatePath(temp,path.get(X));
}
温度=右侧(X,位置);
如果(!temp.等于(“-1”)){
打开。添加(临时);
updatePath(temp,path.get(X));
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

public class puzzle {

    private static LinkedHashSet<String> OPEN = new LinkedHashSet<>();
    private static HashSet<String> CLOSED = new HashSet<>();
    private static Map<String, List<String>> paths = new HashMap<>();
    public static boolean STATE = false;


    public static void main(String args[]) {

        String start = "120345678";
        String goal =  "012345678";
        String X = "";
        String temp = "";
        OPEN.add(start);
        paths.put(start, Arrays.asList(start));

        while (OPEN.isEmpty() == false && STATE == false) {
            X = OPEN.iterator().next();
            OPEN.remove(X);
            print(X);


            int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
            if (X.equals(goal)) {
                System.out.println("SUCCESS" +"\n" + paths.get(X));
                STATE = true;
            } else {
                // generate children
                CLOSED.add(X);

                temp = up(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                temp = down(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                    temp = left(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
                temp = right(X, pos);
                if (!temp.equals("-1")) {
                    OPEN.add(temp);
                    updatePaths(temp, paths.get(X));
                }
            }
        }
    }

    static void updatePaths(String s, List<String> path){

        if(paths.containsKey(s)) return;
        List<String> newPath = new ArrayList<>(path);
        newPath.add(s);
        paths.put(s, newPath);
    }

    /*
     * MOVEMENT UP
     */
    public static String up(String s, int p) {
        String str = s;
        if (!(p < 3)) {
            char a = str.charAt(p - 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p - 3) + '0' + newS.substring(p - 2);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT DOWN
     */
    public static String down(String s, int p) {
        String str = s;
        if (!(p > 5)) {
            char a = str.charAt(p + 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p + 3) + '0' + newS.substring(p + 4);
        }

        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT LEFT
     */
    public static String left(String s, int p) {
        String str = s;
        if (p != 0 && p != 3 && p != 7) {
            char a = str.charAt(p - 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p - 1) + '0' + newS.substring(p);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    /*
     * MOVEMENT RIGHT
     */
    public static String right(String s, int p) {
        String str = s;
        if (p != 2 && p != 5 && p != 8) {
            char a = str.charAt(p + 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, p + 1) + '0' + newS.substring(p + 2);
        }
        // Eliminates child of X if its on OPEN or CLOSED
        if (!OPEN.contains(str) && CLOSED.contains(str) == false)
            return str;
        else
            return "-1";
    }

    public static void print(String s) {
       System.out.println(s.substring(0, 3));
       System.out.println(s.substring(3, 6));
       System.out.println(s.substring(6, 9));
       System.out.println();
    }
}
public class Puzzle {

    public static LinkedHashSet<Step> open = new LinkedHashSet<>();
    public static HashSet<Step> closed = new HashSet<>();
    public static boolean problemSolved = false;

    private static class Step {

        final String data;

        Step previous = null;

        Step(String data) {
            this.data = data;
        }

        Step(Step previous, String data) {
            this.previous = previous;
            this.data = data;
        }

        public String getData() {
            return data;
        }

        public Step getPrevious() {
            return previous;
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append(data.substring(0, 3))
                    .append("\r\n")
                    .append(data.substring(3, 6))
                    .append("\r\n")
                    .append(data.substring(6, 9))
                    .toString();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof Step)) {
                return false;
            }
            if (obj == this) {
                return true;
            }
            return this.getData().equals(((Step) obj).getData());
        }

        @Override
        public int hashCode() {
            return this.getData().hashCode();
        }
    }

    public static void main(String args[]) {
        int statesVisited = 0;

        Step startStep = new Step("120345678");
        Step goalStep = new Step("012345678");
        Step currentStep;

        open.add(startStep);

        while (!open.isEmpty() && !problemSolved) {
            currentStep = open.iterator().next();
            open.remove(currentStep);
            // print(currentStep);

            if (currentStep.equals(goalStep)) {
                System.out.println("SUCCESS PATH: \r\n");
                printSuccessPath(
                        getSuccessPathFromFinishStep(currentStep) // here currentStep is finish step
                );
                problemSolved = true;
            } else {
                // generate children
                closed.add(currentStep);

                Step nextStep = up(currentStep);
                if (nextStep != null) {
                    open.add(nextStep);
                }

                nextStep = down(currentStep);
                if (nextStep != null) {
                    open.add(nextStep);
                }

                nextStep = left(currentStep);
                if (nextStep != null) {
                    open.add(nextStep);
                }

                nextStep = right(currentStep);
                if (nextStep != null) {
                    open.add(nextStep);
                }
            }

        }
    }

    /*
     * MOVEMENT UP
     */
    public static Step up(Step step) {
        int p = step.getData().indexOf('0');
        String str = step.getData();
        if (!(p < 3)) {
            char a = str.charAt(p - 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);
        }
        Step nexStep = new Step(step, str); // Creates new step with step as previous one
        // Eliminates child of X if its on open or closed
        if (!open.contains(nexStep) && !closed.contains(nexStep))
            return nexStep;
        else
            return null;
    }

    /*
     * MOVEMENT DOWN
     */
    public static Step down(Step step) {
        int p = step.getData().indexOf('0');
        String str = step.getData();
        if (!(p > 5)) {
            char a = str.charAt(p + 3);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);
        }
        Step nexStep = new Step(step, str); // Creates new step with step as previous one
        // Eliminates child of X if its on open or closed
        if (!open.contains(nexStep) && !closed.contains(nexStep))
            return nexStep;
        else
            return null;
    }

    /*
     * MOVEMENT LEFT
     */
    public static Step left(Step step) {
        int p = step.getData().indexOf('0');
        String str = step.getData();
        if (p != 0 && p != 3 && p != 7) {
            char a = str.charAt(p - 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);
        }
        Step nexStep = new Step(step, str); // Creates new step with step as previous one
        // Eliminates child of X if its on open or closed
        if (!open.contains(nexStep) && !closed.contains(nexStep))
            return nexStep;
        else
            return null;
    }

    /*
     * MOVEMENT RIGHT
     */
    public static Step right(Step step) {
        int p = step.getData().indexOf('0');
        String str = step.getData();
        if (p != 2 && p != 5 && p != 8) {
            char a = str.charAt(p + 1);
            String newS = str.substring(0, p) + a + str.substring(p + 1);
            str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);
        }
        Step nexStep = new Step(step, str); // Creates new step with step as previous one
        // Eliminates child of X if its on open or closed
        if (!open.contains(nexStep) && !closed.contains(nexStep))
            return nexStep;
        else
            return null;
    }

    private static void print(Step s) {
        System.out.println(s);
        System.out.println();
    }

    private static void printSuccessPath(List<Step> successPath) {
        for (Step step : successPath) {
            print(step);
        }
    }

    private static List<Step> getSuccessPathFromFinishStep(Step finishStep) {
        LinkedList<Step> successPath = new LinkedList<>();

        Step step = finishStep;
        while (step != null) {
            successPath.addFirst(step);
            step = step.getPrevious();
        }

        return successPath;
    }
}
SUCCESS PATH: 

120
345
678

102
345
678

012
345
678
package basic;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;

public class Puzzle {

    private static class Node {
        private final Node previous;
        private final String data;

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((data == null) ? 0 : data.hashCode());
            return result;
        }

        public Node getPrevious() {
            return previous;
        }

        public String getData() {
            return data;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Node other = (Node) obj;
            if (data == null) {
                if (other.data != null)
                    return false;
            } else if (!data.equals(other.data))
                return false;
            return true;
        }

        public Node(String data) {
            this.data = data;
            this.previous = null;
        }

        public Node(String data, Node previous) {
            this.data = data;
            this.previous = previous;
        }
    }

    public static void main(String args[]) {
        Queue<Node> open = new LinkedList<>();
        Set<Node> closed = new HashSet<>();
        Node start = new Node("120345678");
        Node goal = new Node("012345678");

        open.add(start);
        boolean solving = true;
        while (!open.isEmpty() && solving) {
            Node current = open.poll();
            int pos = current.getData().indexOf('0');
            if (!closed.contains(current)) {
                if (current.equals(goal)) {
                    printPath(current);
                    System.out.println("SUCCESS");
                    solving = false;
                } else {
                    // generate children
                    up(current, pos, open, closed);
                    down(current, pos, open, closed);
                    left(current, pos, open, closed);
                    right(current, pos, open, closed);
                    closed.add(current);
                }
            }
        }
    }

    /*
     * MOVEMENT UP
     */
    private static void up(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
        if (zeroPosition >= 3) {
            char substitutedChar = current.getData().charAt(zeroPosition - 3);
            open.add(new Node(current.getData().substring(0, zeroPosition - 3) + '0'
                    + current.getData().substring(zeroPosition - 2, zeroPosition) + substitutedChar
                    + current.getData().substring(zeroPosition + 1), current));
        }
    }

    /*
     * MOVEMENT DOWN
     */
    private static void down(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
        if (zeroPosition <= 5) {
            char substitutedChar = current.getData().charAt(zeroPosition + 3);
            open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar
                    + current.getData().substring(zeroPosition + 1, zeroPosition + 3) + '0'
                    + current.getData().substring(zeroPosition + 4), current));
        }
    }

    /*
     * MOVEMENT LEFT
     */
    private static void left(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
        if (zeroPosition % 3 != 0) {
            char substitutedChar = current.getData().charAt(zeroPosition - 1);
            open.add(new Node(current.getData().substring(0, zeroPosition - 1) + '0' + substitutedChar
                    + current.getData().substring(zeroPosition + 1), current));
        }
    }

    /*
     * MOVEMENT RIGHT
     */
    private static void right(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
        if (zeroPosition % 3 != 2) {
            char substitutedChar = current.getData().charAt(zeroPosition - 1);
            open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar + '0'
                    + current.getData().substring(zeroPosition + 2), current));
        }
    }

    private static void printPath(Node current) {
        Stack<String> stack = new Stack<>();
        for (; current != null; current = current.getPrevious()) {
            stack.push(current.getData());
        }
        while (!stack.isEmpty()) {
            print(stack.pop());
        }
    }

    private static void print(String s) {
        System.out.println(s.substring(0, 3));
        System.out.println(s.substring(3, 6));
        System.out.println(s.substring(6, 9));
        System.out.println();

    }
}
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;

public class Puzzle {

    private static class Node {
        private final Node previous;
        private final char[][] data;

        public Node getPrevious() {
            return previous;
        }

        public char[][] getData() {
            return data;
        }

        public int getZeroX() {
            return zeroX;
        }

        public int getZeroY() {
            return zeroY;
        }

        private final int zeroX;

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + Arrays.deepHashCode(data);
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Node other = (Node) obj;
            if (!Arrays.deepEquals(data, other.data))
                return false;
            return true;
        }

        private final int zeroY;

        public Node(Node previous, char[][] data, int zeroX, int zeroY) {
            super();
            this.previous = previous;
            this.data = data;
            this.zeroX = zeroX;
            this.zeroY = zeroY;
        }
    }

    public static void main(String args[]) {
        Queue<Node> open = new LinkedList<>(); //Stack<Node> open = new Stack<>();
        Set<Node> closed = new HashSet<>();
        Node start = new Node(null, new char[][] { { '1', '2', '0' }, { '3', '4', '5' }, { '6', '7', '8' } }, 2, 0);
        Node goal = new Node(null, new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { '6', '7', '8' } }, 0, 0);

        open.add(start); //open.push(start);
        boolean solving = true;
        while (!open.isEmpty() && solving) {
            Node current = open.poll(); //open.pop();
            if (!closed.contains(current)) {
                if (current.equals(goal)) {
                    printPath(current);
                    System.out.println("SUCCESS");
                    solving = false;
                } else {
                    // generate children
                    up(current, open, closed);
                    down(current, open, closed);
                    left(current, open, closed);
                    right(current, open, closed);
                    closed.add(current);
                }
            }
        }
    }

    /*
     * MOVEMENT UP
     */
    private static void up(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
        if (current.getZeroY() > 0) {
            char[][] chars = copy(current.getData());
            chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() - 1][current.getZeroX()];
            chars[current.getZeroY() - 1][current.getZeroX()] = '0';
            open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() - 1));
        }
    }

    /*
     * MOVEMENT DOWN
     */
    private static void down(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
        if (current.getZeroY() < 2) {
            char[][] chars = copy(current.getData());
            chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() + 1][current.getZeroX()];
            chars[current.getZeroY() + 1][current.getZeroX()] = '0';
            open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() + 1));
        }
    }

    /*
     * MOVEMENT LEFT
     */
    private static void left(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
        if (current.getZeroX() > 0) {
            char[][] chars = copy(current.getData());
            chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() - 1];
            chars[current.getZeroY()][current.getZeroX() - 1] = '0';
            open.add/*push*/(new Node(current, chars, current.getZeroX() - 1, current.getZeroY()));
        }
    }

    /*
     * MOVEMENT RIGHT
     */
    private static void right(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
        if (current.getZeroX() < 2) {
            char[][] chars = copy(current.getData());
            chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() + 1];
            chars[current.getZeroY()][current.getZeroX() + 1] = '0';
            open.add/*push*/(new Node(current, chars, current.getZeroX() + 1, current.getZeroY()));
        }
    }

    private static char[][] copy(char[][] data) {
        char[][] newData = new char[3][3];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                newData[i][j] = data[i][j];
            }
        }
        return newData;
    }

    private static void printPath(Node current) {
        Stack<char[][]> stack = new Stack<>();
        for (; current != null; current = current.getPrevious()) {
            stack.push(current.getData());
        }
        while (!stack.isEmpty()) {
            print(stack.pop());
        }
    }

    private static void print(char[][] chars) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(chars[i][j]);
            }
            System.out.println();
        }
        System.out.println();

    }
}