Given a 2 dimensional char array filled with 0's and 1 where 0 represents a wall and 1 represents a valid path, I have developed a recursive method called findPath(int r, int c) to find the exit in the maze marked with an 'x'. The method takes in the current row and column of the maze and goes through N,E,S,W directions until it finds a valid path and marks that valid path with a '+'. Given an instance where all directions are found to be blocked by a wall, the method then is suppose to backtrack until this is not the case anymore, and then marking that path traveled with an 'F' to symbolize the bad path.
Right now I can't figure out why the findPath method doesn't seem to transverse through all the directions as my display method just shows the program starting from the coordinates I pass in and not moving anywhere from there, why could this be?
Here is my Driver class
public class MazeMain2
{
public static void main(String[]args)
{
char[][] mazeArr = {{'0','0','0','1','0','0','0','0','0','0','0','0','0','0','0'},
{'0','0','0','1','0','0','0','0','1','0','0','0','0','1','0'},
{'0','0','0','1','1','1','1','1','1','1','1','1','0','0','0'},
{'0','0','0','1','0','0','0','0','0','0','0','1','0','0','0'},
{'0','0','0','1','1','1','1','1','0','0','0','1','0','0','0'},
{'0','0','0','0','0','0','0','1','0','0','0','1','0','0','0'},
{'0','0','0','0','1','1','1','1','0','0','0','1','0','0','0'},
{'0','0','0','0','1','0','0','1','0','0','0','1','0','1','0'},
{'0','0','0','0','1','0','0','1','0','0','0','0','0','0','0'},
{'0','0','0','0','1','0','0','0','0','0','0','0','0','0','0'},
{'0','0','0','0','1','1','1','1','1','1','1','0','0','0','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'},
{'0','0','0','0','0','1','0','0','0','0','1','1','1','1','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'}};
MazeSolver2 mazeS = new MazeSolver2(mazeArr);
mazeS.markEntry();
mazeS.markExit();
mazeS.solve(0, mazeS.start);
}
}
And here is my maze solver class with the findPath method
public class MazeSolver2
{
int start;
int exit;
char[][] maze;
public MazeSolver2(char[][] currentMaze)
{
maze = currentMaze;
}
//Finds where the first 1 is in the top row of the
//maze (entrance)
public void markEntry()
{
for(int x = 0; x < maze.length; x++)
{
if(maze[0][x] == '1')
{
maze[0][x] = 'E';
start = x;
}
}
}
//Finds where the last 1 is in the bottom row of the
//maze (exit)
public void markExit()
{
for(int x = 0; x < maze.length; x++)
{
if(maze[maze.length - 1][x] == '1')
{
maze[maze.length - 1][x] = 'x';
exit = x;
}
}
}
public void solve(int x, int y)
{
if(findPath(x, y))
{
System.out.println(maze[x][y]);
}
else
System.out.println("No solution");
}
public boolean findPath(int r, int c)
{
displayMaze(maze);
//Found the exit
if(maze[r][c] == 'x')
{
return true;
}
if(maze[r][c] == '0' || maze[r][c] == '+' || maze[r][c] == 'F')
{
return false;
}
maze[r][c] = '+';
//If row is currently at zero then don't check north
//direction because it will be outside of the maze
if(r <= 0)
{
if(findPath(r, c++))
{
return true;
}
if(findPath(r++, c))
{
return true;
}
if(findPath(r, c--))
{
return true;
}
}
else
{
//check N, E, S, W directions
if(findPath(r--, c) || findPath(r, c++) ||
findPath(r++, c) || findPath(r, c--))
{
return true;
}
}
//Marking the bad path
maze[r][c] = 'F';
return false;
}
//Displays maze
public void displayMaze(char[][] maze)
{
for(int row = 0; row < maze.length; row++)
{
for(int col = 0; col < maze.length; col++)
{
if(col == 14)
{
System.out.print(maze[row][col]);
System.out.println();
}
else
{
System.out.print(maze[row][col]);
}
}
}
System.out.println();
}
}
Your algorithm has several flow in itself, which I don't feel right to point out. You can search for maze traverse problems, and get many good tutorials.
However, give attention to the method calls. Notice that if findPath(int r, int c) get called with findPath(5, 5) then a call to findPath(r, c++) passes the values findPath(5, 5) again, not with findPath(5, 6).
Because in that case findPath(r, c++) get called with current value of c and after that c++ gets executed.
Same goes for findPath(r, c--) findPath(r++ , c) etc, etc.
A good idea to understand the fact is to print the values int r, int c at the starting of method findPath().
Also play a little with post increments/decrements(x++/--x) and pre increments/decrements(++x/--x).
Hope it helps.
Need a push in the right direction for a class assignment. I've read other posts that mentioned creating a variable/method to store the path traveled, but not sure how to get about it...
Edited 9/28/16
was able to get to the end point of the maze but still haven't figured out
how to print only the path taken; I really need to
import java.io.*;
import java.util.*;
public class Maze
{
private static int rows, cols, startRow, startCol, nextRow, nextCol;
private static int endRow = 3;
private static int endCol = 34;
private static char[][] mazeBoard;
//private static char start = 'S';
private static char end = 'E';
//private boolean finish = false;
private char[][] explored = new char[rows][cols];
//construct the maze board
public Maze() throws FileNotFoundException
{
Scanner in = new Scanner(new File("maze.txt"));
rows = in.nextInt();
cols = in.nextInt();
startRow = in.nextInt();
startCol = in.nextInt();
//fill out the mazeBoard
mazeBoard = new char[rows][cols];
int i = 0;
while (in.hasNextLine())
{
String inLine = in.nextLine();
if (inLine.isEmpty())
{
continue;
}
for (int j = 0;j < cols; j++)
{
char nextChar = inLine.charAt(j);
mazeBoard[i][j] = nextChar;
System.out.print(nextChar);
}
System.out.println();
i++;
}
in.close();
}
//updated the move method from void to boolean
public boolean move(int row, int col, int prevRow, int prevCol)
{
boolean finish = false;
prevRow = row;
prevCol = col;
//show location
System.out.println("row: " + row + " col: " + col);
//base case1 to check for out of bounds and not the previous position
if (row < 0 || col < 0 || row >= rows || col >= cols || row != prevRow || col != prevCol)
{ return false; }
//base case2 to see if reached exit/end point
if (row == endRow && col == endCol)
{
System.out.println("Found the exit!");
return true;
}
//base case3 to check for wall
if (mazeBoard[row][col] == '+' || mazeBoard[row][col] == '*')
{ return false; }
mazeBoard[row][col] = '*';
//try to move down
if (move(row + 1, col, prevRow, prevCol))
{ return true; }
//try to move right
if (move(row, col + 1, prevRow, prevCol))
{ return true; }
//try to move up
if (move(row - 1, col, prevRow, prevCol))
{ return true; }
//try to move left
if (move(row, col - 1, prevRow, prevCol))
{ return true; }
row = prevRow;
col = prevCol;
return false;
}
public static void main(String[] args) throws FileNotFoundException
{
Maze maze = new Maze();
maze.move(startRow, startCol);
}
}
====
so I'm not sure how to implement a method to keep track of path traveled, any pointers will be greatly appreciated!
The easy way is to wait until you find the solution. Then simply record the successful moves as you crawl back up that branch of the call tree. Each winning call prepends its move to the front of the return value and passes that back up the stack. This would be something like
result = move(rowM + 1, colM);
if result != ""
return "D" + result; // "D" for a move right
else {
// Try a move right ...
You do have a couple of things to fix. Most of all, you have to block taking a step you've already taken. Right now, when your search hits a dead end, it keeps repeating the final step and backtrack in an infinite recursion.
Second, you'll need to implement logic to abort other searches once you've found one solution. Setting a finish doesn't help much; that's a local variable, and you need to communicate to the calling program that you've failed or succeeded.
Is that enough to move you to the next step?
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;
}
I'm having trouble coding the 8 queens problem. I've coded a class to help me solve it, but for some reason, I'm doing something wrong. I kind of understand what's supposed to happen.
Also, we have to use recursion to solve it but I have no clue how to use the backtracking I've read about, so I just used it in the methods checking if a position is legitimate.
My board is String [] [] board = { { "O", "O"... etc etc with 8 rows and 8 columns.
If I'm getting anything wrong conceptually or making a grave Java mistake, please say so :D
Thanks!
public void solve () {
int Queens = NUM_Queens - 1;
while (Queens > 0) {
for (int col = 0; col < 8; col++) {
int row = -1;
boolean c = false;
while (c = false && row < 8) {
row ++;
c = checkPos (row, col);
}
if (c == true) {
board[row][col] = "Q";
Queens--;
}
else
System.out.println("Error");
}
}
printBoard ();
}
// printing the board
public void printBoard () {
String ret = "";
for (int i = 0; i < 8; i++) {
for (int a = 0; a < 8; a++)
ret += (board[i][a] + ", ");
ret += ("\n");
}
System.out.print (ret);
}
// checking if a position is a legitimate location to put a Queen
public boolean checkPos (int y, int x) {
boolean r = true, d = true, u = true, co = true;
r = checkPosR (y, 0);
co = checkPosC (0, x);
int col = x;
int row = y;
while (row != 0 && col != 0 ) { //setting up to check diagonally downwards
row--;
col--;
}
d = checkPosDD (row, col);
col = x;
row = y;
while (row != 7 && col != 0 ) { //setting up to check diagonally upwards
row++;
col--;
}
d = checkPosDU (row, col);
if (r = true && d = true && u = true && co = true)
return true;
else
return false;
}
// checking the row
public boolean checkPosR (int y, int x) {
if (board[y][x].contentEquals("Q"))
return false;
else if (board[y][x].contentEquals("O") && x == 7)
return true;
else //if (board[y][x].contentEquals("O"))
return checkPosR (y, x+1);
}
// checking the column
public boolean checkPosC (int y, int x) {
if (board[y][x].contentEquals("Q"))
return false;
else if (board[y][x].contentEquals("O") && y == 7)
return true;
else //if (board[y][x].contentEquals("O"))
return checkPosR (y+1, x);
}
// checking the diagonals from top left to bottom right
public boolean checkPosDD (int y, int x) {
if (board[y][x].contentEquals("Q"))
return false;
else if (board[y][x].contentEquals("O") && (x == 7 || y == 7))
return true;
else //if (board[y][x].contentEquals("O"))
return checkPosR (y+1, x+1);
}
// checking the diagonals from bottom left to up right
public boolean checkPosDU (int y, int x) {
if (board[y][x].contentEquals("Q"))
return false;
else if (board[y][x].contentEquals("O") && (x == 7 || y == 0))
return true;
else //if (board[y][x].contentEquals("O"))
return checkPosR (y-1, x+1);
}
}
As this is homework, the solution, but not in code.
Try to write a method that only handles what needs to happen on a single column; this is where you are supposed to use recursion. Do backtracking by checking if a solution exists, if not, undo your last change (i.e. change the queen position) and try again. If you only focus on one part of the problem (one column), this is much easier than thinking about all columns at the same time.
And as Quetzalcoatl points out, you are assigning false to your variable in the first loop. You probably do not want to do that. You should always enable all warnings in your compiler (run javac with -Xlint) and fix them.
You are trying some kind of brute-force, but, as you already mentioned, you have no recursion.
Your programs tries to put a queen on the first possible position. But at the end no solution is found. It follows that your first assumption (the position of your first queen) is invalid. You have to go back to this state. And have to assume that your checkPos(x,y) is false instead of true.
Now some hints:
As mentioned before by NPE int[N] queens is more suitable representation.
sum(queens) have to be 0+1+2+3+4+5+6+7=28, since a position has to be unique.
Instead of checking only the position of the new queen, you may check a whole situation. It is valid if for all (i,j) \in N^2 with queen(i) = j, there exists no (k,l) != (i,j) with abs(k-i) == abs(l-j)
So I have this university assignment to solve Sudoku... I read about Algorithm X and Dancing algorithm, but they didn't help me.
I need to make it with backtracking. I hard-coded some of the indexes in the two dimensional array with numbers on places given from Wikipedia (so I am sure that it's solvable).
The code I got is the following:
public void solveSudoku(int row, int col)
{
// clears the temporary storage array that is use to check if there are
// dublicates on the row/col
for (int k = 0; k < 9; k++)
{
dublicates[k] = 0;
}
// checks if the index is free and changes the input number by looping
// until suitable
if (available(row, col))
{
for (int i = 1; i < 10; i++)
{
if (checkIfDublicates(i) == true)
{
board[row][col] = i;
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
board[row][col] = 0;
}
}
}
// goes to the next row/col
else
{
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
}
}
/**
* Checks if the spot on the certain row-col index is free of element
*
* #param row
* #param col
* #return
*/
private boolean available(int row, int col)
{
if (board[row][col] != 0)
return false;
else
return true;
}
/**
* Checks if the number given is not already used in this row/col
*
* #param numberToCheck
* #return
*/
private boolean checkIfDublicates(int numberToCheck)
{
boolean temp = true;
for (int i = 0; i < dublicates.length; i++)
{
if (numberToCheck == dublicates[i])
{
temp = false;
return false;
}
else if (dublicates[i] == 0)
{
dublicates[i] = numberToCheck;
temp = true;
return true;
}
}
return temp;
}
I am getting StackOverflow on
// goes to the next row/col
else
{
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
}
which means that I have to stop the recursion at some point, but I can't figure it out how!
If you find any other mistakes in the solve() function - let me know. Because I am not sure I understand the "backtracking" thing completely...
You can stop recursion for example if you keep track of the current recursion depth
public void solveSudoku(int row, int col, int recursionDepth) {
// get out of here if too much
if (recursionDepth > 15) return;
// regular code...
// at some point call self with increased depth
solveSudoku(0, col + 1, recursionDepth + 1);
}
And if you find any other mistakes in the solve() function - let me know.
Too much code :)
This is roughly the way I've done this in the past.
Whenever all the definite moves have been taken and there is a choice of equally good next moves:
copy your grid data structure and push it onto a stack.
take the first candidate move and continue solving recursively
Whereever you get stuck:
pop the saved grid off the stack
take the next candidate move.
I made it in a more simple way:
public void solve(int row, int col)
{
if (row > 8)
{
printBoard();
System.out.println();
return;
}
if (board[row][col] != 0)
{
if (col < 8)
solve(row, col + 1);
else
solve(row + 1, 0);
}
else
{
for (int i = 0; i < 10; i++)
if (checkRow(row, i) && checkCol(col, i))
//&& checkSquare(row, col, i))
{
board[row][col] = i;
if (col < 8)
solve(row, col + 1);
else
solve(row + 1, 0);
}
board[row][col] = 0;
}
}
private boolean checkRow(int row, int numberToCheck)
{
for (int i = 0; i < 9; i++)
if (board[row][i] == numberToCheck)
return false;
return true;
}
private boolean checkCol(int col, int numberToCheck)
{
for (int i = 0; i < 9; i++)
if (board[i][col] == numberToCheck)
return false;
return true;
}
I'm not sure why you say that Dancing Links and Algorithm X were not useful.
Do you mean that you were not able to map Sudoku to an instance of the Exact Cover problem that Algorithm X is designed to solve?
Or that it is a too complicated approach for what you need??
If the former is the case, you might want to look at: A Sudoku Solver in Java implementing Knuthâs Dancing Links Algorithm. It's quite clear and explains also the reasoning behind.
N.B. Algorithm X is a backtracking algorithm so, if that's your only requirement, you can definitely use this approach.
Hope this can help.