8拼图A*java实现
有人告诉我,以下8个谜题求解器的*实现是错误的,有人能告诉我哪里是错误的,以及如何纠正它吗 另外:这会在线程“main”java.lang.OutOfMemoryError:java堆空间中引发异常,即使构建进程堆大小设置为2048 下面是Solver.java8拼图A*java实现,java,shortest-path,a-star,sliding-tile-puzzle,Java,Shortest Path,A Star,Sliding Tile Puzzle,有人告诉我,以下8个谜题求解器的*实现是错误的,有人能告诉我哪里是错误的,以及如何纠正它吗 另外:这会在线程“main”java.lang.OutOfMemoryError:java堆空间中引发异常,即使构建进程堆大小设置为2048 下面是Solver.java import java.util.HashSet; import java.util.Set; import java.util.Stack; import java.util.PriorityQueue; public clas
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.PriorityQueue;
public class Solver {
private int moves = 0;
private SearchNode finalNode;
private Stack<Board> boards;
public Solver(Board initial) {
if (!initial.isSolvable()) throw new IllegalArgumentException("Unsolvable puzzle");
// this.initial = initial;
PriorityQueue<SearchNode> minPQ = new PriorityQueue<SearchNode>(initial.size() + 10);
Set<Board> previouses = new HashSet<Board>(50);
Board dequeuedBoard = initial;
Board previous = null;
SearchNode dequeuedNode = new SearchNode(initial, 0, null);
Iterable<Board> boards;
while (!dequeuedBoard.isGoal()) {
boards = dequeuedBoard.neighbors();
moves++;
for (Board board : boards) {
if (!board.equals(previous) && !previouses.contains(board)) {
minPQ.add(new SearchNode(board, moves, dequeuedNode));
}
}
previouses.add(previous);
previous = dequeuedBoard;
dequeuedNode = minPQ.poll();
dequeuedBoard = dequeuedNode.current;
}
finalNode = dequeuedNode;
}
// min number of moves to solve initial board
public int moves() {
if (boards != null) return boards.size()-1;
solution();
return boards.size() - 1;
}
public Iterable<Board> solution() {
if (boards != null) return boards;
boards = new Stack<Board>();
SearchNode pointer = finalNode;
while (pointer != null) {
boards.push(pointer.current);
pointer = pointer.previous;
}
return boards;
}
private class SearchNode implements Comparable<SearchNode> {
private final int priority;
private final SearchNode previous;
private final Board current;
public SearchNode(Board current, int moves, SearchNode previous) {
this.current = current;
this.previous = previous;
this.priority = moves + current.manhattan();
}
@Override
public int compareTo(SearchNode that) {
int cmp = this.priority - that.priority;
return Integer.compare(cmp, 0);
}
}
public static void main(String[] args) {
int[][] tiles = {{4, 1, 3},
{0, 2, 6},
{7, 5, 8}};
double start = System.currentTimeMillis();
Board board = new Board(tiles);
Solver solve = new Solver(board);
System.out.printf("# of moves = %d && # of actual moves %d & time passed %f\n, ", solve.moves(), solve.moves, (System.currentTimeMillis() - start) / 1000);
}
}
import java.util.HashSet;
导入java.util.Set;
导入java.util.Stack;
导入java.util.PriorityQueue;
公共类求解器{
私有整数移动=0;
私有搜索节点最终节点;
私人堆叠板;
公共解决方案(董事会首字母){
如果(!initial.isSolvable())抛出新的IllegalArgumentException(“无法解决的难题”);
//this.initial=initial;
PriorityQueue minPQ=新的PriorityQueue(initial.size()+10);
Set previouses=新哈希集(50);
Board dequeuedBoard=初始;
上一个板=空;
SearchNode dequeuedNode=新的SearchNode(初始值,0,null);
可折叠板;
而(!dequeuedBoard.isGoal()){
boards=dequeuedBoard.neights();
移动++;
用于(板:板){
如果(!board.equals(previous)&&!previouses.contains(board)){
添加(新的搜索节点(board、moves、dequeuedNode));
}
}
上一个。添加(上一个);
previous=出列板;
dequeuedNode=minPQ.poll();
dequeuedBoard=dequeuedNode.current;
}
finalNode=dequeuedNode;
}
//求解初始板的最小移动次数
公营机构{
如果(boards!=null)返回boards.size()-1;
溶液();
返回板。尺寸()-1;
}
公共可替代解决方案(){
如果(板数!=null)返回板数;
boards=新堆栈();
SearchNode指针=最终节点;
while(指针!=null){
板。推(指针。电流);
指针=pointer.previous;
}
返回板;
}
私有类SearchNode实现了可比较的{
私有最终int优先级;
私有最终搜索节点;
私人最终董事会电流;
公共SearchNode(当前板、整数移动、上一个SearchNode){
这个电流=电流;
this.previous=先前;
this.priority=moves+current.manhattan();
}
@凌驾
public int compareTo(搜索节点){
int cmp=this.priority-that.priority;
返回整数。比较(cmp,0);
}
}
公共静态void main(字符串[]args){
int[]tiles={{4,1,3},
{0, 2, 6},
{7, 5, 8}};
双启动=System.currentTimeMillis();
板=新板(瓷砖);
解算器解算=新解算器(板);
System.out.printf(“#移动次数=%d和实际移动次数%d和经过的时间%f\n,”,solve.moves(),solve.moves,(System.currentTimeMillis()-start)/1000);
}
}
和Board.java,以防万一:
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
public final class Board {
private final int[][] tilesCopy;
private final int N;
// cache
private int hashCode = -1;
private int zeroRow = -1;
private int zeroCol = -1;
private Collection<Board> neighbors;
/*
* Rep Invariant
* tilesCopy.length > 0
* Abstraction Function
* represent single board of 8 puzzle game
* Safety Exposure
* all fields are private and final (except cache variables). In the constructor,
* defensive copy of tiles[][] (array that is received from the client)
* is done.
*/
public Board(int[][] tiles) {
//this.N = tiles.length;
this.N = 3;
this.tilesCopy = new int[N][N];
// defensive copy
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (tiles[i][j] >= 0 && tiles[i][j] < N*N) tilesCopy[i][j] = tiles[i][j];
else {
System.out.printf("Illegal tile value at (%d, %d): "
+ "should be between 0 and N^2 - 1.", i, j);
System.exit(1);
}
}
}
checkRep();
}
public int tileAt(int row, int col) {
if (row < 0 || row > N - 1) throw new IndexOutOfBoundsException
("row should be between 0 and N - 1");
if (col < 0 || col > N - 1) throw new IndexOutOfBoundsException
("col should be between 0 and N - 1");
return tilesCopy[row][col];
}
public int size() {
return N;
}
public int hamming() {
int hamming = 0;
for (int row = 0; row < this.size(); row++) {
for (int col = 0; col < this.size(); col++) {
if (tileAt(row, col) != 0 && tileAt(row, col) != (row*N + col + 1)) hamming++;
}
}
return hamming;
}
// sum of Manhattan distances between tiles and goal
public int manhattan() {
int manhattan = 0;
int expectedRow = 0, expectedCol = 0;
for (int row = 0; row < this.size(); row++) {
for (int col = 0; col < this.size(); col++) {
if (tileAt(row, col) != 0 && tileAt(row, col) != (row*N + col + 1)) {
expectedRow = (tileAt(row, col) - 1) / N;
expectedCol = (tileAt(row, col) - 1) % N;
manhattan += Math.abs(expectedRow - row) + Math.abs(expectedCol - col);
}
}
}
return manhattan;
}
public boolean isGoal() {
if (tileAt(N-1, N-1) != 0) return false; // prune
for (int i = 0; i < this.size(); i++) {
for (int j = 0; j < this.size(); j++) {
if (tileAt(i, j) != 0 && tileAt(i, j) != (i*N + j + 1)) return false;
}
}
return true;
}
// change i && j' s name
public boolean isSolvable() {
int inversions = 0;
for (int i = 0; i < this.size() * this.size(); i++) {
int currentRow = i / this.size();
int currentCol = i % this.size();
if (tileAt(currentRow, currentCol) == 0) {
this.zeroRow = currentRow;
this.zeroCol = currentCol;
}
for (int j = i; j < this.size() * this.size(); j++) {
int row = j / this.size();
int col = j % this.size();
if (tileAt(row, col) != 0 && tileAt(row, col) < tileAt(currentRow, currentCol)) {
inversions++;
}
}
}
if (tilesCopy.length % 2 != 0 && inversions % 2 != 0) return false;
if (tilesCopy.length % 2 == 0 && (inversions + this.zeroRow) % 2 == 0) return false;
return true;
}
@Override
public boolean equals(Object y) {
if (!(y instanceof Board)) return false;
Board that = (Board) y;
// why bother checking whole array, if last elements aren't equals
return this.tileAt(N - 1, N - 1) == that.tileAt(N - 1, N - 1) && this.size() == that.size() && Arrays.deepEquals(this.tilesCopy, that.tilesCopy);
}
@Override
public int hashCode() {
if (this.hashCode != -1) return hashCode;
// more optimized version(Arrays.hashCode is too slow)?
this.hashCode = Arrays.deepHashCode(tilesCopy);
return this.hashCode;
}
public Collection<Board> neighbors() {
if (neighbors != null) return neighbors;
if (this.zeroRow == -1 && this.zeroCol == -1) findZeroTile();
neighbors = new HashSet<>();
if (zeroRow - 1 >= 0) generateNeighbor(zeroRow - 1, true);
if (zeroCol - 1 >= 0) generateNeighbor(zeroCol - 1, false);
if (zeroRow + 1 < this.size()) generateNeighbor(zeroRow + 1, true);
if (zeroCol + 1 < this.size()) generateNeighbor(zeroCol + 1, false);
return neighbors;
}
private void findZeroTile() {
outerloop:
for (int i = 0; i < this.size(); i++) {
for (int j = 0; j < this.size(); j++) {
if (tileAt(i, j) == 0) {
this.zeroRow = i; // index starting from 0
this.zeroCol = j;
break outerloop;
}
}
}
}
private void generateNeighbor(int toPosition, boolean isRow) {
int[][] copy = Arrays.copyOf(this.tilesCopy, tilesCopy.length);
if (isRow) swapEntries(copy, zeroRow, zeroCol, toPosition, zeroCol);
else swapEntries(copy, zeroRow, zeroCol, zeroRow, toPosition);
neighbors.add(new Board(copy));
}
private void swapEntries(int[][] array, int fromRow, int fromCol, int toRow, int toCol) {
int i = array[fromRow][fromCol];
array[fromRow][fromCol] = array[toRow][toCol];
array[toRow][toCol] = i;
}
public String toString() {
StringBuilder s = new StringBuilder(4 * N * N); // optimization?
// s.append(N + "\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s.append(String.format("%2d ", tileAt(i, j)));
}
s.append("\n");
}
return s.toString();
}
private void checkRep() {
assert tilesCopy.length > 0;
}
}
导入java.util.array;
导入java.util.Collection;
导入java.util.HashSet;
公开期末考试委员会{
私人最终整版[][]瓷砖复印件;
私人终审法院;
//缓存
私有int hashCode=-1;
private int zerorrow=-1;
私有整数zeroCol=-1;
私人收藏邻居;
/*
*重复不变量
*TileCopy.length>0
*抽象功能
*代表单板的8个益智游戏
*安全暴露
*所有字段都是私有的和最终的(缓存变量除外),
*分片[][](从客户端接收的阵列)的防御副本
*完成了。
*/
公共电路板(int[][]瓷砖){
//这.N=瓦片长度;
这个。N=3;
this.tilesCopy=新整数[N][N];
//防御性副本
对于(int i=0;i=0和&tiles[i][j]N-1)抛出新的IndexOutOfBoundsException
(“行应介于0和N-1之间”);
如果(col<0 | | col>N-1)抛出新的IndexOutOfBoundsException
(“col应介于0和N-1之间”);
返回瓷砖复制[行][列];
}
公共整数大小(){
返回N;
}
公共卫生署署长{
int-hamming=0;
对于(int row=0;rowint[][] copy = Arrays.copyOf(this.tilesCopy, tilesCopy.length);
copy == this.tolesCopy // false
copy[0] == this.tilesCopy[0] // true
copy[1] == this.tilesCopy[1] // true
copy[2] == this.tilesCopy[2] // true
private void generateNeighbor(int toPosition, boolean isRow) {
Board board = new Board(this.tilesCopy);
if (isRow) swapEntries(board.tilesCopy, zeroRow, zeroCol, toPosition, zeroCol);
else swapEntries(board.tilesCopy, zeroRow, zeroCol, zeroRow, toPosition);
neighbors.add(board);
}