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;
}
}
所以这就是我最终解决了我的问题。当我研究这个问题时,我发现当我比较检查的元素是否在集合中时,它实际上比较了地址值而不是对象需要,这就是为什么我无法摆脱无限循环,因为每次生成一个新地址。为了不使用集合比较对象,我创建了一组字符串,比较存储为字符串的对象的配置然后把它放进去。感谢很多让我找到问题的人。真的!
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;
}
}
答案 0 :(得分:0)
在评论中指出了使用散列数据结构而没有实现与hashCode()
一致的equals()
的问题,因此这里建议您可以将hashCode()
用作@Override
public int hashCode() {
int hashCode = 0;
for(int i = 0; i < square.size; i++) {
hashcode += (square[i] << (3 + i % 2)*i);
}
}
:将电路板的单元格视为从左上角到右下角0 <= i <= 8的数字。
int
你最终会得到一个有点粗暴的equals()
,但仍然理所当然地来自与你的关注相关的董事会状态,并且肯定与equals()
一致,检查是否所有被比较的两块板的单元保持相同的值。如果您确实实施了hashCode()
和A.equals(B) -> A.hashCode() == B.hashCode()
,请务必执行此操作,这大致意味着
->
其中{{1}}是逻辑含义。