forked from rampatra/Algorithms-and-Data-Structures-in-Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKnightTour.java
111 lines (95 loc) · 3.39 KB
/
KnightTour.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.rampatra.backtracking;
/**
* Created by IntelliJ IDEA.
* <p/>
* A knight's tour is a sequence of moves of a knight on a chessboard such that the knight visits every square only
* once. If the knight ends on a square that is one knight's move from the beginning square (so that it could tour the
* board again immediately, following the same path), the tour is closed, otherwise it is open.
*
* @author rampatra
* @since 10/15/15
* @time: 11:56 PM
* @see: https://en.wikipedia.org/wiki/Knight%27s_tour
* @see: RatInAMaze for a simpler version of this problem
*/
public class KnightTour {
/**
* Determines if a move is a valid move in the given chess board.
*
* @param i is the row of the new move
* @param j is the column of the new move
* @param tour
* @return
*/
public static boolean isValidMove(int i, int j, int[][] tour) {
if (i >= 0 && i < tour.length && j >= 0 && j < tour[0].length && tour[i][j] == 0) {
return true;
} else {
return false;
}
}
/**
* Finds a valid knight's tour for a given chess board size if any
* with the use of backtracking.
*
* @param i
* @param j
* @param xMoves
* @param yMoves
* @param step
* @param tour
* @return
*/
public static boolean isValidKnightTour(int i, int j, int[] xMoves, int[] yMoves, int step, int[][] tour) {
if (step > tour.length * tour[0].length) return true;
int nextI, nextJ;
for (int k = 0; k < xMoves.length; k++) {
// next move is calculated from all possible moves
nextI = i + xMoves[k];
nextJ = j + yMoves[k];
// if the next move is valid then we proceed otherwise we
// try next set of moves
if (isValidMove(nextI, nextJ, tour)) {
tour[nextI][nextJ] = step;
if (isValidKnightTour(nextI, nextJ, xMoves, yMoves, step + 1, tour)) {
return true;
} else {
tour[nextI][nextJ] = 0; // backtrack
}
}
}
return false;
}
/**
* Prints the knight's tour if any.
*
* @param i is the start row
* @param j is the start column
* @param boardSize is the size of the chess board
*/
public static void printKnightTour(int i, int j, int[] boardSize) {
if (boardSize.length < 2) return;
// a 2D array for the knight's tour
int[][] tour = new int[boardSize[0]][boardSize[1]];
// all possible relative moves that a knight can make
int[] xMoves = new int[]{1, 1, 2, 2, -1, -1, -2, -2};
int[] yMoves = new int[]{-2, 2, -1, 1, -2, 2, -1, 1};
tour[0][0] = 1;
if (isValidKnightTour(i, j, xMoves, yMoves, 2, tour)) {
print2DMatrix(tour);
} else {
System.out.println("Knight's tour doesn't exist for board size [" + boardSize[0] + "x" + boardSize[1] + "]");
}
}
public static void print2DMatrix(int[][] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
System.out.print("[" + array[i][j] + "]");
}
System.out.println();
}
}
public static void main(String[] args) {
printKnightTour(0, 0, new int[]{8, 8});
}
}