问题
Hi I'm using java to create a Solver program that uses the assistance of HeapMinPQ and nodes in order to solve any board based on the "8 puzzle" format. I've already created by "Board" data type which uses a two-dimensional array to account for the tiles (and "0" is the blank space). Within my SearchNodes, I have a priority Integer that accounts for the "Manhattan" values (and I'm sure that method works fine). The problem is that I've been trying to make progress, and although my program compiles, it simply gets stuck running without giving the appropriate output (the minimum number of moves required). I guess I'm having difficulty wrapping my head around all of this but this is my code to solve so far...
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;
}
And this is my "twin" method from the "board" data type.
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);
}
There must be a deep miscalculation that I'm making here and I'm pretty sure it starts at the solve(heap, twinHeap); method within the public Solver(Board initial) method. Any help would be greatly appreciated.
回答1:
here are some tricks to solve 8-puzzle problem:
For Board class:
when implementing Board class, it's better to use two integer variables (eg. rowIndex, colIndex) to track where the blank(number 0) is. Using self-defined Position class may lead to failure of passing the memory test if you are doing so as an assignment from coursera.
For generating a twin board, pay attention not to swap a number with blank tile whose number is 0. for generating a randomized twin, it's better first to generate two random values range from [0, n*n). then transfer them to row and col index.
When generating neighbors of a board, don't forget to update the blank tile position index.
For Solver class:
a new private inner class describing a game node is recommended. In this class, we can record the board, moves, and previous node. and update the Hamming and Manhattan methods which will be used in a Priority Queue to Deque an expected node.
To avoid going into a long-time loop, before inserting a node to a Priority Queue, Do check whether it has already been in the Queue.
Here are some useful explanation and suggestions from coursera: http://coursera.cs.princeton.edu/algs4/checklists/8puzzle.html
My code is here: My 8-puzzle code not timing optimized for Solver.
来源:https://stackoverflow.com/questions/31106659/using-a-algorithm-to-solve-8-puzzle-boards-board-data-type-works-fine