4
4
import java .util .Comparator ;
5
5
import java .util .List ;
6
6
7
- /*
8
- * Problem Statement: -
9
-
10
- Given a N*N board with the Knight placed on the first block of an empty board. Moving according
11
- to the rules of chess knight must visit each square exactly once. Print the order of each cell in
12
- which they are visited.
13
-
14
- Example: -
15
-
16
- Input : N = 8
17
-
18
- Output:
19
- 0 59 38 33 30 17 8 63
20
- 37 34 31 60 9 62 29 16
21
- 58 1 36 39 32 27 18 7
22
- 35 48 41 26 61 10 15 28
23
- 42 57 2 49 40 23 6 19
24
- 47 50 45 54 25 20 11 14
25
- 56 43 52 3 22 13 24 5
26
- 51 46 55 44 53 4 21 12
27
-
7
+ /**
8
+ * The KnightsTour class solves the Knight's Tour problem using backtracking.
9
+ *
10
+ * Problem Statement:
11
+ * Given an N*N board with a knight placed on the first block, the knight must
12
+ * move according to chess rules and visit each square on the board exactly once.
13
+ * The class outputs the sequence of moves for the knight.
14
+ *
15
+ * Example:
16
+ * Input: N = 8 (8x8 chess board)
17
+ * Output: The sequence of numbers representing the order in which the knight visits each square.
28
18
*/
29
19
public final class KnightsTour {
30
20
private KnightsTour () {
31
21
}
32
22
23
+ // The size of the chess board (12x12 grid, with 2 extra rows/columns as a buffer around a 8x8 area)
33
24
private static final int BASE = 12 ;
34
- private static final int [][] MOVES = {
35
- {1 , -2 },
36
- {2 , -1 },
37
- {2 , 1 },
38
- {1 , 2 },
39
- {-1 , 2 },
40
- {-2 , 1 },
41
- {-2 , -1 },
42
- {-1 , -2 },
43
- }; // Possible moves by knight on chess
44
- private static int [][] grid ; // chess grid
45
- private static int total ; // total squares in chess
46
-
47
- public static void main (String [] args ) {
48
- grid = new int [BASE ][BASE ];
49
- total = (BASE - 4 ) * (BASE - 4 );
50
-
51
- for (int r = 0 ; r < BASE ; r ++) {
52
- for (int c = 0 ; c < BASE ; c ++) {
53
- if (r < 2 || r > BASE - 3 || c < 2 || c > BASE - 3 ) {
54
- grid [r ][c ] = -1 ;
55
- }
56
- }
57
- }
58
25
59
- int row = 2 + (int ) (Math .random () * (BASE - 4 ));
60
- int col = 2 + (int ) (Math .random () * (BASE - 4 ));
61
-
62
- grid [row ][col ] = 1 ;
63
-
64
- if (solve (row , col , 2 )) {
65
- printResult ();
66
- } else {
67
- System .out .println ("no result" );
68
- }
69
- }
70
-
71
- // Return True when solvable
72
- private static boolean solve (int row , int column , int count ) {
26
+ // Possible moves for a knight in chess
27
+ private static final int [][] MOVES = {
28
+ {1 , -2 },
29
+ {2 , -1 },
30
+ {2 , 1 },
31
+ {1 , 2 },
32
+ {-1 , 2 },
33
+ {-2 , 1 },
34
+ {-2 , -1 },
35
+ {-1 , -2 },
36
+ };
37
+
38
+ // Chess grid representing the board
39
+ static int [][] grid ;
40
+
41
+ // Total number of cells the knight needs to visit
42
+ static int total ;
43
+
44
+ /**
45
+ * Recursive method to solve the Knight's Tour problem.
46
+ *
47
+ * @param row The current row of the knight
48
+ * @param column The current column of the knight
49
+ * @param count The current move number
50
+ * @return True if a solution is found, False otherwise
51
+ */
52
+ static boolean solve (int row , int column , int count ) {
73
53
if (count > total ) {
74
54
return true ;
75
55
}
@@ -80,49 +60,72 @@ private static boolean solve(int row, int column, int count) {
80
60
return false ;
81
61
}
82
62
63
+ // Sort neighbors by Warnsdorff's rule (fewest onward moves)
83
64
neighbor .sort (Comparator .comparingInt (a -> a [2 ]));
84
65
85
66
for (int [] nb : neighbor ) {
86
- row = nb [0 ];
87
- column = nb [1 ];
88
- grid [row ][ column ] = count ;
89
- if (!orphanDetected (count , row , column ) && solve (row , column , count + 1 )) {
67
+ int nextRow = nb [0 ];
68
+ int nextCol = nb [1 ];
69
+ grid [nextRow ][ nextCol ] = count ;
70
+ if (!orphanDetected (count , nextRow , nextCol ) && solve (nextRow , nextCol , count + 1 )) {
90
71
return true ;
91
72
}
92
- grid [row ][ column ] = 0 ;
73
+ grid [nextRow ][ nextCol ] = 0 ; // Backtrack
93
74
}
94
75
95
76
return false ;
96
77
}
97
78
98
- // Returns List of neighbours
99
- private static List <int []> neighbors (int row , int column ) {
79
+ /**
80
+ * Returns a list of valid neighboring cells where the knight can move.
81
+ *
82
+ * @param row The current row of the knight
83
+ * @param column The current column of the knight
84
+ * @return A list of arrays representing valid moves, where each array contains:
85
+ * {nextRow, nextCol, numberOfPossibleNextMoves}
86
+ */
87
+ static List <int []> neighbors (int row , int column ) {
100
88
List <int []> neighbour = new ArrayList <>();
101
89
102
90
for (int [] m : MOVES ) {
103
91
int x = m [0 ];
104
92
int y = m [1 ];
105
- if (grid [row + y ][column + x ] == 0 ) {
93
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid [row + y ][column + x ] == 0 ) {
106
94
int num = countNeighbors (row + y , column + x );
107
95
neighbour .add (new int [] {row + y , column + x , num });
108
96
}
109
97
}
110
98
return neighbour ;
111
99
}
112
100
113
- // Returns the total count of neighbors
114
- private static int countNeighbors (int row , int column ) {
101
+ /**
102
+ * Counts the number of possible valid moves for a knight from a given position.
103
+ *
104
+ * @param row The row of the current position
105
+ * @param column The column of the current position
106
+ * @return The number of valid neighboring moves
107
+ */
108
+ static int countNeighbors (int row , int column ) {
115
109
int num = 0 ;
116
110
for (int [] m : MOVES ) {
117
- if (grid [row + m [1 ]][column + m [0 ]] == 0 ) {
111
+ int x = m [0 ];
112
+ int y = m [1 ];
113
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid [row + y ][column + x ] == 0 ) {
118
114
num ++;
119
115
}
120
116
}
121
117
return num ;
122
118
}
123
119
124
- // Returns true if it is orphan
125
- private static boolean orphanDetected (int count , int row , int column ) {
120
+ /**
121
+ * Detects if moving to a given position will create an orphan (a position with no further valid moves).
122
+ *
123
+ * @param count The current move number
124
+ * @param row The row of the current position
125
+ * @param column The column of the current position
126
+ * @return True if an orphan is detected, False otherwise
127
+ */
128
+ static boolean orphanDetected (int count , int row , int column ) {
126
129
if (count < total - 1 ) {
127
130
List <int []> neighbor = neighbors (row , column );
128
131
for (int [] nb : neighbor ) {
@@ -134,14 +137,18 @@ private static boolean orphanDetected(int count, int row, int column) {
134
137
return false ;
135
138
}
136
139
137
- // Prints the result grid
140
+ /**
141
+ * Prints the resulting chess board after solving the Knight's Tour.
142
+ * Visited cells are displayed with their move numbers, while boundary/invalid cells are marked as "XX".
143
+ */
138
144
private static void printResult () {
139
145
for (int [] row : grid ) {
140
146
for (int i : row ) {
141
147
if (i == -1 ) {
142
- continue ;
148
+ System .out .print ("XX " ); // Invalid cells
149
+ } else {
150
+ System .out .printf ("%2d " , i ); // Print the move number
143
151
}
144
- System .out .printf ("%2d " , i );
145
152
}
146
153
System .out .println ();
147
154
}
0 commit comments