This is a Knight's Tour problem. The first application:
import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
public class GcdsHorse {
private static int X;
private static int Y;
private static boolean[] visited;
private static boolean finished;
public static void main(String[] args) {
System.out.println("the horse has been running");
X = 8;
Y = 8;
int row = 2;
int column = 3;
int[][] chessboard = new int[X][Y];
visited = new boolean[X * Y];
long start = System.currentTimeMillis();
traversalChessboard(chessboard, row - 1, column - 1, 1);
long end = System.currentTimeMillis();
System.out.println("time: " + (end - start) + " ms");
for (int[] rows:chessboard){
for (int steps:rows){
System.out.print(steps+"\t");
}
System.out.println();
}
}
public static void traversalChessboard(int[][] chessboard, int row, int column, int step){
System.out.println(step);
chessboard[row][column] =step;
visited[row * X + column] = true;
ArrayList<Point> ps = getAvailable(new Point(column, row));
sort(ps);
while(!ps.isEmpty()) {
Point p = (Point)ps.remove(0);
if (!visited[p.y * X + p.x]) {
traversalChessboard(chessboard, p.y, p.x, step + 1);
}
}
if (step < X * Y && !finished) {
chessboard[row][column] = 0;
visited[row * X + column] = false;
} else {
finished = true;
}
}
//This method is to get next collection of the position that horse can reach in current position
public static ArrayList<Point> getAvailable(Point curPoint){
ArrayList<Point> ps=new ArrayList<>();
Point p1=new Point();
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
return ps;
}
//The core of GCD. This method is to sort the collection of position the horse can reach according to time-consuming.
public static void sort(ArrayList<Point> ps) {
ps.sort(new Comparator<Point>() {
public int compare(Point o1, Point o2) {
int count1 = GcdsHorse.getAvailable(o1).size();
int count2 = GcdsHorse.getAvailable(o2).size();
if (count1 < count2) {
return -1;
} else {
return count1 == count2 ? 0 : 1;
}
}
});
}
}
And the computational results is:
time: 12 ms
2 35 4 19 30 33 14 17
5 20 1 34 15 18 29 32
36 3 62 57 44 31 16 13
21 6 59 54 61 28 43 46
52 37 56 63 58 45 12 27
7 22 53 60 55 64 47 42
38 51 24 9 40 49 26 11
23 8 39 50 25 10 41 48
The cost of time is low. But when I use the same algorithm and the same data in a swing application. It seems like an endless loop. Code is below:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Comparator;
public class HorsePane extends JFrame implements ActionListener,Runnable{
private static int X;
private static int Y;
private static boolean[] visited;
private static boolean finished;
private JTextField[] texts;
private JButton button;
private DefaultTableModel tableModel;
private JTable jtable;
public Object [] temp= {"no result"};
Thread thread;
public HorsePane(){
super("knigtht's tour");
this.setBounds(400, 300, 800, 360);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel panel=new JPanel();
this.getContentPane().add(panel,"North");
String[] str_label= {"chessboard's row","chessboard's column","initial row","initial column"};
String[] str_text= {"6","6","1","1"};
this.texts=new JTextField[str_text.length];
for(int i=0; i<str_text.length;i++)
{
panel.add(new JLabel(str_label[i]));
panel.add(this.texts[i]=new JTextField(str_text[i]));
}
panel.add(this.button=new JButton("demonstrate"));
this.button.addActionListener(this);
this.tableModel =new DefaultTableModel();
this.tableModel.setRowCount(0);
this.tableModel.setColumnCount(0);
this. jtable=new JTable (this.tableModel);
this.getContentPane().add(new JScrollPane(jtable));
this.setVisible(true);
}
public static void traversalChessboard(int[][] chessboard, int row, int column, int step){
System.out.println(step);
chessboard[row][column] =step;
visited[row * X + column] = true;
ArrayList<Point> ps = getAvailable(new Point(column, row));
sort(ps);
while(!ps.isEmpty()) {
Point p = (Point)ps.remove(0);
if (!visited[p.y * X + p.x]) {
traversalChessboard(chessboard, p.y, p.x, step + 1);
}
}
if (step < X * Y && !finished) {
chessboard[row][column] = 0;
visited[row * X + column] = false;
} else {
finished = true;
}
}
//This method is to get next collection of the position that horse can reach in current position
public static ArrayList<Point> getAvailable(Point curPoint){
ArrayList<Point> ps=new ArrayList<>();
Point p1=new Point();if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
ps.add(new Point(p1));
}
return ps;
}
//The core of GCD. This method is to sort the collection of position the horse can reach according to time-consuming.
public static void sort(ArrayList<Point> ps) {
ps.sort(new Comparator<Point>() {
public int compare(Point o1, Point o2) {
int count1 = GcdsHorse.getAvailable(o1).size();
int count2 = GcdsHorse.getAvailable(o2).size();
if (count1 < count2) {
return -1;
} else {
return count1 == count2 ? 0 : 1;
}
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
this.tableModel.setRowCount(0);
this.tableModel.setColumnCount(0);
if(e.getSource() instanceof JButton)
{
this.thread=new Thread(this);
this.thread.start();
}
}
@Override
public void run() {
try {
X=Integer.parseInt(texts[0].getText());
Y=Integer.parseInt(texts[1].getText());
int row=Integer.parseInt(texts[2].getText());
int column=Integer.parseInt(texts[3].getText());
int[][] chessboard = new int[X][Y];
visited = new boolean[X * Y];
finished=false;
traversalChessboard(chessboard, row - 1, column - 1, 1);
if(!finished){
throw new Exception("no result");
}
this.tableModel.setRowCount(X);
this.tableModel.setColumnCount(Y);
for(int i=1;i<=X*Y;i++){
Point p = getIndex(chessboard,i);
this.tableModel.setValueAt(String.format("%d", i),p.x, p.y);
this.thread.sleep(500);
}
this.thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, e.toString());
}
}
public static Point getIndex(int[][] temp1,int temp2){
for (int i=0;i<X;i++){
for(int j=0;j<Y;j++){
if (temp1[i][j]==temp2){
return new Point(i,j);
}
}
}
return null;
}
public static void main(String[] args) {
new HorsePane();
}
}
But in other situation, when I use other data, the second swing application can run. data:6,6,1,1 data:8,8,1,1
I can't find where the reason is.