//solver.java的debug未完成
另外以后我将把我的project代码都放在GitHub上了:https://github.com/wuwentao1998
//Board.java
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import java.util.Stack;
import java.lang.Math;
public class Board {
private char[][] blocks;
private int dimension;
public Board(int[][] blocks) {
this.dimension = blocks.length;
this.blocks = new char[dimension][dimension];
for (int i = 0;i<dimension;i++) {
for (int j = 0;j<dimension;j++) {
this.blocks[i][j] =(char) blocks[i][j];
}
}
} // construct a board from an n-by-n array of blocks
// (where blocks[i][j] = block in row i, column j)
public int dimension() {
return dimension;
} // board dimension n
public int hamming() {
int num =0;
for (int i = 0;i<dimension;i++) {
for (int j =0;j<dimension;j++) {
if ( i +j != dimension*2 -1 && blocks[i][j] != i * dimension + j+1 ) {
num++;
}
}
}
return num;
} // number of blocks out of place
public int manhattan() {
int distance = 0;
for (int i = 0;i<dimension;i++) {
for (int j = 0;j<dimension;j++) {
if (blocks[i][j] != 0) {
int col = (blocks[i][j] - 1) % dimension;
int row = (blocks[i][j] - col - 1) / dimension;
distance += (((col > j) ? (col - j) : (j - col)) +
((row > i) ? (row - i) : (i - row)));
}
}
}
return distance;
} // sum of Manhattan distances between blocks and goal
public boolean isGoal() {
return this.hamming() ==0;
} // is this board the goal board?
public Board twin() {
int[][] twinBoard = new int[dimension][dimension];
for (int i=0; i<dimension; i++) {
for (int j = 0; j < dimension; j++) {
twinBoard[i][j] = blocks[i][j];
}
}
if (twinBoard[0][0] != 0 && twinBoard[0][1] != 0){
exch(twinBoard,0,0,0,1);
}else{
exch(twinBoard,1,0,1,1);
}
return new Board(twinBoard);
} // a board that is obtained by exchanging any pair of blocks
public boolean equals(Object y) {
if (this == y)
return true;
if (y == null)
return false;
if (this.getClass() != y.getClass())
return false;
Board that = (Board) y;
if(this.dimension != that.dimension)
return false;
for (int i=0; i<dimension; i++){
for (int j=0; j<dimension; j++){
if (this.blocks[i][j] !=that.blocks[i][j]){
return false;
}
}
}
return true;
} // does this board equal y?
public Iterable<Board> neighbors() // all neighboring boards
{
int blankRow = 0;
int blankCol = 0;
Stack<Board> neighbours = new Stack<Board>();
int[][] clone = new int[dimension][dimension];
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
clone[i][j] = (int) blocks[i][j];
if (clone[i][j] == 0) {
blankRow = i;
blankCol = j;
}
}
}
if (blankCol != 0) {
exch(clone, blankRow, blankCol - 1, blankRow, blankCol);
neighbours.push(new Board(clone));
exch(clone, blankRow, blankCol - 1, blankRow, blankCol);
}
if (blankCol != (dimension - 1)) {
exch(clone, blankRow, blankCol + 1, blankRow, blankCol);
neighbours.push(new Board(clone));
exch(clone, blankRow, blankCol + 1, blankRow, blankCol);
}
if (blankRow != 0) {
exch(clone, blankRow - 1, blankCol, blankRow, blankCol);
neighbours.push(new Board(clone));
exch(clone, blankRow - 1, blankCol, blankRow, blankCol);
}
if (blankRow != (dimension - 1)) {
exch(clone, blankRow + 1, blankCol, blankRow, blankCol);
neighbours.push(new Board(clone));
}
return neighbours;
}
// 这种exch的写法是错误的,因为是传递的是复制的值
// private void exch(int a, int b) {
// int temp = a;
// a= b;
// b =temp;
// }
private void exch(int[][] array, int i, int j, int a, int b) {
int temp = array[i][j];
array[i][j] = array[a][b];
array[a][b] = temp;
}
public String toString() // string representation of this board (in the output format specified below)
{
StringBuilder s = new StringBuilder();
s.append(dimension + "\n");
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
s.append(String.format("%2d ", (int) blocks[i][j]));
}
s.append("\n");
}
return s.toString();
} // string representation of this board (in the output format specified below)
public static void main(String[] args) {
// read in the board specified in the filename
In in = new In(args[0]);
int n = in.readInt();
int[][] tiles = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
tiles[i][j] = in.readInt();
}
}
// solve the slider puzzle
Board initial = new Board(tiles);
StdOut.printf("hamming:%d manhattan:%d \n", initial.hamming(),
initial.manhattan());
StdOut.println("dim:" + initial.dimension());
StdOut.println(initial.toString());
StdOut.println("goal:" + initial.isGoal());
StdOut.println("twin:\n" + initial.twin().toString());
StdOut.println("neighbours:");
for (Board s : initial.neighbors()) {
StdOut.println(s.toString());
}
}
} // unit tests (not graded)
//Solver.java
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.StdOut;
import java.util.Comparator;
import java.util.Stack;
public class Solver {
private MinPQ<Node> open = new MinPQ<Node>(new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if (o1.priority < o2.priority)
return -1;
else if (o1.priority > o2.priority)
return 1;
else
return 0;
}
});
int move =-1;
boolean issolve = false;
Node currentNode;
private class Node implements Comparable<Node>{
int move;
boolean isTwin;
Board board;
Node parent;
int priority;
public Node(Board board, Node parent, boolean isTwin, int move) {
this.board = board;
this.parent = parent;
this.isTwin = isTwin;
this.move = move;
priority = this.board.manhattan() + this.move;
}
public int compareTo(Node that)
{
if (this.priority > that.priority) {
return 1;
}
else if (this.priority < that.priority) {
return -1;
}
else
return 0;
}
}
public Solver(Board initial) {
if (initial == null)
throw new NullPointerException();
currentNode = new Node(initial,null,false,0);
Node twinNode = new Node(initial.twin(),null,true,0);
// open.insert(twinNode);
open.insert(currentNode);
while (true) {
Node currentNode = open.delMin();
if (currentNode.board.isGoal() ) {
if (!currentNode.isTwin) {
issolve = true;
break;
}
else
{
issolve = false;
move = -1;
break;
}
}
for (Board neigh : currentNode.board.neighbors()) {
Node neighNode = new Node(neigh, currentNode, currentNode.isTwin, currentNode.move + 1);
if (currentNode.parent == null) {
open.insert(neighNode);
}
else if ( !currentNode.parent.equals(neigh) ) {
open.insert(neighNode);
}
}
}
} // find a solution to the initial board (using the A* algorithm)
public boolean isSolvable() {
return issolve;
} // is the initial board solvable?
public int moves() {
return move;
} // min number of moves to solve initial board; -1 if unsolvable
public Iterable<Board> solution() {
Stack<Board> solution = new Stack<Board>();
while (currentNode != null) {
solution.push(currentNode.board);
currentNode = currentNode.parent;
}
return solution;
} // sequence of boards in a shortest solution; null if unsolvable
public static void main(String[] args) {
// create initial board from file
In in = new In(args[0]);
int n = in.readInt();
int[][] blocks = new int[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
blocks[i][j] = in.readInt();
Board initial = new Board(blocks);
// solve the puzzle
Solver solver = new Solver(initial);
// print solution to standard output
if (!solver.isSolvable())
StdOut.println("No solution possible");
else {
StdOut.println("Minimum number of moves = " + solver.moves());
for (Board board : solver.solution())
StdOut.println(board);
}
} // solve a slider puzzle (given below)
}