使用A *算法解决8-puzzle板(Board数据类型工作正常)

时间:2015-06-29 01:45:22

标签: java algorithm 8-puzzle

您好我正在使用java创建一个Solver程序,该程序使用HeapMinPQ和节点的帮助,以便根据“8拼图”格式解决任何板。我已经通过“Board”数据类型创建了它,它使用二维数组来计算tile(而“0”是空格)。在我的SearchNodes中,我有一个优先级整数,用于解释“曼哈顿”值(我确信该方法可以正常工作)。问题是我一直在努力取得进步,虽然我的程序编译,但它只是在没有给出适当的输出(所需的最小移动次数)的情况下卡住了。我想我很难绕过这一切,但这是我到目前为止要解决的代码......

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

这是“板”数据类型的“双胞胎”方法。

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; 
 }

我必须在这里做一个深度错误的计算,我很确定它是从解决开始的(heap,twinHeap);公共求解器(Board initial)方法中的方法。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

这里有一些解决8-puzzle问题的技巧:

Board 类:

  1. 在实现Board类时,最好使用两个整数变量(例如rowIndex,colIndex)来跟踪空白(数字0)的位置。使用自定义的Position类可能会导致无法通过内存测试,如果你这样做是为了从课程中分配。

  2. 为了生成双板,注意不要用数字为0的空白区块交换数字来生成随机双胞胎,最好先生成两个随机值,范围为[0, N * N)。然后将它们转移到row和col索引。

  3. 生成电路板的邻居时,不要忘记更新空白磁贴位置索引。

  4. 对于解算器类:

    1. 建议使用描述游戏节点的新私有内部类。在这个类中,我们可以记录板,移动和前一个节点。并更新将在优先级队列中使用的汉明和曼哈顿方法,以取消预期的节点。

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

    3. 以下是一些有用的解释和建议: http://coursera.cs.princeton.edu/algs4/checklists/8puzzle.html

    4. 我的代码在这里: My 8-puzzle code not timing optimized for Solver.