This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 6 years ago.
I am trying to use stacks to find my way through a maze.
Before I worry about stacks, I am trying to get it so that it comes to a dead-end first.
However, when I run my code I am getting java.lang.ArrayIndexOutofBoundsException: -1. Which does not make sense since I am constantly updating the rows and columns.
Here is part of my code that I am stuck on:
Maze myMaze = new Maze (rows, columns);
MazeDisplay myDisplay = new MazeDisplay (myMaze);
myMaze.buildMaze(10);
myMaze.setSolveAnimationDelay(75);
boolean [][] mazeArray = new boolean [rows][columns];
for (int row=0; row<mazeArray.length; row++)
for (int col=0; col<mazeArray[row].length; col++)
mazeArray[row][col] = false;
mazeArray [myMaze.getCurrentRow()][myMaze.getCurrentCol()] = true;
for (int i = 0; i < 9999999 ; i++) //Temporary for now
{
int arrayRows = myMaze.getCurrentRow();
int arrayCols = myMaze.getCurrentCol();
if (myMaze.isOpen(Maze.Direction.RIGHT) && mazeArray [arrayRows][1 + arrayCols] == false)
{
myMaze.move(Maze.Direction.RIGHT);
//mazeStack.push(Maze.Direction.RIGHT);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.UP) && mazeArray [1 + arrayRows][arrayCols] == false)
{
myMaze.move(Maze.Direction.UP);
//mazeStack.push(Maze.Direction.UP);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.LEFT) && mazeArray [arrayRows][arrayCols - 1] == false) // <---Getting an error here.
{
myMaze.move(Maze.Direction.LEFT);
//mazeStack.push(Maze.Direction.LEFT);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.DOWN) && mazeArray [arrayRows - 1][arrayCols] == false) // <---Getting an error here.
{
myMaze.move(Maze.Direction.DOWN);
//mazeStack.push(Maze.Direction.DOWN);
mazeArray[arrayRows][arrayCols] = true;
}
Is there a way to get around this? What I want is to access the ArrayList's position down or left of the current position.
Here are some of the methods of the Maze class:
//-------- isOpen - returns true if there is no wall in the direction that is passed in
public boolean isOpen(Direction direction)
{
boolean result = false;
if (direction == Direction.UP && mazeArray[currentArrayRow-1][currentArrayCol]==0)
result = true;
else if (direction == Direction.DOWN && mazeArray[currentArrayRow+1][currentArrayCol]==0)
result = true;
else if (direction == Direction.LEFT && mazeArray[currentArrayRow][currentArrayCol-1]==0)
result = true;
else if (direction == Direction.RIGHT && mazeArray[currentArrayRow][currentArrayCol+1]==0)
result = true;
return result;
}
//-------- getCurrentRow - returns the current (real) row
public int getCurrentRow()
{
return currentArrayRow/2;
}
//-------- getCurrentCol - returns the current (real) col
public int getCurrentCol()
{
return currentArrayCol/2;
}
// -------- move - receives a Direction and moves there if OK. Calls the other
// arrayMove to do this
public boolean move(Direction direction)
{
boolean success = false;
if (direction == Direction.UP)
success = arrayMove(currentArrayRow-2, currentArrayCol);
else if (direction == Direction.DOWN)
success = arrayMove(currentArrayRow+2, currentArrayCol);
else if (direction == Direction.LEFT)
success = arrayMove(currentArrayRow, currentArrayCol-2);
else if (direction == Direction.RIGHT)
success = arrayMove(currentArrayRow, currentArrayCol+2);
return success;
}
//This is Maze's enumerated data type: moves can be UP, DOWN, LEFT, RIGHT
public enum Direction
{
UP, DOWN, LEFT, RIGHT
}
//-------- getMazeArray - returns the mazeArray
public int[][] getMazeArray()
{
return mazeArray;
}
Before checking the left cell, you should check that you are not on the left edge. Otherwise mazeArray [arrayRows][arrayCols - 1] will throw an exception, since arrayCols - 1 = -1.
If I understand your code correctly, your algorithm isn't perfect. It gets stuck at dead ends. I think the shortest path algorithm is the easiest one to implement.
Related
what i'm trying to do is to check if 2 is before 4 in a array i used a for loop and condition check and i see that i'm going wrong in my first condition check. i want to make it so that if two is not in the loop it just breaks and if it sees that four is before it breaks as well.
i put the print statement to see where i was going wrong and it seems to if(array[i] == two and it goes to the else and breaks. i also read that you can do it with another array but that sound off so i also wanted to ask if that was possible.
public static void main(String[] args) {
int[] check = {2, 3, 4, 2, 6};
System.out.println(universe42(check));
}
private static boolean universe42(int[]array){
boolean check1 = false;
boolean check2 = false;
int two = 2;
int four = 4;
for(int i=0; i< array.length; i++) {
if (array[i] == two) {
check1 = true;
System.out.println("check1");
}
else {
System.out.println("check-------");
break;
}
if (array[i]== four){
check2=true;
}
}
if(check1==true && check2== true){
return true;
}
return false;
}
}
You're breaking the loop execution if array[i]==two is false, and it eventually always is, because at position 1 you have a 3, and you always run the first check.
You need to remove the break of the else.
You need to break when you find a 4, not when you don't find a 2. Something like this:
boolean foundTwo = false;
for (int x : array) {
if (x == 2) {
foundTwo = true;
} else if (x == 4) {
break;
}
}
return foundTwo;
If you want to make sure there's both a 2 and a 4, in the correct order, just return on 4 instead of breaking, and default to false otherwise:
boolean foundTwo = false;
for (int x : array) {
if (x == 2) {
foundTwo = true;
} else if (x == 4) {
return foundTwo;
}
}
return false;
I am new to programing, so bare with me lol. Our teacher has given us a game in which we need to add some elements to it. It's a game where we have a player, some enemies and some food made out of rectangles. If the player hits the food i want the food to spawn somewhere else in the window. Heres is the code where im trying to make it happen:
private void updateFood(){
for(int i = 0; i < food.length; ++i)
{
//Should we follow or move randomly?
//2 out of 3 we will follow..
if(rnd.nextInt(3) < 2)
{
//We follow
int dx = player.getX() - food[i].getX();
int dy = player.getY() - food[i].getY();
if(abs(dx) > abs(dy))
{
if(dx > 0)
{
//Player is to the right - opiste
food[i].moveLeft();
}
else
{
//Player is to the left - opiste
food[i].moveRight();
}
}
else if(dy > 0)
{
//Player is down; - opiste
food[i].moveUp();
}
else
{//Player is up; - opiste
food[i].moveDown();
}
}
else
{
//We move randomly
int move = rnd.nextInt(4);
if(move == 0)
{
//Move right
food[i].moveRight();
}
else if(move == 1)
{
//Move left
food[i].moveLeft();
}
else if(move == 2)
{
//Move up
food[i].moveUp();
}
else if(move == 3)
{
//Move down
food[i].moveDown();
}
}
if(food[i].getX() == player.getX() && food[i].getY() == player.getY()){
food[i].getX() = random(0,width);
food[i].getY() = random(0,height);
}
}
}
the last 10 lines (or so) is where im having the problem.
if(food[i].getX() == player.getX() && food[i].getY() == player.getY()){
food[i].getX() = random(0,width);
food[i].getY() = random(0,height);
With limited info on what methods your food[index] objects have, I'm going to guess .getX() is read-only, meaning you can't set a value to it. Either find a .setX(number) method, or use the existing .moveLeft/Right/Up/Down(number) with a bit of maths.
I'm trying to create a maze with Union Find, but am unable to remove walls.
This is what I have got so far.
private void createMaze (int cells, Graphics g) {
s = new int[cells*cells]; //No unions yet setting all to -1
for(int i = 0; i < cells*cells; ++i){
s[i] = -1;
}
g.setColor(Color.yellow);
random = new Random();
while(breaker){
g.setColor(Color.yellow);
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
else{
int location = randomCellX+(randomCellY*cells);
int neighbour = 0;
if(innerWall==0){
neighbour =location-1;
}
else if(innerWall==1){
neighbour =location-cells;
}
else if(innerWall==2){
neighbour =location+1;
}
else if(innerWall==3){
neighbour =location+cells;
}
int locationRoot =find(location);
int neighbourRoot =find(neighbour);
if(locationRoot==neighbourRoot){
breaker = checkIfDone(s);
}
union(location,neighbour);
drawWall(randomCellX,randomCellY,innerWall,g);
}
}
}
If I remove the
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
It removes the lines fine,but when it is added the walls are not removed. The method is called but doesn't do anything.
It seems some logical mistake have been done obviously. But can not spot specifically as you haven't given the explanation of the logic you have done. Only can help showing the path where the problem might be happening.
Since you can not reach the else block anyway, it is obvious that one or more of these conditions in if are always true.
(randomCellX == cells && innerWall == 2)
(randomCellX == 0 && innerWall == 0)
(randomCellY == cells - 1 && innerWall == 3)
(randomCellY == 0 && innerWall == 1)
That's why you are getting true for the if condition and continuing the loop without doing anything. Ensure the conditions are okay.
If these conditions are right, the next suspect might be these lines:
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
Check whether these random values range are exactly what you want or not. For example: you are taking random values for randomCellX from 0 to cells-2, but for randomCellY the range is 0 to cells-1.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to solve an interesting problem for navigating a Barbie doll inside a grid system. Initially, Barbie is in [0,0] position, means in the intersection of the X and Y axis. Barbie has 3 operations on movement with 'F' for forward, 'R' for right turn (90 degree) and 'L' for left turn (90 degree). Say, if I pass the direction String of "FF", the position should be [0,2]. I solve the problem and the current state of code is as following,
public static void barbiePosition(String str ){
if( str == null || str.length() == 0)
return;
int [] initial = {0,0};
boolean xPos = false, xNeg = false, yPos = true, yNeg = false;
char[] ch = str.toCharArray();
for( char c: ch){
// the initial postion of the robot is towards the positive Y axis
if(c == 'L'){
if(xPos){
xPos = false;
yPos = true;
}
else if ( xNeg){
xNeg = false;
yNeg = true;
}
else if(yPos){
xNeg = true;
yPos = false;
}
else if (yNeg){
yNeg = false;
xPos = true;
}
}
else if ( c == 'R'){
if(xPos){
xPos = false;
yNeg = true;
}
else if ( xNeg){
yPos = true;
xNeg = false;
}
else if(yPos){
yPos = false;
xPos = true;
}
else if (yNeg){
yNeg = false;
xNeg = true;
}
}
else if (c == 'F'){
if(xNeg){
initial[0] -= 1;
}
else if (xPos){
initial[0] += 1;
}
else if (yNeg){
initial[1] -=1;
}
else if( yPos){
initial[1] += 1;
}
}
}
System.out.println(Arrays.toString(initial));
}
The thing is I just don't the solution as it's feels ugly. Is there any better way
to design the algorithm ?
What constitutes 'forward' in your application is a function of the previous move.
Forward simply means you repeat your last move.
If forward is your first move you need to pick a convention that says something like "Barbie is initially moving to the right".
The purpose of this assignment was to create a Field and Robot class and objects of those classes.
The single field object is limited to a square of points from (0, 0) to (50, 50), and contains 3 pieces of gold and 3 bombs.
Three robot objects search the field (one after another) for gold from left to right (0, 0) to (0, 50) and descend through the field (1, 0) to 1, 50) and so on.
The robots are destroyed by bombs that are places by input from the user. Once the gold is collected it cannot be picked up by another robot, and one a bomb explodes it does not do so again.
This is my attempt at solving the problem so far, I am continuing to work on it, but would appreciate a second pair of eyes on it to catch something im missing. The program compiles, but the bombs and gold arent being "found" correctly and the output states that the following robots die on the same bomb as the one before it. Also, there are several pieces of code removed by comments, I did this to test different parts of the program. I think this section is where I'm having trouble. The methods field.alreadyFound() and field.alreadyBombed() return a boolean with the value true. My if statements should be saying if the gold/bomb has already been found, ignore it.
while(x <= 50 && y <= 50 && alive2 == true) {
foundGold1 = robot2.look(field.locateGold1());
foundGold2 = robot2.look(field.locateGold2());
foundGold3 = robot2.look(field.locateGold3());
foundBomb1 = robot2.look(field.locateBomb1());
foundBomb2 = robot2.look(field.locateBomb2());
foundBomb3 = robot2.look(field.locateBomb3());
/*gotBomb1 = field.alreadyBombed1();
gotBomb2 = field.alreadyBombed2();
gotBomb3 = field.alreadyBombed3();
gotGold1 = field.alreadyFound1();
gotGold2 = field.alreadyFound2();
gotGold3 = field.alreadyFound3();*/
if (foundGold1 == true){
if (field.alreadyFound1() == true){}
else {robot2.addGold();
field.foundGold1();}
}
if (foundGold2 == true) {
if (field.alreadyFound2() == true){}
else {robot2.addGold();
field.foundGold2();}
}
if (foundGold3 == true) {
if (field.alreadyFound3() == true){}
else {robot2.addGold();
field.foundGold3();}
}
if (foundBomb1 == true) {
if (field.alreadyBombed1() == true){}
else alive2 = false;
}
if (foundBomb2 == true) {
if (field.alreadyBombed2() == true){}
else alive2 = false;
}
if (foundBomb3 == true) {
if (field.alreadyBombed3() == true){}
else alive2 = false;
}
y = y + 1;
robot2.setLocation(x, y);
//System.out.println(y);
if (y == 50)
{x = x + 1;
y = 0;}
}
I don't see where you set that a bomb has exploded, so from what I see here, you're missing that part.
Below is the code reformatted and slightly restructured: I found the code fairly difficult to work with as-is. It may be easier to work with this shorter, more canonical, and IMO more communicative version.
while (x <= 50 && y <= 50 && alive2 == true) {
foundGold1 = robot2.look(field.locateGold1());
foundGold2 = robot2.look(field.locateGold2());
foundGold3 = robot2.look(field.locateGold3());
foundBomb1 = robot2.look(field.locateBomb1());
foundBomb2 = robot2.look(field.locateBomb2());
foundBomb3 = robot2.look(field.locateBomb3());
/*gotBomb1 = field.alreadyBombed1();
gotBomb2 = field.alreadyBombed2();
gotBomb3 = field.alreadyBombed3();
gotGold1 = field.alreadyFound1();
gotGold2 = field.alreadyFound2();
gotGold3 = field.alreadyFound3();*/
if (foundGold1 && !field.alreadyFound1()) {
robot2.addGold();
field.foundGold1();
}
if (foundGold2 && !field.alreadyFound2()) {
robot2.addGold();
field.foundGold2();
}
if (foundGold3 && !field.alreadyFound3()) {
robot2.addGold();
field.foundGold3();
}
if (foundBomb1 && !field.alreadyBombed1()) {
alive2 = false;
}
if (foundBomb2 && !field.alreadyBombed2()) {
alive2 = false;
}
if (foundBomb3 && !field.alreadyBombed3()) {
alive2 = false;
}
y = y + 1;
robot2.setLocation(x, y);
if (y == 50) {
x = x + 1;
y = 0;
}
}
You may also be hampered by the amount of code it takes to do this work: I assume you have essentially identical code for robot1 and robot2, the only difference being which robot you're currently processing.
Rather than repeat the code, consider passing a currentRobot in to a single method. There are a variety of ways to go about dealing with issues like this, but that fits in well with what you've already done. You're likely want to add an isAlive method/property to the robot class.