all.
I am working on this problem which comes from Leetcode.
Here is the link if anyone want to see the problem: https://leetcode.com/problems/valid-sudoku/
I think I almost solve this problem, but something wrong with the "java.lang.ArrayIndexOutOfBoundsException" which I used capital comment in my code to mark it out, ==> "if (brain[((int) board[x][y]) - 1])"
I checked it many times and I think the indexes should be perfectly fine within 0~8 by doing "for( int i = 0, i < 9; i++)" and I could not find the reason.
I guess this must be easy stupid question, but I kinda spend a lot of time to find it out. Can someone help me out?
BIG THANKS to whoever help!
public class Solution {
public boolean isValidSudoku(char[][] board) {
if (board.length > 9 || board[0].length > 9 || board == null) {
return false;
}
boolean[] brain;
// 9 digits are corresponding to 1 ~ 9 ==> 0 - 1, 1 - 2 ... 8 - 9
// ex: brain[2] is checking for digit "3" , so using brain[3-1] to check "3"
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
// THE NEXT LINE IS THE PROBLEM!!!
if (brain[((int) board[x][y]) - 1]) {
// my condition failed by using:
// brain[board[x][y] - 1]
// other's condition Partially passed by using
// (still failed for final submission:
// brain[(int) (board[x][y] - '1')]
// need to compare the difference
return false;
} else {
brain[((int) board[x][y]) - 1] = true;
}
}
}
}
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
if (brain[((int) board[y][x]) - 1]) {
return false;
} else {
brain[((int) board[y][x]) - 1] = true;
}
}
}
}
for (int block = 0; block < 9; block++) {
// Reset brain
brain = new boolean[9];
for (int r = block / 3 * 3; r < block / 3 * 3 + 3; r++) {
for (int c = block % 3 * 3; c < block % 3 * 3 + 3; c++) {
if (board[r][c] != '.') {
if (brain[((int) board[r][c]) - 1]) {
return false;
} else {
brain[((int) board[r][c]) - 1] = true;
}
}
}
}
}
return true;
}
}
You are trying to cast a char as int. Try to manually cast these values and you will notice that 0=48 and 9=57, which i guess should be the cause of your exception.
You might want to check if the value in there represents a number and get the numeric value of the char by using the Character#getNumericValue method.
if (Character.isDigit(board[x][y]) &&
brain[Character.getNumericValue(board[x][y])) - 1]) {
...
}
Related
I am writing an answer to a CCC question in java, but every time I input something it just takes infinite inputs. Can anyone help me stop this?
Your task is to write a program that verifies the validity of a well plan by verifying that the borehole will not intersect itself. A two-dimensional well plan is used to represent a vertical cross-section of the borehole, and this well plan includes some drilling that has occurred starting at (0, −1) and moving to (−1, −5). You will encode in your program the current well plan shown in the figure below:
Input Format:
The input consists of a sequence of drilling command pairs. A drilling command pair begins with one of four direction indicators (d for down, u for up, l for left, and r for right) followed by a positive length. There is an additional drilling command indicated by q (quit) followed by an integer, which indicates the program should stop the execution. You can assume that the input is such that the drill point will not:
rise above the ground, nor
be more than 200 units below ground, nor
be more than 200 units to the left of the original starting point, nor
be more than 200 units to the right of the original starting point.
Output Format:
The program should continue to monitor drilling assuming that the well shown in the figure has already been made. As we can see (−1, −5) is the starting position for your program. After each command, the program must output one line with the coordinates of the new position of the drill, and one of the two comments safe, if there has been no intersection with a previous position or DANGER if there has been an intersection with a previous borehole location. After detecting and reporting a self-intersection, your program must stop.
My code is:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> holeX = new ArrayList<>();
ArrayList<Integer> holeY = new ArrayList<>();
String direction;
boolean danger = false;
holeX.add(0);
holeX.add(0);
for (int i = 0; i < 4; i++) {
holeX.add(i);
}
holeX.add(3);
holeX.add(3);
holeX.add(4);
holeX.add(5);
holeX.add(5);
holeX.add(5);
holeX.add(6);
for (int i = -3; i > -8; i--) {
holeX.add(7);
}
for (int i = 6; i > -2; i--) {
holeX.add(i);
}
holeX.add(-1);
holeX.add(-1);
holeY.add(-1);
holeY.add(-2);
for (int i = 0; i < 4; i++) {
holeY.add(-3);
}
holeY.add(-4);
holeY.add(-5);
holeY.add(-5);
holeY.add(-5);
holeY.add(-4);
holeY.add(-3);
holeY.add(-3);
for (int i = -3; i > -8; i--) {
holeY.add(i);
}
for (int i = 6; i > -2; i--) {
holeY.add(-7);
}
holeY.add(-6);
holeY.add(-5);
do {
direction = sc.next();
int steps = sc.nextInt();
switch (direction) {
case "d":
for (int i = holeY.get(holeY.size() - 1); i > holeY.get(holeY.size() - 1) - steps; i--) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
case "u":
for (int i = holeY.get(holeY.size() - 1); i < holeY.get(holeY.size() - 1) + steps; i++) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
break;
case "l":
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
case "r":
for (int i = holeX.get(holeX.size() - 1); i < holeX.get(holeX.size() - 1) + steps; i++) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
default:
break;
}
if (danger == false && !"q".equals(direction)) {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + "safe");
System.out.print(" safe");
} else {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + " DANGER");
}
} while (!"q".equals(direction) && danger == false);
}
holeX and holeY are the coordinates of the drilled area.
Input:
l 2
d 2
r 1
q 0
Output:
-3 -5 safe
-3 -7 safe
-2 -7 safe
Well yes, you have an infinite loop. Let's take case "l" for example.
I used l and then 2.
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i)...
You add something to the list and the condition gets re-evaluated, which leads to an infinite loop.
I don't know if it is what you want to do, but what helps is to extract the condition first into a variable, then the infinite loop stops.
This question already has answers here:
Find elements surrounding an element in an array
(8 answers)
Closed 6 years ago.
I have a series of if statements, as shown below:
if (board[x+1][y]==true) {
ar+=1;
}
if (board[x][y+1]==true) {
ar+=1;
}
if (board[x-1][y]==true) {
ar+=1;
}
if (board[x][y-1]==true) {
ar+=1;
}
if (board[x+1][y+1]==true) {
ar+=1;
}
if (board[x+1][y-1]==true) {
ar+=1;
}
if (board[x-1][y+1]==true) {
ar+=1;
}
if (board[x-1][y-1]==true) {
ar+=1;
}
Is there a way to simplify/condense these statements with Java?
Simply loop around the position that you care about. Skipping the center of the "box".
Tip: You access a 2D array by row then column, or [y][x] (at least, that's how you'd translate the board from looking at the code).
// int x, y; // position to look around
for (int xDiff = -1; xDiff <= 1; xDiff++) {
for (int yDiff = -1; yDiff <= 1; yDiff++) {
if (xDiff == 0 && yDiff == 0) continue;
if (board[y+yDiff][x+xDiff]) {
ar += 1;
}
}
}
Beware - Out of bounds exception is not handled
The following would be a more visual equivalent, easily extensible to other shapes of the area of interest. Note ternary operators, ?: which are necessary in Java to convert bools to ints.
ar += (board[x-1][y-1]?1:0) + (board[x-1][y]?1:0) + (board[x-1][y+1]?1:0);
ar += (board[x+0][y-1]?1:0) + (board[x+0][y+1]?1:0);
ar += (board[x+1][y-1]?1:0) + (board[x+1][y]?1:0) + (board[x+1][y+1]?1:0);
In addition to the answers you already have, you can also use enhanced for loops (and re-use the range as it is the same for both).
int[] range = { -1, 0, 1 };
for (int i : range) {
for (int j : range) {
if ((i != 0 || j != 0) && board[i][j]) {
ar++;
}
}
}
This code should give the same result (probably you want to check that you are always in the bounds of the matrix
for(int i=-1; i<=1; i++) {
for(int j=-1; j<=1; j++) {
if((i != 0 || j != 0) && board[x+i][y+j]) {
ar++;
}
}
}
You can simplify as follows as well :
for(int i = x-1;i<=x+1;i++) {
for(int j=y-1;j<=y+1;j++) {
if(i==x && j==y) continue;
if (board[i][j]) {
ar+=1;
}
}
}
Looks like you're testing surrounding squares apart from (x, y) itself. I'd use a loop to maintain a counter, with extra step to exclude the (x, y) centre cell.
for (int xTest = x - 1; xTest <= x + 1; xTest++) {
for (int yTest = y - 1; yTest <= y + 1; yTest++) {
if (xTest == x && yTest == y) {
continue;
}
if (board[xTest][yTest]) {
ar += 1;
}
}
}
Also, note the == true is unnecessary. Boolean statements are first class citizens in Java.
The valid sudoku problem on Leetcode is solved, however, there is still a little question regarding the '.', which I fail to filter until I try another way.
Check out the comment parts regarding (1) & (2), (1) = the correct way to filter period by using continue; if '.' is found. (2) = is the wrong way which I used before, it will only allow digits to get passed for the following if statements.
Assume 1~9 digits and '.' will be the only inputs.
I just need someone to help me analyze the difference between these 2 ways, so I can learn from the mistakes.
Thank you for the help!
public class Solution {
public boolean isValidSudoku(char[][] board) {
if (board.length > 9 || board[0].length > 9 || board == null) {
return false;
}
boolean[] brain;
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
// ------- (1) Begin -------
if (board[x][y] == '.') {
continue;
}
if (brain[board[x][y] - '1']) {
return false;
} else {
brain[board[x][y] - '1'] = true;
}
// ------- (1) End -------
// statments (1) above is the correct one, I used to use code below:
/*
// ------- (2) Begin -------
if (board[x][y] != '.') {
if (brain[board[x][y] - '1']) {
return false;
} else {
brain[board[x][y] - '1'] = true;
}
}
// ------- (2) Begin -------
*/
// which failed for not filter out '.' properly
// so I changed to filter '.' out by using continue;
}
}
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[y][x] == '.') {
continue;
}
if (brain[board[y][x] - '1']) {
return false;
} else {
brain[board[y][x] - '1'] = true;
}
}
}
for (int block = 0; block < 9; block++) {
// Reset brain
brain = new boolean[9];
for (int r = block / 3 * 3; r < block / 3 * 3 + 3; r++) {
for (int c = block % 3 * 3; c < block % 3 * 3 + 3; c++) {
if (board[r][c] == '.') {
continue;
}
if (brain[board[r][c] - '1']) {
return false;
} else {
brain[board[r][c] - '1'] = true;
}
}
}
}
return true;
}
}
The two methods you use to skip dots on your Sudoku board are equivalent under the assumption that the digits 1 thru 9 and the dot are your only input.
I have tried to verify this with two different Sudoku boards, and both methods returned the same result. As I believe the two methods to do the same I think you will be hard pressed to find a board that shows differing results for each method.
i am try to implement 8 queen using depth search for any initial state it work fine for empty board(no queen on the board) ,but i need it to work for initial state if there is a solution,if there is no solution for this initial state it will print there is no solution
Here is my code:
public class depth {
public static void main(String[] args) {
//we create a board
int[][] board = new int[8][8];
board [0][0]=1;
board [1][1]=1;
board [2][2]=1;
board [3][3]=1;
board [4][4]=1;
board [5][5]=1;
board [6][6]=1;
board [7][7]=1;
eightQueen(8, board, 0, 0, false);
System.out.println("the solution as pair");
for(int i=0;i<board.length;i++){
for(int j=0;j<board.length;j++)
if(board[i][j]!=0)
System.out.println(" ("+i+" ,"+j +")");
}
System.out.println("the number of node stored in memory "+count1);
}
public static int count1=0;
public static void eightQueen(int N, int[][] board, int i, int j, boolean found) {
long startTime = System.nanoTime();//time start
if (!found) {
if (IsValid(board, i, j)) {//check if the position is valid
board[i][j] = 1;
System.out.println("[Queen added at (" + i + "," + j + ")");
count1++;
PrintBoard(board);
if (i == N - 1) {//check if its the last queen
found = true;
PrintBoard(board);
double endTime = System.nanoTime();//end the method time
double duration = (endTime - startTime)*Math.pow(10.0, -9.0);
System.out.print("total Time"+"= "+duration+"\n");
}
//call the next step
eightQueen(N, board, i + 1, 0, found);
} else {
//if the position is not valid & if reach the last row we backtracking
while (j >= N - 1) {
int[] a = Backmethod(board, i, j);
i = a[0];
j = a[1];
System.out.println("back at (" + i + "," + j + ")");
PrintBoard(board);
}
//we do the next call
eightQueen(N, board, i, j + 1, false);
}
}
}
public static int[] Backmethod(int[][] board, int i, int j) {
int[] a = new int[2];
for (int x = i; x >= 0; x--) {
for (int y = j; y >= 0; y--) {
//search for the last queen
if (board[x][y] != 0) {
//deletes the last queen and returns the position
board[x][y] = 0;
a[0] = x;
a[1] = y;
return a;
}
}
}
return a;
}
public static boolean IsValid(int[][] board, int i, int j) {
int x;
//check the queens in column
for (x = 0; x < board.length; x++) {
if (board[i][x] != 0) {
return false;
}
}
//check the queens in row
for (x = 0; x < board.length; x++) {
if (board[x][j] != 0) {
return false;
}
}
//check the queens in the diagonals
if (!SafeDiag(board, i, j)) {
return false;
}
return true;
}
public static boolean SafeDiag(int[][] board, int i, int j) {
int xx = i;
int yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy++;
xx++;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy--;
xx--;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy--;
xx++;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy++;
xx--;
}
return true;
}
public static void PrintBoard(int[][] board) {
System.out.print(" ");
for (int j = 0; j < board.length; j++) {
System.out.print(j);
}
System.out.print("\n");
for (int i = 0; i < board.length; i++) {
System.out.print(i);
for (int j = 0; j < board.length; j++) {
if (board[i][j] == 0) {
System.out.print(" ");
} else {
System.out.print("Q");
}
}
System.out.print("\n");
}
}
}
for example for this initial state it give me the following error:
Exception in thread "main" java.lang.StackOverflowError
i am stuck, i think the error is infinite call for the method how to solve this problem.
any idea will be helpful,thanks in advance.
note:the broad is two dimensional array,when i put (1) it means there queen at this point.
note2:
we i put the initial state as the following it work:
board [0][0]=1;
board [1][1]=1;
board [2][2]=1;
board [3][3]=1;
board [4][4]=1;
board [5][5]=1;
board [6][6]=1;
board [7][1]=1;
[EDIT: Added conditional output tip.]
To add to #StephenC's answer:
This is a heck of a complicated piece of code, especially if you're not experienced in programming Java.
I executed your code, and it outputs this over and over and over and over (and over)
back at (0,0)
01234567
0
1 Q
2 Q
3 Q
4 Q
5 Q
6 Q
7 Q
back at (0,0)
And then crashes with this
Exception in thread "main" java.lang.StackOverflowError
at java.nio.Buffer.<init>(Unknown Source)
...
at java.io.PrintStream.print(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at Depth.eightQueen(Depth.java:56)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
...
My first instinct is always to add some System.out.println(...)s to figure out where stuff is going wrong, but that won't work here.
The only two options I see are to
Get familiar with a debugger and use it to step through and analyze why it's never stopping the loop
Break it down man! How can you hope to deal with a massive problem like this without breaking it into digestible chunks???
Not to mention that the concept of 8-queens is complicated to begin with.
One further thought:
System.out.println()s are not useful as currently implemented, because there's infinite output. A debugger is the better solution here, but another option is to somehow limit your output. For example, create a counter at the top
private static final int iITERATIONS = 0;
and instead of
System.out.println("[ANUMBERFORTRACING]: ... USEFUL INFORMATION ...")
use
conditionalSDO((iITERATIONS < 5), "[ANUMBERFORTRACING]: ... USEFUL INFORMATION");
Here is the function:
private static final void conditionalSDO(boolean b_condition, String s_message) {
if(b_condition) {
System.out.println(s_message);
}
}
Another alternative is to not limit the output, but to write it to a file.
I hope this information helps you.
(Note: I edited the OP's code to be compilable.)
You asked for ideas on how to solve it (as distinct from solutions!) so, here's a couple of hints:
Hint #1:
If you get a StackOverflowError in a recursive program it can mean one of two things:
your problem is too "deep", OR
you've got a bug in your code that is causing it to recurse infinitely.
In this case, the depth of the problem is small (8), so this must be a recursion bug.
Hint #2:
If you examine the stack trace, you will see the method names and line numbers for each of the calls in the stack. This ... and some thought ... should help you figure out the pattern of recursion in your code (as implemented!).
Hint #3:
Use a debugger Luke ...
Hint #4:
If you want other people to read your code, pay more attention to style. Your indentation is messed up in the most important method, and you have committed the (IMO) unforgivable sin of ignoring the Java style rules for identifiers. A method name MUST start with a lowercase letter, and a class name MUST start with an uppercase letter.
(I stopped reading your code very quickly ... on principle.)
Try to alter your method IsValid in the lines where for (x = 0; x < board.length - 1; x++).
public static boolean IsValid(int[][] board, int i, int j) {
int x;
//check the queens in column
for (x = 0; x < board.length - 1; x++) {
if (board[i][x] != 0) {
return false;
}
}
//check the queens in row
for (x = 0; x < board.length - 1; x++) {
if (board[x][j] != 0) {
return false;
}
}
//check the queens in the diagonals
if (!SafeDiag(board, i, j)) {
return false;
}
return true;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm trying to learn a little bit more about recursion but somehow I can't solve the knight's tour and I'm hoping someone can point out my logic error.
class main {
static int fsize = 5; // board size (5*5)
static int board[][] = new int[fsize][fsize];
static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)
// x = current x coordinate
// y = current y coordinate
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
// check whether the knight has been on all filds or not
if (move_number == ((fsize * fsize) - 1)) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
System.out.printf("%3d", board[i][c]);
}
System.out.println("\n");
}
}
else {
// calculate new board coordinates
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 8; c++) {
// Check whether the new coordinates are valid or not
if ((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize && (y + move_y[c]) >= 0 && (y + move_y[c]) < fsize) {
// check whether the knight has been on this field or not (-1 = hasn't been here)
if (board[x + move_x[i]][y + move_y[c]] == -1) {
System.out.println("Move: " + move_number + "\n");
// Find next field
Solve(move_number + 1, (x + move_x[i]), (y + move_y[c]));
}
}
}
}
// couldn't find a valid move
board[x][y] = -1;
}
}
public static void main(String[] args) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
board[i][c] = -1;
}
}
Solve(0, 0, 0);
}
}
Edit: hope this is ok. I tried to run this program but couldn't get more than 22 valid moves.
I was able to fix your code by doing two things:
Only use for (int i = 0; i < 8; i++) single-level loop to check for the next 8 possibilities
Why do you have two nested loops here? You just want to check those 8 possibilities, that's it.
There are only 8 moves at each level, not 64
Make board[x][y] = -1; the last statement in Solve
You want this executed regardless of the if conditions
You HAVE to undo board[x][y] = move_number; before you exit from this level
After fixing those, your homework is done, correct, finished. Congratulations!
In pseudocode
Right now, this is what you have:
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
if (DONE) {
PRINT;
} else {
for (int i = 0; i < 8; i++) {
for (int c = 0; c < 8; c++) {
ATTEMPT_MOVE(i, c); // doesn't make sense!!!
}
}
board[x][y] = -1; // this doesn't belong here!!!
}
}
To fix this code, you just have to do this:
static void Solve(int move_number, int x, int y) {
board[x][y] = move_number;
if (DONE) {
PRINT;
} else {
for (int i = 0; i < 8; i++) {
ATTEMPT_MOVE(i); // now makes more sense!
}
}
board[x][y] = -1; // must undo assignment in first line!
}
Extra suggestions
Break down logic into helper methods, i.e. board printing, and checking for valid coordinates
Here's the thing - you are trying different valid moves even if the first attempted move was successful (led to a solution). I would make the function return a boolean value that specifies whether it reached a solution. So when you call the function from itself you should only try the next valid move if it returned false. Also, when you try a different move, you should clear the previous move (since the array was changed).
Edit:
class main {
static int fsize = 5; // board size (5*5)
static int board[][] = new int[fsize][fsize];
static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)
// x = current x coordinate
// y = current y coordinate
static boolean solve(int move_number, int x, int y)
{
boolean ret = true;
board[x][y] = move_number;
if(move_number == ((fsize * fsize) - 1))
{
for(int i = 0; i < fsize; i++)
{
for(int c = 0; c < fsize; c++)
{
System.out.printf("%3d", board[i][c]);
}
System.out.println("\n");
}
}
else
{
for(int i = 0; i < 8; i++)
{
if((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize
&& (y + move_y[i]) >= 0
&& (y + move_y[i]) < fsize)
{
if(board[x + move_x[i]][y + move_y[i]] == -1)
{
if (solve(move_number + 1, (x + move_x[i]), (y + move_y[i]))) {
break;
}
}
}
}
ret = false;
board[x][y] = -1;
}
return ret;
}
public static void main(String[] args) {
for (int i = 0; i < fsize; i++) {
for (int c = 0; c < fsize; c++) {
board[i][c] = -1;
}
}
solve(0, 0, 0);
}
}
This returns:
0 15 20 9 24
19 10 23 14 21
16 1 18 5 8
11 6 3 22 13
Hm, so I gave it a shot and tried to figure out what's going on. Here is what I could gather.
sprung_x and sprung_y are supposed to be moved together as they represent the movement of a Knight. You have c and i as the independent indices for moving over those arrays, but really it should be just 1 variable. I struck the inner for loop and used i everywhere I saw c.
At the end of your method SucheWeg you are resetting the cell you invoked it on back to -1. This caused the infinite loop for me. Removing that line allowed it to complete normally in 19 moves at cell 1, 2. According to the definition of Knight's Tour, that is 1 attack move away from the cell you started at (0, 0) and so represents a complete tour.
Your fsize of 5 may not complete, according to Wikipedia. I used 6 instead for testing.
You need to account for what will happen when you reach the very end. In your code, on the last step there is a print out, but the method SucheWeg will still continue running, and it needs a way to terminate normally. You have to allow for unrolling of decisions if you hit a dead end (what I assume the -1 reset is from #2) but also realize that the same unrolling will make it go forever if you aren't careful. **When you return from the method, you should check that the board is not full before undoing steps. If it is full, you reached the end.
Just to show you the code I used:
static boolean isFull(int b [][])
{
for(int i = 0; i < b.length; i++)
{
for(int k = 0; k < b[i].length; k++)
{
if(b[i][k] == -1) return false;
}
}
return true;
}
static void SucheWeg(int schrittnummer, int x, int y)
{
board[x][y] = schrittnummer;
if(schrittnummer == ((fsize * fsize) - 1)) return;
for(int i = 0; i < 8; i++)
{
int nextX = x + sprung_x[i];
int nextY = y + sprung_y[i];
// if we can visit the square, visit it
if(nextX >= 0 && nextX < fsize && nextY >= 0 && nextY < fsize)
{
if(board[nextX][nextY] == -1)
{
SucheWeg(schrittnummer + 1, nextX, nextY);
}
}
}
if(isFull(board)) return; // this is how we avoid resetting to -1
board[x][y] = -1; // reset if you get this far, so you can try other routes
}
Then in main I printed it out for us:
for(int i = 0; i < fsize; i++)
{
for(int c = 0; c < fsize; c++) System.out.format("%02d ", board[i][c]);
System.out.println("");
}
And the output is:
00 33 28 17 30 35
27 18 31 34 21 16
32 01 20 29 10 05
19 26 11 06 15 22
02 07 24 13 04 09
25 12 03 08 23 14
I would like to say one last thing - a good implementation of this algorithm would catch the infinite loops. If this is in fact homework, you should modify it until you can run it on any size board without worrying about infinite loops. Currently if there is no solution, it may run forever.
Since it looks a little like a homework question, I'll just start with a hint.
move_x and move_y are the possible x, y moves by the knight. However, these can be indexed independently (i and c). You may wish to reconsider that.