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 ;
25
+
26
+ // Possible moves for a knight in chess
34
27
private static final int [][] MOVES = {
35
28
{1 , -2 },
36
29
{2 , -1 },
@@ -40,36 +33,40 @@ private KnightsTour() {
40
33
{-2 , 1 },
41
34
{-2 , -1 },
42
35
{-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
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 ;
46
43
47
- public static void main (String [] args ) {
44
+ /**
45
+ * Resets the chess board to its initial state.
46
+ * Initializes the grid with boundary cells marked as -1 and internal cells as 0.
47
+ * Sets the total number of cells the knight needs to visit.
48
+ */
49
+ public static void resetBoard () {
48
50
grid = new int [BASE ][BASE ];
49
51
total = (BASE - 4 ) * (BASE - 4 );
50
-
51
52
for (int r = 0 ; r < BASE ; r ++) {
52
53
for (int c = 0 ; c < BASE ; c ++) {
53
54
if (r < 2 || r > BASE - 3 || c < 2 || c > BASE - 3 ) {
54
- grid [r ][c ] = -1 ;
55
+ grid [r ][c ] = -1 ; // Mark boundary cells
55
56
}
56
57
}
57
58
}
58
-
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
59
}
70
60
71
- // Return True when solvable
72
- private static boolean solve (int row , int column , int count ) {
61
+ /**
62
+ * Recursive method to solve the Knight's Tour problem.
63
+ *
64
+ * @param row The current row of the knight
65
+ * @param column The current column of the knight
66
+ * @param count The current move number
67
+ * @return True if a solution is found, False otherwise
68
+ */
69
+ static boolean solve (int row , int column , int count ) {
73
70
if (count > total ) {
74
71
return true ;
75
72
}
@@ -80,49 +77,72 @@ private static boolean solve(int row, int column, int count) {
80
77
return false ;
81
78
}
82
79
80
+ // Sort neighbors by Warnsdorff's rule (fewest onward moves)
83
81
neighbor .sort (Comparator .comparingInt (a -> a [2 ]));
84
82
85
83
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 )) {
84
+ int nextRow = nb [0 ];
85
+ int nextCol = nb [1 ];
86
+ grid [nextRow ][ nextCol ] = count ;
87
+ if (!orphanDetected (count , nextRow , nextCol ) && solve (nextRow , nextCol , count + 1 )) {
90
88
return true ;
91
89
}
92
- grid [row ][ column ] = 0 ;
90
+ grid [nextRow ][ nextCol ] = 0 ; // Backtrack
93
91
}
94
92
95
93
return false ;
96
94
}
97
95
98
- // Returns List of neighbours
99
- private static List <int []> neighbors (int row , int column ) {
96
+ /**
97
+ * Returns a list of valid neighboring cells where the knight can move.
98
+ *
99
+ * @param row The current row of the knight
100
+ * @param column The current column of the knight
101
+ * @return A list of arrays representing valid moves, where each array contains:
102
+ * {nextRow, nextCol, numberOfPossibleNextMoves}
103
+ */
104
+ static List <int []> neighbors (int row , int column ) {
100
105
List <int []> neighbour = new ArrayList <>();
101
106
102
107
for (int [] m : MOVES ) {
103
108
int x = m [0 ];
104
109
int y = m [1 ];
105
- if (grid [row + y ][column + x ] == 0 ) {
110
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid [row + y ][column + x ] == 0 ) {
106
111
int num = countNeighbors (row + y , column + x );
107
112
neighbour .add (new int [] {row + y , column + x , num });
108
113
}
109
114
}
110
115
return neighbour ;
111
116
}
112
117
113
- // Returns the total count of neighbors
114
- private static int countNeighbors (int row , int column ) {
118
+ /**
119
+ * Counts the number of possible valid moves for a knight from a given position.
120
+ *
121
+ * @param row The row of the current position
122
+ * @param column The column of the current position
123
+ * @return The number of valid neighboring moves
124
+ */
125
+ static int countNeighbors (int row , int column ) {
115
126
int num = 0 ;
116
127
for (int [] m : MOVES ) {
117
- if (grid [row + m [1 ]][column + m [0 ]] == 0 ) {
128
+ int x = m [0 ];
129
+ int y = m [1 ];
130
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid [row + y ][column + x ] == 0 ) {
118
131
num ++;
119
132
}
120
133
}
121
134
return num ;
122
135
}
123
136
124
- // Returns true if it is orphan
125
- private static boolean orphanDetected (int count , int row , int column ) {
137
+ /**
138
+ * Detects if moving to a given position will create an orphan (a position with no further valid moves).
139
+ *
140
+ * @param count The current move number
141
+ * @param row The row of the current position
142
+ * @param column The column of the current position
143
+ * @return True if an orphan is detected, False otherwise
144
+ */
145
+ static boolean orphanDetected (int count , int row , int column ) {
126
146
if (count < total - 1 ) {
127
147
List <int []> neighbor = neighbors (row , column );
128
148
for (int [] nb : neighbor ) {
@@ -133,17 +153,4 @@ private static boolean orphanDetected(int count, int row, int column) {
133
153
}
134
154
return false ;
135
155
}
136
-
137
- // Prints the result grid
138
- private static void printResult () {
139
- for (int [] row : grid ) {
140
- for (int i : row ) {
141
- if (i == -1 ) {
142
- continue ;
143
- }
144
- System .out .printf ("%2d " , i );
145
- }
146
- System .out .println ();
147
- }
148
- }
149
156
}
0 commit comments