java:generalized 8 queen to work for any initial state using depth first search [duplicate] - java

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;
}

Related

For-loop involved in Diagonal Check for Connect Four

So I am currently coding Connect 4 on Netbeans. I have the vertical and horizontal check already made but I am having trouble with the diagonal check, specifially the for loops. Currently my code for this,
public static boolean checkDiagnol(String[][] board, int counter, String playerMoving, int lastPlacedTileRow, int col) {
for (int i = lastPlacedTileRow-1; q = col-1; i >= 0, q >=0; i--,q--){
if (board[i][q] == playerMoving) {
counter += 1;
} else {
break;
}
if (counter > 4) {
return true;
}
}
for (int i = lastPlacedTileRow + 1, q = col +1; i < board.length, q < board[0].length; i++,q++) {
if (board[i][q] == playerMoving) {
counter += 1;
} else {
break;
}
if (counter > 4) {
return true;
}
}
return false;
}
lastPlacedTileRow is the row of the last placed tile, col is the column chosen by the user, counter is a counter used to check if there are 4 tiles in a row, and playerMoving is the current players tile.
The current problem I have is that my for loops give errors. This is my first time using two variables in a single for loop so I am not sure how it is supose to be arranged.
Thanks for the help
Syntax
You have put a semicolon instead of a comma in the first for loop.
for (int i = lastPlacedTileRow-1; q = col-1; i >= 0, q >=0; i--,q--){
this should be
for (int i = lastPlacedTileRow-1, q = col-1; i >= 0, q >=0; i--,q--){
Logic
I think variable i should be counted down (or up) in both the loops because we have to check below the lastPlacedTileRow in both cases.

Explanation of 8-Queen solution Java code.

I found a 8-Queen solution that I was able to compile and run in Eclipse. I believe this solution follows the backtracking approach and meat of the work is done in the solution and unsafe functions, but I am having a hard time understanding the code paths in there. Can someone please help me understand what this code is doing.
My Source - http://rosettacode.org/wiki/N-queens_problem#Java
I verified the output against the 92 solutions published on other sources. Looks good. So I know the code works.
I have tried to format it and add some basic notes to clear things up -
private static int[] b = new int[8];
private static int s = 0;
public static void main(String[] args) {
// solution from - http://rosettacode.org/wiki/N-queens_problem#Java
new QueenN();
}
public QueenN() {
solution();
}
public void solution() {
int y = 0;
b[0] = -1;
while (y >= 0) {
do {
b[y]++;
} while ((b[y] < 8) && unsafe(y));
if (b[y] < 8) {
if (y < 7) {
b[++y] = -1;
} else {
putboard();
}
} else {
y--;
}
}
}
// check if queen placement clashes with other queens
public static boolean unsafe(int y) {
int x = b[y];
for (int i = 1; i <= y; i++) {
int t = b[y - i];
if (t == x || t == x - i || t == x + i) {
return true;
}
}
return false;
}
// printing solution
public static void putboard() {
System.out.println("\n\nSolution " + (++s));
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
if (b[y] == x)
System.out.print("|Q");
else
System.out.print("|_");
}
System.out.println("|");
}
}
End.
Let's try to understand the code step by step. First of all, we call the function solution(), which is what leads to the execution of the puzzle answer.
Solution funcion:
public void solution() {
int y = 0;
b[0] = -1;
while (y >= 0) {
do {
b[y]++; //if last cell was unsafe or we reached the end of the board, we go for the next row.
} while ((b[y] < 8) && unsafe(y)); //Checks whether it's the last cell and if it's an unsafe cell (clashing)
if (b[y] < 8) { //We found a safe cell. Hooray!
if (y < 7) { //Did we place the last queen?
b[++y] = -1; //Nope, let's allocate the next one.
} else {
putboard(); //Yup, let's print the result!
}
} else { //If not a single safe cell was found, we reallocate the last queen.
y--;
}
}
}
On the first while, you're going to iterate through each cell in a row (or column, however you prefer it. It's just a rotation matter). On each cell you make the unsafe(y) check, which will return true in case the cell you're placing the queen in is clashing with other queen-occupied cells (as you've already found out in the comment).
Next step, once we've found a safe cell in which to place the actual queen (y), we make a security check: if we have not found a single safe cell for that queen, we have to reallocate last queen.
In case the cell was found and was correct, we check whether it was the last queen (y < 7). If it is so, we proceed to print the result. Otherwise, we just re-start the while loop by placing b[++y] = -1.
Unsafe function:
public static boolean unsafe(int y) {
int x = b[y]; //Let's call the actual cell "x"
for (int i = 1; i <= y; i++) { //For each queen before placed BEFORE the actual one, we gotta check if it's in the same row, column or diagonal.
int t = b[y - i];
if (t == x || t == x - i || t == x + i) {
return true; //Uh oh, clash!
}
}
return false; //Yay, no clashes!
}
This function checks whether the queen we're using clashes with any of the allocated queens before this one. The clashes might happen diagonally, vertically or horizontally: That is why there is a triple OR check before the "return true" statement.
Putboard function:
public static void putboard() {
System.out.println("\n\nSolution " + (++s));
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
if (b[y] == x)
System.out.print("|Q");
else
System.out.print("|_");
}
System.out.println("|");
}
}
I'm not gonna explain this one that deep, because it is simply a fairly simply line printing function which you can find out how it works by yourself when executing the solution!
Hope this helps.
Cheers!

Java 2D Array manipulation

I have to modify the below method:
private final static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
}
This method checks if it's a even number and if so it replaces its value with 0. Simple.
I now need to modify it so that it directs each cell to simultaneously replace its value with its number of diagonal neighbors that hold a value of 0.
I've thought about this for about an hour and tried many different solutions, most of which resulted in an out of bounds exception. I'm stumped and don't know how to accomplish this.
If the code is right, using the integers for the grid array below, it will reproduce the numbers shown in the bottom of the picture.
What is the problem, you just need to put if statements, like there can be maximum 4 possible neighbors so check that how many are equal to 0. But this is not enough you just need to add one more condition in each of the if statements. The condition would be that the neighbor you are trying to check is possible or not.
That is: Total 4 neighbors. If the coordinates of your main cell are x, y then:
1st Diagonal neighbor: x-1, y-1
2nd Diagonal neighbor: x-1, y+1
3rd Diagonal neighbor: x+1, y+1
4th Diagonal neighbor: x+1, y-1
These are all the 4 diagonal neighbors' coordinates but the last thing you need to check is whether they go out of bonds or not. For example for checking the 1st Diagonal neighbor I would do:
if((x-1)>0 && (y-1)>0){
//and then check here if that block is = `0`
}
and for other having say x+1 or y+1 you will need to check whether or not they are less than the NUM. Like if I want to check the 3rd Diagonal Neighbor:
if((x+1)<NUM && (y+1)<NUM){
//and then check here if that block is = `0`
}
Update: What do you mean by check here if that block is = 0?
If you want to check that is the diagonal neighboring blocks are equal to 0 or not then you will need to do it in a loop. Here is how:
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
for(row = 0; row< NUM; row++){
for(int col = 0; col < NUM; col++) {
int count = 0;
// To check for the 1st Diagonal Neighbor
if((row-1)>0 && (col-1)>0){
if(grid[row-1][col-1]==0){
count++;
}
}
//Similarly for 2nd, 3rd and 4th Diagonal Neighbors
//and then
grid[row][col]=count;
}
}
}
Update 2:
For say the 3rd diagonal neighbor the code block would be like this:
if((row+1)<NUM && (col+1)<NUM){
if(grid[row+1][col+1]==0){
count++;
}
}
Answer
final private static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
int counter = 0;
if((row - 1) > 0 && (col - 1) > 0) {
if(grid[row - 1][col - 1] == 0) {
counter++;
}
}
if((row - 1) > 0 && (col + 1) < NUM) {
if(grid[row - 1][col + 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col - 1) > 0) {
if(grid[row + 1][col - 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col + 1) < NUM) {
if(grid[row + 1][col + 1] == 0) {
counter++;
}
}
grid[row][col] = counter;
}
}
}

Detect Infinite Loop?

I'm working on a Sudoku solver program. The idea is that the user inputs the Sudoku puzzle and the program solves it for them.
The program works fine when entering any normal puzzle. However, there are some puzzles that are impossible to solve. Here is one example that I entered: http://i.imgur.com/5L8pF8Q.png
The input is perfectly legal, but top right square cannot be filled in since all numbers 1-9 have been used in that row and column.
If I hit "Solve", my program freezes as it enters an infinite loop.
So my question here is, how can I prevent this from happening?
I tried implementing the "boolean flag" approach, but on second thought I realized that it's probably not feasible.
Here is my solver method:
public boolean solve(int i, int j) {
for (int a = 0; a < 9; a++) {
for (int b = 0; b < 9; b++) {
if (sudokuArray[a][b] == 0) {
for (int k = 1; k <= 9; k++) {
sudokuArray[a][b] = k;
if (checkNumber(a, b, k) && solve(a, b)) {
return true;
}else {
sudokuArray[a][b] = 0;
}
}
return false;
}
}
}
return true;
}
The checkNumber() method checks if number k can be legally inserted in row a, column b and returns true/false accordingly.
Ideas? Tips?
Thanks.
PS: Added checkNumber() as requested:
public boolean checkNumber(int i, int j, int num) {
for (int a = 0; a < 9; a++) {
if (a != i) {
if (sudokuArray[a][j] == num) {
return false;
}
}
if (a != j) {
if (sudokuArray[i][a] == num) {
return false;
}
}
}
for (int a = (i / 3) * 3; a < (i / 3) * 3 + 3; a++) {
for (int b = (j / 3) * 3; b < (j / 3) * 3 + 3; b++) {
if ((a != i) && (b != j)) {
if (sudokuArray[a][b] == num) {
return false;
}
}
}
}
return true;
}
This is just an idea (i would comment but this account is too new). Try making it so that if all numbers from 0-9 return false, then it returns an error of some sort. For example if it hasn't found an answer by 9, then move up to 10. If the program detects a 10, do some kind of System.out.println("Unsolvable") or something along those lines. Sorry if I'm confusing you by the way. I've been told I'm bad at explaining things.

Ascii Art with Java - Creating a square/rectangle with different symbolled edges

I'm working to printout ascii art which takes two integers entered from the console then displays a rectangle or square from those two integers (the then dimensions). But the corners need to be a different symbol then the main symbol... yet the trick is that the short side has to have only 1 or 2 of the original symbols on it (due to odd or even.)
Here are two examples:
6x9:
001111100
011111110
111111111
111111111
011111110
001111100
9x6:
001100
011110
111111
111111
111111
111111
111111
011110
001100
I've gotten this far (since the console only goes from 0 to 9 right?)
What would need to be added to take in account the corners?
Would an If statement work or something else?
And yes, I know this is only for the "square". How would I add a second dimension? Can I get some help?
class Main {
public static void printSquare(int size) {
if(size > 9) {
size = 9;
}
int line = 1;
while (line <= size) {
int width = size;
int i = 1;
while (i <= width) {
System.out.print("*");
i = i + 1;
}
System.out.println(); // Newline
line = line + 1;
}
}
}
You need to simply tell it that the three corner symbols are different.
Scanner keys = new Scanner(System.in);
int x = 0;
int y = 0;
public void getInput() {
x = keys.nextInt();
y = keys.nextInt();
createart();
}
public void createart() {
System.out.print("00");
int counter = 0;
while (counter < x - 4) {
System.out.print(1);
counter++;
}
System.out.println("00");
counter = 0;
System.out.print("0");
while (counter < x - 2) {
System.out.print(1);
counter++;
}
System.out.print("0");
counter = 0;
int counter2 = 0;
while (counter < y - 4) {
System.out.println("");
while (counter2 < x) {
System.out.print(1);
counter2++;
}
counter++;
}
System.out.println("");
counter = 0;
while (counter < x - 2) {
System.out.print(1);
counter++;
}
counter = 0;
System.out.println("0");
System.out.print("00");
while (counter < x - 4) {
System.out.print(1);
counter++;
}
System.out.print("00");
}
Simple logic.

Categories