Java 使用*算法解决8个拼图板(板数据类型工作正常)

Java 使用*算法解决8个拼图板(板数据类型工作正常),java,algorithm,sliding-tile-puzzle,Java,Algorithm,Sliding Tile Puzzle,嗨,我正在使用java创建一个解算程序,该程序使用HeapMinPQ和节点的帮助来解决基于“8拼图”格式的任何电路板。我已经创建了“板”数据类型,它使用二维数组来解释瓦片(而“0”是空白区)。在我的SearchNodes中,我有一个优先级整数,它代表“Manhattan”值(我确信该方法工作正常)。问题是,我一直在努力取得进展,尽管我的程序可以编译,但它只是在没有给出适当的输出(所需的最少移动次数)的情况下停止运行。我想我很难理解这一切,但这是我目前要解决的代码 import java.util

嗨,我正在使用java创建一个解算程序,该程序使用HeapMinPQ和节点的帮助来解决基于“8拼图”格式的任何电路板。我已经创建了“板”数据类型,它使用二维数组来解释瓦片(而“0”是空白区)。在我的SearchNodes中,我有一个优先级整数,它代表“Manhattan”值(我确信该方法工作正常)。问题是,我一直在努力取得进展,尽管我的程序可以编译,但它只是在没有给出适当的输出(所需的最少移动次数)的情况下停止运行。我想我很难理解这一切,但这是我目前要解决的代码

import java.util.Comparator;
public class Solver {
private SearchNode result;

// Helper search node class.
private class SearchNode {
    SearchNode prev; 
    Board value; 
    int moves = 0; 
    int priority;


    public SearchNode(Board board, SearchNode previous) {
        super();
        this.value = board; 
        prev = previous; 
        if (null != previous) { 
            this.moves = previous.moves + 1; 
        } else { 
            this.moves = 0; 
        } 
         // priority = this.value.hamming() + moves; 
         priority = this.value.manhattan() + moves; 

    }
}

/**
 * Finds a solution to the initial board (using the A* algorithm).
 * @param initial initial board.
 */
public Solver(Board initial) {
    SearchNode root = new SearchNode(initial, null); 
    HeapMinPQ<SearchNode> heap = new HeapMinPQ<SearchNode>(new ManhattanOrder()); 
    heap.insert(root);


     Board twin = initial.twin();
     SearchNode twinRoot = new SearchNode(twin, null); 
     HeapMinPQ<SearchNode> twinHeap = new HeapMinPQ<SearchNode>(new ManhattanOrder()); 
     twinHeap.insert(twinRoot); 


     solve(heap, twinHeap);

}

private void solve(HeapMinPQ<SearchNode> heap, HeapMinPQ<SearchNode> twinHeap) { 
     while (!heap.isEmpty() && !twinHeap.isEmpty()) { 
         if (null != perform(heap)) { 
             return; 
         } 


         if (null != perform(twinHeap)) { 
             result = null; 
             return; 
         } 
     } 
 } 


 private SearchNode perform(HeapMinPQ<SearchNode> heap) { 
     SearchNode n = heap.delMin(); 
     if (n.value.isGoal()) { 
         result = n; 
         return result; 
     } 
     for (Board board : n.value.neighbors()) { 
         SearchNode x = new SearchNode(board, n); 
         if (null != n.prev && n.prev.value.equals(board)) { 
             // don't add neighbors that are same as previous board 
             continue; 
         } 
         heap.insert(x); 
     } 
     return null; 
 }
import java.util.Comparator;
公共类求解器{
私有搜索节点结果;
//助手搜索节点类。
私有类搜索节点{
SearchNode-prev;
董事会价值;
int=0;
int优先级;
公共SearchNode(Board Board,SearchNode previous){
超级();
这个值=电路板;
prev=先前的;
如果(null!=上一个){
this.moves=previous.moves+1;
}否则{
这个值=0;
} 
//优先级=this.value.hamming()+移动;
优先级=this.value.manhattan()+移动;
}
}
/**
*找到初始电路板的解决方案(使用a*算法)。
*@param初始板。
*/
公共解决方案(董事会首字母){
SearchNode root=新的SearchNode(初始值,null);
HeapMinPQ heap=newheapminpq(newmanhattanoder());
heap.insert(根);
Board twin=初始值.twin();
SearchNode twinRoot=新的SearchNode(twin,null);
HeapMinPQ twinHeap=newheapminpq(newmanhattanoder());
插入(twinRoot);
求解(堆、双堆);
}
私有void solve(HeapMinPQ heap,HeapMinPQ twinHeap){
而(!heap.isEmpty()&&!twinHeap.isEmpty()){
如果(null!=执行(堆)){
返回;
} 
如果(null!=执行(twinHeap)){
结果=空;
返回;
} 
} 
} 
私有搜索节点执行(HeapMinPQ堆){
SearchNode n=heap.delMin();
如果(n.value.isGoal()){
结果=n;
返回结果;
} 
对于(Board-Board:n.value.neights()){
SearchNode x=新的SearchNode(板,n);
如果(null!=n.prev&&n.prev.value.equals(board)){
//不要添加与前一块电路板相同的邻居
继续;
} 
heap.insert(x);
} 
返回null;
}
这是我从“board”数据类型得到的“twin”方法

public Board twin(){
     int dim = this.length; 
     int[][] copy = this.tiles; 
     if (this.length <= 1) 
         return new Board(copy); 
     // Find zero so that we don't exchange with the blank 
     // This looks like a O(dim^2) algorithm, but on average it should finish 
     // in O(1). 
     int row = 0; 
     int col = 0; 
     int value = 0; 
     int lastValue = tiles[0][0]; 
     zerosearch: for (row = 0; row < dim; row++) { 
         for (col = 0; col < dim; col++) { 
             value = tiles[row][col]; 
             // Check col>0 because swap must occur on same row 
             if (value != 0 && lastValue != 0 && col > 0) 
                 break zerosearch; 
             lastValue = value; 
         } 
     } 
     copy[row][col] = lastValue; 
     copy[row][col - 1] = value; 
     return new Board(copy); 


}
publicboard twin(){
int dim=此长度;
int[][]copy=this.tiles;

如果(this.length,以下是一些解决8字谜问题的技巧:

对于类:

  • 在实现Board类时,最好使用两个整型变量(例如rowIndex、colIndex)来跟踪空白(数字0)的位置。如果使用自定义的Position类作为coursera的作业,则可能导致无法通过内存测试

  • 对于生成双板,请注意不要将数字与数字为0的空白磁贴交换。对于生成随机双板,最好先生成两个范围为[0,n*n]的随机值,然后将它们转移到行和列索引

  • >P>当生成一个板的邻居时,不要忘记更新空白的瓦片位置索引。

    对于解算器类:

  • 建议使用一个新的私有内部类来描述游戏节点。在这个类中,我们可以记录棋盘、移动和以前的节点。并更新将在优先级队列中使用的Hamming和Manhattan方法来定义预期的节点

  • 为了避免进入长时间循环,在将节点插入优先级队列之前,请检查它是否已经在队列中

  • 以下是coursera提供的一些有用的解释和建议:

  • 我的代码在这里:


  • 你是否等了足够长的时间让你的程序给出答案?比如说5分钟,15分钟!?是的。什么都没发生。你试过调试代码吗?断点,条件断点可以帮你很多。