简体   繁体   English

广度优先搜索算法陷入无限循环

[英]Breadth First Search algorithm gets stuck in infinite loop

I am trying to implement a Breadth First Search algorithm for 8puzzle. I am somehow not able to get in the `is(RequiredState(see))` condition where my search terminates. My program gets stuck in an infinite loop. I have put the repeating states in a state to prevent getting stuck in a loop, but somehow my program still gets stuck in a loop.

board.java

        public class board {
            public
                int[] square = new int[9];
            board()
            {
                for(int i=0;i<9;i++)
                {
                    square[i]=8-i;
                    square[8] = 0;


                }
            }
            int findBlankPos()
            {
                for(int i=0;i<square.length;i++)
                {
                    if(square[i]==0)
                    {
                        return i;
                    }
                }
                return 9;
            }
            static int size()
            {
                return 9;
            }
            void moveBlankUp(int blankpos)
            {
                square[blankpos] = square[blankpos-3];
                square[blankpos-3] = 0;
            }
            void moveBlankDown(int blankpos)
            {
                square[blankpos] = square[blankpos+3];
                square[blankpos+3] = 0;
            }
            void moveBlankRight(int blankpos)
            {
                square[blankpos] = square[blankpos+1];
                square[blankpos+1] = 0;
            }
            void moveBlankLeft(int blankpos)
            {
                square[blankpos] = square[blankpos-1];
                square[blankpos-1] = 0;
            }
            boolean canMoveUp(int blankpos)
            {
                if((blankpos==0)||(blankpos==1)||(blankpos==2))
                    return false;
                else
                    return true;
            }
            boolean canMoveDown(int blankpos)
            {
                if((blankpos==6)||(blankpos==7)||(blankpos==8))
                    return false;
                else
                    return true;
            }
            boolean canMoveRight(int blankpos)
            {
                if((blankpos==2)||(blankpos==5)||(blankpos==8))
                    return false;
                else
                    return true;
            }
            boolean canMoveLeft(int blankpos)
            {
                if((blankpos==0)||(blankpos==3)||(blankpos==6))
                    return false;
                else
                    return true;
            }
            void display()
            {
                for(int i=0;i<square.length;i++)
                {
                    if((i)%3==0)
                    {
                        System.out.println();
                    }
                    System.out.print(square[i] + " ");
                }
            }
            Integer getAt(int pos)
            {
                return square[pos];
            }
            void setAt(int pos,int value)
            {
                square[pos] = value;
            }
        }

puzzle.java

    import java.awt.List;
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Set;


    public class puzzle {
        public static void main(String[] args)
        {
            board b = new board();
            Set<board> set = new HashSet<board>();
            b.display();
            Queue<board> queue = new LinkedList<board>();
            queue.add(b);
            /*b.setAt(4,0);
            b.setAt(8,4);
            b.display();
            System.out.println();
            AddChildrentoQueue(queue,b);*/

            //System.out.println(queue.);
            int itr=0;
            while(!queue.isEmpty())
            {
                itr++;
                System.out.println(itr);
                board see = queue.peek();
                //System.out.println(count);
                if(!(set.contains(see)))
                {
                    set.add(see);
                    //see.display();
                    //System.out.println();
                    if(isRequiredState(see))
                    {
                        queue.peek().display();
                        System.out.println("End it with a Bang");
                        break;
                    }
                        AddChildrentoQueue(queue,queue.peek());
                        //System.out.println(queue.size());
                        if(itr==1)
                            break;

                }
                queue.remove();
            }
            //System.out.println(isRequiredState(b));

        }

        private static boolean isRequiredState(board peek) {
            // TODO Auto-generated method stub
            String state="";
            for(int i=0;i<peek.size();i++)
            {
                String temp = (String)peek.getAt(i).toString();
                //System.out.println(temp);
                state = state + temp;
            }
            //System.out.println(state);
            if(state.equals("123456780"))
            {
                return true;
            }
            return false;
        }

        private static void AddChildrentoQueue(Queue<board> queue, board b) {
            // TODO Auto-generated method stub
            board d;
            if(b.canMoveUp(b.findBlankPos()))
            {
                d = getClone(b);
                d.moveBlankUp(b.findBlankPos());
                d.display();
                System.out.println();
                queue.add(d);
            }
            if(b.canMoveDown(b.findBlankPos()))
            {
                d = getClone(b);
                d.moveBlankDown(b.findBlankPos());
                d.display();
                System.out.println();
                queue.add(d);
            }
            if(b.canMoveRight(b.findBlankPos()))
            {
                d = getClone(b);
                d.moveBlankRight(b.findBlankPos());
                d.display();
                System.out.println();
                queue.add(d);
            }
            if(b.canMoveLeft(b.findBlankPos()))
            {
                d = getClone(b);
                d.moveBlankLeft(b.findBlankPos());
                d.display();
                System.out.println();
                queue.add(d);
            }


        }
        static board getClone(board b)
        {
            board c = new board();
            for(int i=0;i<c.size();i++)
            {
                c.setAt(i,b.getAt(i));
            }
            return c;
        }


    }

So this is how i finally solved my problem .As i worked on the problem i found out that when i compared that whether the element checked is in the set or not,it actually compared the address values but not the objects as was required and that is why i was unable to come out of the infinite loop because every time a new address was generated.Hence instead of comparing the objects using a set,I created a set of strings that compared the configuration of the object stored as strings and put in a set.Thanks a lot for making me find the problem guyz..cheers!!! 因此,这就是我最终解决问题的方式。在研究该问题时,我发现,当我比较所检查的元素是否在集合中时,它实际上是比较地址值而不是所需的对象,并且这就是为什么我无法走出无限循环的原因,因为每次生成一个新地址。因此,我没有使用一组比较对象,而是创建了一组字符串,该字符串比较了存储为字符串并放入其中的对象的配置一组。非常感谢让我发现问题了。

import java.awt.List;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;


public class puzzle {
    public static void main(String[] args)
    {
        board b = new board();
        Set<String> set = new HashSet<String>();
        b.display();
        Queue<board> queue = new LinkedList<board>();
        queue.add(b);
        /*b.setAt(4,0);
        b.setAt(8,4);
        b.display();
        System.out.println();
        AddChildrentoQueue(queue,b);*/

        //System.out.println(queue.);
        //int itr=0;
        while(!queue.isEmpty())
        {
            //itr++;
            board see = queue.peek();
            String check = getSequence(queue.peek());
            //System.out.println(itr);
            //System.out.println(check);
            if(!(set.contains(check)))
            {
                set.add(check);
                //see.display();
                //System.out.println();
                if(isRequiredState(see))
                {
                    queue.peek().display();
                    System.out.println("End it with a Bang");
                    break;
                }
                    AddChildrentoQueue(queue,queue.peek());
                    //System.out.println(queue.size());
            }
            queue.remove();
        }
        //System.out.println(isRequiredState(b));

    }

    private static boolean isRequiredState(board peek) {
        // TODO Auto-generated method stub
        String state = getSequence(peek);
        //System.out.println(state);
        if(state.equals("123456780"))
        {
            return true;
        }
        return false;
    }


    private static String getSequence(board peek) {
        // TODO Auto-generated method stub
        String state="";
        for(int i=0;i<peek.size();i++)
        {
            String temp = (String)peek.getAt(i).toString();
            //System.out.println(temp);
            state = state + temp;
        }
        return state;
    }

    private static void AddChildrentoQueue(Queue<board> queue, board b) {
        // TODO Auto-generated method stub
        board d;
        if(b.canMoveUp(b.findBlankPos()))
        {
            d = getClone(b);
            d.moveBlankUp(b.findBlankPos());
            d.display();
            System.out.println();
            queue.add(d);
        }
        if(b.canMoveDown(b.findBlankPos()))
        {
            d = getClone(b);
            d.moveBlankDown(b.findBlankPos());
            d.display();
            System.out.println();
            queue.add(d);
        }
        if(b.canMoveRight(b.findBlankPos()))
        {
            d = getClone(b);
            d.moveBlankRight(b.findBlankPos());
            d.display();
            System.out.println();
            queue.add(d);
        }
        if(b.canMoveLeft(b.findBlankPos()))
        {
            d = getClone(b);
            d.moveBlankLeft(b.findBlankPos());
            d.display();
            System.out.println();
            queue.add(d);
        }


    }
    static board getClone(board b)
    {
        board c = new board();
        for(int i=0;i<c.size();i++)
        {
            c.setAt(i,b.getAt(i));
        }
        return c;
    }


}

The problem with using a hashing data structure without implementing a hashCode() that is consistent with equals() was pointed out in the comments, so here's a suggestion what you could use as a hashCode() : consider the cells of the board as number with 0 <= i <= 8 from top left to bottom right. 在注释中指出了使用散列数据结构而未实现与equals()一致的hashCode()的问题,因此,建议您可以将其用作hashCode() :将板的单元格视为数字从左上到右下的0 <= i <= 8。

@Override
public int hashCode() {
    int hashCode = 0;

    for(int i = 0; i < square.size; i++) {
        hashcode += (square[i] << (3 + i % 2)*i);
    }
}

You'll end up with an int that somewhat crudely, but still sensibly derives from the state of the board that is relevant to your concerns, and certainly consistent with an equals() that checks whether all cells of the two boards being compared hold the same value. 您最终得到的int可能有点粗略,但仍然明智地源自与您所关注的问题相关的董事会状态,并且肯定与equals()一致,该equals()检查所比较的两个董事会的所有单元格是否都持有相同的值。 Make sure that if you do implement equals() and hashCode() , you do it consistently, which roughly means 确保如果您确实实现equals()hashCode() ,则可以始终如一地进行操作,这大致意味着

A.equals(B) -> A.hashCode() == B.hashCode()

where -> is the logical implication. 其中->是逻辑含义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM