Java: Whenever I test this code and try to put a value of 6 or more for the rows
ID: 3855435 • Letter: J
Question
Java:
Whenever I test this code and try to put a value of 6 or more for the rows and columns it gives me a StackOverflow Error. How would I be able to change this to include values of 6 or more?
import java.util.Random;
import java.util.Scanner;
public class MouseMaze2 {
static final int INVALID_LOC = -10000;
static final int neighX[] = {-1, -1, -1, 0, 0, 1, 1, 1};
static final int neighY[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int counter = 0;
int catCaught = 0;
int totalBadMoves = 0;
int fellOverTheEdge = 0;
Random random = new Random();
public boolean isLegal(int maze[][], int totRows, int totCols, int destRow,
int destCol, int curRow, int curCol, int visited [][], int catX, int catY){
if (destRow >= totRows || destCol >= totCols || destRow < 0 || destCol < 0) {
fellOverTheEdge++;
totalBadMoves++;
return false;
}
if ((destRow+destCol) < (curRow+curCol) || visited[destRow][destCol] == 1) {
totalBadMoves++;
return false;
}
if ((destRow==catX && destCol==catY) || (destRow==catX && destCol==catY+1)
|| (destRow==catX+1 && destCol==catY) || (destRow==catX+1 && destCol==catY+1)) {
catCaught++;
totalBadMoves++;
return false;
}
return true;
}
public void resetAll(int maze[][], int[][] visited, int totRows, int totCols) {
for (int i=0; i<totRows; i++) {
for (int j=0; j<totCols; j++) {
maze[i][j] = 0;
visited[i][j] = 0;
}
}
counter = 0;
}
public void runForrestRun(int maze[][], int totRows, int totCols, int curRow,
int curCol, int visited[][], int catX, int catY) {
if (curRow == totRows-1 && curCol == totCols-1) {
printStatistics(maze, totRows, totCols, catX, catY);
return;
}
visited[curRow][curCol] = 1;
maze[curRow][curCol] = ++counter;
int nextLocIndex = random.nextInt(8);
if (isLegal(maze, totRows, totCols, curRow+neighX[nextLocIndex],
curCol+neighY[nextLocIndex], curRow, curCol, visited, catX, catY)) {
int newCatX = random.nextInt(totRows);
int newCatY = random.nextInt(totCols);
runForrestRun(maze, totRows, totCols, curRow+neighX[nextLocIndex],
curCol+neighY[nextLocIndex], visited, newCatX, newCatY);
} else {
resetAll(maze, visited, totRows, totCols);
runForrestRun(maze, totRows, totCols, 0, 0, visited, INVALID_LOC, INVALID_LOC);
}
}
void printStatistics(int[][] maze, int totRows, int totCols, int catX, int catY) {
System.out.println("It took " + totalBadMoves + " attempts to find a path");
System.out.println("The mouse fell off the maze " + fellOverTheEdge + " times");
System.out.println("The cat got the mouse " + catCaught + " times");
for (int i=0; i<totRows; i++) {
for (int j=0; j<totCols; j++) {
if ((i==catX && j==catY) || (i==catX && j==catY+1) || (i==catX+1 && j==catY) || (i==catX+1 && j==catY+1)) {
System.out.print("C ");
} else {
System.out.print(maze[i][j]+" ");
}
}
System.out.println();
}
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter the size of the maze");
System.out.print("How many rows would you like ? : "); int totRows = sc.nextInt();
System.out.print("How many cols would you like ? : "); int totCols = sc.nextInt();
sc.close();
int maze[][] = new int[totRows][totCols];
int visited[][] = new int[totRows][totCols];
new MouseMaze2().runForrestRun(maze, totRows, totCols, 0, 0, visited, INVALID_LOC, INVALID_LOC);
}
}
Explanation / Answer
I checked it .. Its not happening everytime. It is because you have not handled the case, if mouse is not able to find a path after alot of tries. As computer have a fixed stack size limit, so we were getting this error StackOverflowException.
Let us explain the situation in details.
What we are actually doing in the code is that we are actually generating random numbers less than 8 and then using that random value and neighX array value, we are going to next random position. Lets say mouse tried 2500 times for finding the correct path, but each time it gets into a wrong path and resetAll function is called. As system has limited stack, when it gets full it throws out StackOverflow Exception....
To handle this situation there are many ways.. Some of them are: -
1. Add in Java Run configuration-> VM arguments: -
-Xss1m
This will increase the stack size from default(512KB) to 1024KB or 1 Mb. But this is not a good practice as it effects the performance and can eventually result to failures.
2. Adding a terminating condition: -
This is the mostly used way to avoid this exception, Here a terminating condition is added, to stop execution of program , if it is not resulting to required state. In our program we can actually do this. we can control the program execution by terminating the program , if totalBadMoves becomes greater than some threshhold limit.. for eg.. I have changed the runForrestRun function as below: -
public void runForrestRun(int maze[][], int totRows, int totCols, int curRow, int curCol, int visited[][], int catX,
int catY) {
if (curRow == totRows - 1 && curCol == totCols - 1) {
printStatistics(maze, totRows, totCols, catX, catY);
return;
} else if(totalBadMoves > 2000) {
System.out.println("Mouse is lost and exhausted. Sad!");
return;
}
visited[curRow][curCol] = 1;
maze[curRow][curCol] = ++counter;
int nextLocIndex = random.nextInt(8);
if (isLegal(maze, totRows, totCols, curRow + neighX[nextLocIndex], curCol + neighY[nextLocIndex], curRow,
curCol, visited, catX, catY)) {
int newCatX = random.nextInt(totRows);
int newCatY = random.nextInt(totCols);
runForrestRun(maze, totRows, totCols, curRow + neighX[nextLocIndex], curCol + neighY[nextLocIndex], visited,
newCatX, newCatY);
} else {
resetAll(maze, visited, totRows, totCols);
runForrestRun(maze, totRows, totCols, 0, 0, visited, INVALID_LOC, INVALID_LOC);
}
}
The output by above method is like follows: -
Please enter the size of the maze
How many rows would you like ? : 7
How many cols would you like ? : 7
Mouse is lost and exhausted. Sad!
This happens if after 2000 tries also mouse was not able to get to the required path.But there is a problem in this one also. We cannot assume any random threshhold limit. If we select less value, we will get exit the program very early. If we select larger value, the system may again get into StackOverFlowException.
3.
The third way is the most decent way to handle this situation. And the way is to use a try catch statement. It is done as follows: -
public void runForrestRun(int maze[][], int totRows, int totCols, int curRow, int curCol, int visited[][], int catX,
int catY) {
try {
if (curRow == totRows - 1 && curCol == totCols - 1) {
printStatistics(maze, totRows, totCols, catX, catY);
return;
} else if(gotError) {
return;
}
visited[curRow][curCol] = 1;
maze[curRow][curCol] = ++counter;
int nextLocIndex = random.nextInt(8);
if (isLegal(maze, totRows, totCols, curRow + neighX[nextLocIndex], curCol + neighY[nextLocIndex], curRow,
curCol, visited, catX, catY)) {
int newCatX = random.nextInt(totRows);
int newCatY = random.nextInt(totCols);
runForrestRun(maze, totRows, totCols, curRow + neighX[nextLocIndex], curCol + neighY[nextLocIndex], visited,
newCatX, newCatY);
} else {
resetAll(maze, visited, totRows, totCols);
runForrestRun(maze, totRows, totCols, 0, 0, visited, INVALID_LOC, INVALID_LOC);
}
} catch (StackOverflowError e) {
System.out.println("Stack overflowed. It means Mouse is lost and exhausted. Sad!");
gotError = true;
}
}
Define gotError flag and initialize with false globally.
But this will not be a good choice and preventing is better than cure..
So my choice is 2nd option and decide on a good threshhold value.
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.