Reputation: 63
Knight's tour was asked before, but I'm still having trouble with it. I'm trying a recursion to visit all cells of chessboard but I can't make more than 52 visits. After that it backtracks and the number of visited cells counts down. Here is my code:
public class Ch7E22_3 {
public static int[][] chess;
public static int[][] adjacent;
public static void main(String[] args) {
chess = new int[8][8];
adjacent = new int[][] { { 2, 1 }, { 2, -1 }, { -2, 1 }, { -2, -1 }, { 1, 2 }, { -1, 2 }, { 1, -2 },
{ -1, -2 } };
initializeChess();
move(1, 0, 0);
}
private static void move(int cnt, int row, int col) {
chess[row][col] = cnt;
if (cnt == (8 * 8)) {
System.out.println("You moved around all cells: " + cnt);
} else {
for (int i = 0; i < 8; i++) {
if (((row + adjacent[i][0] >= 0) && (row + adjacent[i][0]) < 8)
&& ((col + adjacent[i][1] >= 0) && (col + adjacent[i][1] < 8))) {
if (chess[row + adjacent[i][0]][col + adjacent[i][1]] == 0) {
row = row + adjacent[i][0];
col = col + adjacent[i][1];
cnt++;
System.out.println(row + " " + col + " cnt = " + cnt);
move(cnt, row, col);
}
}
}
}
chess[row][col] = 0;
}
private static void initializeChess() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
chess[i][j] = 0;
}
}
}
}
Upvotes: 2
Views: 133
Reputation: 16359
Your backtracking is not correct. By the time the last line executes, setting chess[row][col]
back to zero, row
and col
have almost certainly changed.
It would be better to never change row
, col
, and cnt
in your method, but only pass new values into the recursive call. Something like this, although I haven't checked the rest of your logic:
for (int i = 0; i < 8; i++) {
int nextrow = row + adjacent[i][0];
int nextcol = col + adjacent[i][1];
if (nextrow >= 0 && nextrow < 8 &&
nextcol >= 0 && nextcol < 8) {
if (chess[nextrow][nextcol] == 0) {
System.out.println(nextrow + " " + nextcol + " cnt = " + (cnt+1));
move(cnt+1, nextrow, nextcol);
}
}
}
To ensure you're consistent in only modifying the values that are passed down to the subsequent recursive call, and never modifying them within the method, you can make the parameters final:
private static void move(final int cnt, final int row, final int col) {
...
}
Upvotes: 2
Reputation: 140427
A first problem is here:
for (int i = 0; i < 8; i++) {
So, you have that out for loop. Lets assume you enter with cnt at 51.
Now you have
if ( ... some overly complicated condition ... ) {
... cnt++
move(cnt,
What happens now is: first you make your recursive calls, and probably each time right your first if hits. Thus, you increase cnt and recurse again. Therefore your printouts show how cnt is constantly increasing.
But at some point, the recursion ends - the if condition doesn't get true any more. So the recursively called method ... ends. But keep in mind: you called that method ... from another call to move. And that one might still be looping. And more importantly, that move() has its own version of cnt.
To see what I mean: change cnt from being a method local variable to be a field of your class, similar to your board! When you do that, you will find that your code actually prints:
...
3 7 cnt = 52
2 4 cnt = 53
...
2 3 cnt = 64
You moved around all cells: 64
0 4 cnt = 65
...
to actually stop later on with
4 0 cnt = 126
Meaning: printing of cnt is just a side effect of your algorithm not really working correctly!
Finally: I would recommend to break up your if condition into a set of small helper methods, like
private static isXyz(...)
and to call those methods within that if statement - it would help with readability dramatically!
Upvotes: 2