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.
Related
I have this question I am trying to solve. I have tried coding for the past 4 hours.
An integer is defined to be a Smart number if it is an element in the infinite sequence
1, 2, 4, 7, 11, 16 …
Note that 2-1=1, 4-2=2, 7-4=3, 11-7=4, 16-11=5 so for k>1, the kth element of the sequence is equal to the k-1th element + k-1. For example, for k=6, 16 is the kth element and is equal to 11 (the k-1th element) + 5 ( k-1).
Write function named isSmart that returns 1 if its argument is a Smart number, otherwise it returns 0. So isSmart(11) returns 1, isSmart(22) returns 1 and isSmart(8) returns 0
I have tried the following code to
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = isSmart(11);
System.out.println(x);
}
public static int isSmart(int n) {
int[] y = new int[n];
int j = 0;
for (int i = 1; i <= n; i++) {
y[j] = i;
j++;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i <= y.length; i++) {
int diff = 0;
y[j] = y[i+1] - y[i] ;
y[i] = diff;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
When I test it with 11 it is giving me 0 but it shouldn't. Any idea how to correct my mistakes?
It can be done in a simpler way as follows
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
int x = isSmart(11);
System.out.println("Ans: "+x);
}
public static int isSmart(int n) {
//------------ CHECK THIS LOGIC ------------//
int[] y = new int[n];
int diff = 1;
for (int i = 1; i < n; i++) {
y[0] =1;
y[i] = diff + y[i-1];
diff++;
}
//------------ CHECK THIS LOGIC ------------//
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
One of the problems is the way that your populating your array.
The array can be populated as such
for(int i = 0; i < n; i++) {
y[i] = (i == 0) ? 1 : y[i - 1] + i;
}
The overall application of the function isSmart can be simplified to:
public static int isSmart(int n) {
int[] array = new int[n];
for(int i = 0; i < n; i++) {
array[i] = (i == 0) ? 1 : array[i - 1] + i;
}
for (int i = 0; i < array.length; i++) {
if (array[i] == n) return 1;
}
return 0;
}
Note that you don't need to build an array:
public static int isSmart(int n) {
int smart = 1;
for (int i = 1; smart < n; i++) {
smart = smart + i;
}
return smart == n ? 1 : 0;
}
Here is a naive way to think of it to get you started - you need to fill out the while() loop. The important thing to notice is that:
The next value of the sequence will be the number of items in the sequence + the last item in the sequence.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
System.out.println(isSmart(11));
}
public static int isSmart(int n) {
ArrayList<Integer> sequence = new ArrayList<Integer>();
// Start with 1 in the ArrayList
sequence.add(1);
// You need to keep track of the index, as well as
// the next value you're going to add to your list
int index = 1; // or number of elements in the sequence
int nextVal = 1;
while (nextVal < n) {
// Three things need to happen in here:
// 1) set nextVal equal to the sum of the current index + the value at the *previous* index
// 2) add nextVal to the ArrayList
// 3) incriment index by 1
}
// Now you can check to see if your ArrayList contains n (is Smart)
if (sequence.contains(n)) { return 1; }
return 0;
}
}
First think of a mathematical solution.
Smart numbers form a sequence:
a0 = 1
an+1 = n + an
This gives a function for smart numbers:
f(x) = ax² + bx + c
f(x + 1) = f(x) + x = ...
So the problem is to find for a given y a matching x.
You can do this by a binary search.
int isSmart(int n) {
int xlow = 1;
int xhigh = n; // Exclusive. For n == 0 return 1.
while (xlow < xhigh) {
int x = (xlow + xhigh)/2;
int y = f(x);
if (y == n) {
return 1;
}
if (y < n) {
xlow = x + 1;
} else {
xhigh = x;
}
}
return 0;
}
Yet smarter would be to use the solution for x and look whether it is an integer:
ax² + bx + c' = 0 where c' = c - n
x = ...
I was playing around with this and I noticed something. The smart numbers are
1 2 4 7 11 16 22 29 ...
If you subtract one you get
0 1 3 6 10 15 21 28 ...
0 1 2 3 4 5 6 7 ...
The above sequence happens to be the sum of the first n numbers starting with 0 which is n*(n+1)/2. So add 1 to that and you get a smart number.
Since n and n+1 are next door to each other you can derive them by reversing the process.
Take 29, subtract 1 = 28, * 2 = 56. The sqrt(56) rounded up is 8. So the 8th smart number (counting from 0) is 29.
Using that information you can detect a smart number without a loop by simply reversing the process.
public static int isSmart(int v) {
int vv = (v-1)*2;
int sq = (int)Math.sqrt(vv);
int chk = (sq*(sq+1))/2 + 1;
return (chk == v) ? 1 : 0;
}
Using a version which supports longs have verified this against the iterative process from 1 to 10,000,000,000.
I have the following problem I can't figure out on my own.
There is a 2D array with 8x8 dimensions. A dog is randomly put within this dimension. The dog is not allowed to walk out of the dimension, if it does those steps are not counted. Every step the dog takes to another square is counted. Each simulation should calculate the number of overall steps it took for the dog to visit all squares of the 8x8 dimension at least once.
How do I know if all 64 squares got stepped at least once to stop the simulation and print the steps?
int [] [] onSquare = new int [8][8];
int counter = 0;
int x = rnd.nextInt(8); // random position for the dog 0-7
int y = rnd.nextInt(8);
for (int i = 0; i < onSquare.length; i++) {
for (int j = 0; j < onSquare.length; j++) {
onSquare [i] [j] = -1; // dog is on no square in beginning
}
while (onSquare[i][j] == -1) {
int dog = rnd.nextInt(4)+1; // random movement from dog
if (dog == 1) {
x++; // x,y show position of the dog
counter++; // number of steps
if (onSquare[i][j] == onSquare[x][y]) { <---- This gives me errors when checking if x,y lies within i,j
onSquare[i][j] = 1; // stepped on square
}
}
if (dog == 2) {
x--;
counter++;
onSquare[i][j] = 1;
}
if (dog == 3) {
y++;
counter++;
onSquare[i][j] = 1;
}
if (dog == 4) {
y--;
counter++;
onSquare[i][j] = 1;
}
if (x < 0 || y < 0 || x > onSquare.length || y > onSquare.length) {
counter++;
onSquare[i][j] = 0;
}
}
}
use a steps counter to keep track of movement, for each movement, increment its value.
instead of using boolean array, use int array for tracking cells traversed.
int [] [] onSquare = new int [8] [8];
initialize all the cell to have -1 , indicating no dog movement to the cell yet.
for(int i = 0 ; i < 8; i++ )
for(int j = 0; j < 8 ; j++ )
onSquare[i][j]=-1;
when dog enters it, assign its value to 1 , indicating presence of dog
when dog exits, assign its value to 0, indicating absence of dog
once all cell have non-negative value, stop the simulation and display the value of steps counter!!
Edit: since you are struggling to solve , here is the complete code:
/**
* This simulation assumes dog movement is discrete relative to grid cells
* i.e. its either in one of these cells at a time, overlapping two cells in not allowed!!
* **/
public class DogMovementSimulation
{
int onBoard[][] = null;
int dogPosX = 0;
int dogPosY = 0;
int dogPrevPosX = 0;
int dogPrevPosY = 0;
int directionOfMovement = 0;
int stepsCount = 0;
DogMovementSimulation()
{
onBoard = new int[8][8];
//initialize each position in onBoard to -1 ,implying dog has not been placed yet, not even once!!
for( int i = 0 ; i < 8 ; i++ )
{
for( int j = 0 ; j < 8 ; j++ )
{
onBoard[i][j] = -1;//implying dog has not been placed yet, not even once!!
}
}
//place dog in random cell
dogPosX = (int)Math.round(Math.random()*7);//generating random number between 0 and 7, since index is from 0 to 7 as there are 8 cell!!
dogPosY = (int)Math.round(Math.random()*7);
//assigning 1 to onBoard at index dogPosX,dogPosY to indicate dog has been placed there
onBoard[dogPosX][dogPosY] = 1;
}
/*this function returns false if any cell has -1,else true
* cause when all cells have been traversed , each cell have non negative value,either 0 or 1
* */
public boolean areAllCellsTraversed()
{
boolean result = true;
for( int i = 0 ; i < 8 ; i++ )
{
for( int j = 0 ; j < 8 ; j++ )
{
if( onBoard[i][j] == -1 )//implying this cell not traversed yet,i.e dog not placed in this cell yet!!
{
result = false;
}
}
}
return result;
}
public void simulate()
{
//loop while all cells have been not traversed
while( !areAllCellsTraversed() )
{
directionOfMovement = (int)Math.round(Math.random()*3);//generating random number between 0 and 3
switch( directionOfMovement )
{
case 0://move left-to-right
dogPosX += 1;
if( dogPosX >= 7 ) dogPosX = 0; //since largest array index is 1 less than its size, we compare with 7 instead of 8
break;
case 1://move right-to-left
dogPosX -= 1;
if( dogPosX <= 0 ) dogPosX = 7;
break;
case 2://move top-to-bottom
dogPosY += 1;
if( dogPosY >= 7 ) dogPosY = 0;
break;
case 3://move bottom-to-top
dogPosY -= 1;
if( dogPosY <= 0 ) dogPosY = 7;
break;
}
//assign 0 to previous position, meaning dog is no longer there
onBoard[dogPrevPosX][dogPrevPosY] = 0;
//assign 1 to new position , meaning dog is here
onBoard[dogPosX][dogPosY] = 1;
stepsCount++;
dogPrevPosX = dogPosX;
dogPrevPosY = dogPosY;
}
//once all cells have been traversed , print result!!
printSteps();
}
/*prints the total number of step taken to traverse all cells*/
public void printSteps()
{
System.out.println("Total steps taken by dog to traverse all cell = "+stepsCount);
}
public static void main(String[] args)
{
DogMovementSimulation dms = new DogMovementSimulation();
dms.simulate();
}
}
Going to write this as a series of suggestions, otherwise I'd feel like I'm basically writing an assignment for you.
It sounds like you should get rid of dimension, since it isn't doing anything useful.
You should store the value 8 in a variable.
int size = 8;
It sounds like you're trying to both check when all squares have been visited, but also check how many steps were taken, including revisiting old squares. For this you will require two counters, not one.
int steps = 0;
int visited = 0;
You need bounds checking to make sure x and y don't go out of bounds.
if (dog == 1 && x < size - 1) {
x += 1;
steps += 1;
You need to check whether the dog has visited this location before. If he hasn't been here before, then increment the counter.
if (!onSquare[x][y]) {
onSquare[x][y] = true;
visited += 1;
}
You need to stop when you've visited every location.
while (visited < size * size) {
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]) {
...
}
I'm not sure, when I run this in eclipse it says . What's happening is, the input Y is a year that's less than 10000, and I have to find the next year after that one that has all different digits. For example, 2010 would print 2013 because 2013 is the next year after 2010 with all different digits.
package from1987To2013;
public class from1987To2013 {
public static void main(String[] args) {
//Y is year input
int Y = 2011;
//number of digits in Y
int length = String.valueOf(Y).length();
//Turns the Y into an int array arrayY
String temp = Integer.toString(Y);
int[] arrayY = new int[temp.length()];
for (int i = 0; i < temp.length(); i++)
{
arrayY[i] = temp.charAt(i) - '0';
}
//first for loop
for (int i = 0; i < 10000; i++) {
//find every value from Y to 10000
int a = Y + i;
//changes if its true or not
boolean bool = true;
//this loop goes through once if y = 2, twice if y = 33, thrice if y = 456, four times if y == 4666, etc
int d = 0;
for (int b = 0; b < length; b++)
//d is the b - 1 which will be compared with the position at b
d = b-1;
int b = 0;
//checks if they're all equal
if (arrayY[d] != (arrayY[b])) {
} else {
bool = false;
break;
}
if (bool = true){
System.out.print(a);
}
}
}
}
As well as changing the code as per #ZouZou's comment, I'm not quite sure why, but i had to change this line:
System.out.print(a);
to
System.out.println(a);
in order to get any output from eclipse.
p.s. your logic doesn't work, but at least this gives you output so you can debug it now.
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;
}