Java Array out of bounds error isn't out of bounds? - java

This code is the relevant portion of my program, and it produces an array out of bounds error, and I can't figure out why.
My error is 'java.lang.ArrayIndexOutOfBoundsException: 6', with 6 being a random value, at the if statement in randomShot();
public class Ai
{
private int WIDTH;
private int HEIGHT;
public Ai(){
WIDTH=10;
HEIGHT=10;
}
int[][] board=new int[WIDTH][HEIGHT];
Random rand = new Random();
public void randomShot(){
x=rand.nextInt(WIDTH/2);
y=rand.nextInt(HEIGHT);
x=x*2;
if(y%2==0)
{
y+=1;
}
if(board[x][y]!=0) //java.lang.ArrayIndexOutOfBoundsException: 6
{
randomShot();
}
}
I have noticed that if I use the code
int[][] board=new int[10][10];
it works perfectly fine. I can't see why this is happening, it's doing exactly the same thing?

WIDTH and HEIGHT are 0 when you are defining board.
Constructor is called after class level variables. For int, the default value is 0.

Move your board initialization into the constructor. The order of field initializations means the array is declared (and initialized) before the constructor is entered (and thus, the WIDTH and HEIGHT are zero).
private int WIDTH;
private int HEIGHT;
public Ai(){
WIDTH=10;
HEIGHT=10;
board=new int[WIDTH][HEIGHT]; // <-- here.
}
int[][] board; // =new int[WIDTH][HEIGHT];

Related

tile disappearing from rubiks cube with rotation

I'm working on a 2x2 rubik cube, and was having trouble getting one side rotate with my program. The cube is a 2d array of squares. I'm just triying to do a 90 degree counter clockwise turn.
This is what happens
https://imgur.com/a/tlskNKY
I changed the colour so I could see the specific squares and how they changed. I tried changing the order, moving specific pieces at a time to see if the problem was just overlapping pieces (no such luck).
//square class
public class square implements Comparable {
int c;
private Rectangle r;
int xpos, ypos, width, height;
public square(int a, int x, int y) {
c = a;
xpos = x;
ypos = y;
r = new Rectangle(xpos, ypos, 50, 50);
}
//some unused methods
}
//inside the cube class
public class cube{
square[] temp = new square[4]
square[][] sq= new square[6][4]
//two for loops make squares and fills the sq 2d array
//the result is in the imgur link
public void turnVc(){
temp= sq[2];
sq[2][0]=temp[1];
sq[2][1]=temp[3];
sq[2][2]=temp[2];
sq[2][3]=temp[0];
}
}
I expect the output to be the original image turned counter clockwise.
tmp is a pointer that points to the same object that sq[2] pointers. That's why when you change sq[2] content, you change tmp's as well.
i think instead of assign "temp= sq[2];" you should do the following:
temp = new square[4];
for (int i = 0; i < 4; i++) {
temp[i] = sq[2][i];
}
Edit:
i think a little improvement you could do is that you don;t need to save all the sq[2] array, you could only save the fist item. i would do like this (tmp is now a square, not an array):
tmp = sq[2][0];
sq[2][0] = sq[2][1];
sq[2][1] = sq[2][3];
sq[2][3] = sq[2][2];
sq[2][2] = tmp;
If your square class implements Cloneable, you should use clone() method possible, it is also similar to answer of #Nguyen Tan Bao, but shorter
I guess you 're C++ dev, reference in Java is like pointer in C++, you can research more Have fun !

Fill ArrayList with objects fills with same values

I am trying to fill my empty ArrayList "circles" with objects Circle with random sizes and random locations, which I will later on paint. for loop fills array normally, but for some reason when I copy it with circ.addAll(circles) it doesn't work. I also tried to use .clone(), circ = circles,... but it ended up with either nullpoint exception error or all circles having same values. This is my code.
public class board {
public static int size = 400;
public static ArrayList<Circle> circles;
public static void fillArray(ArrayList<Circle> circ){
Random r = new Random();
int rand = r.nextInt(10)+5;
circles = new ArrayList<Circle>(rand);
System.out.println("random ="+ rand);
for(int i = 0; i< rand; i++){
circles.add(new Circle(Circle.x, Circle.y,Circle.size));
System.out.println(i+". "+ circles.get(i).x +" "+ circles.get(i).y +" size je "+ circles.get(i).size);
//fills normaly
}
circ.addAll(circles);
System.out.println("aaaaa"+circ.get(0).x);
//why same values?
System.out.println("fillArray circles= " +circ.get(0).x+circ.get(0).y+ " "+circ.get(1).x);
}
public static void main(String[] args) {
fillArray(circles);
}
my Circle class looks like this:
public class Circle {
public static int x,y;
public static int size;
public Circle(int x, int y, int size) {
this.x = randomLoc();
this.y = randomLoc();
this.size = randomSize();
}
public static int randomSize (){
int min = 15;
int max = 30;
Random r = new Random();
int rand = r.nextInt(max)+min;
return rand;
}
public static int randomLoc(){
int min = 12;
int max = board.size;
Random r = new Random();
int rand = r.nextInt(max)+min;
return rand;
}}
I am trying to fill my empty ArrayList "circles" with objects Circle with random sizes and random locations
But you're not doing that. The line
circles.add(new Circle(Circle.x, Circle.y,Circle.size));
adds a Circle with static field values. Presumably, your Circle class has something like this:
public class Circle {
public static int x, y, size; // perhaps with some initialized values
public Circle(int x, int y, int size) { /* ... */ }
}
So you add the same values to all the circles in the list. To randomize the size and location you would need to use the Random instance you created. Something like:
circles.add(new Circle(r.nextInt(10)+5, r.nextInt(10)+5, r.nextInt(10)+5));
For loop fills array normally, but for some reason when I copy it with circ.addAll(circles) it doesn't work.
You are confusing the 2 lists you created - circ and circles. You are passing the reference ArrayList<Circle> circles to the method, which is named circ inside the method scope. This is redundant since you can access the static circles from within the method without passing it as an argument. I suggest you solve your design issues before anything else.
What you probably want to do it initialize circ:
circ = new ArrayList<Circle>();
and note that the argument passed to the constructor is the initial capacity, which is a performance parameter, and almost certainly shouldn't be random.
Once you do that, the line circ.addAll(circles); is meaningless and should be removed. Just print circ to see the values (#Override Circle's toString).
Note: It's recommended to use the interface and not the implementation to hold the reference: List<Circle> list = new ArrayList<>();. You shouldn't care about the implementation details when all you do are list operations.
circ.addAll(circles) may not be working properly because it is only making a shallow copy and adding it to the arraylist. A shallow copy is a only a copy of the pointers of the original data, not the data itself. There may be errors happening behind the scenes because of this. Try adding the circle objects by creating a deep copy with the actual data.

how do i call an accsessor method from a different class for an object of that class?

I am trying to produce a proceduraly generated 2D map, but i am stuck on creating the accsessor method to just return what type a specific location is.
I created a custom square class that has the variable type and special..
here is the square class
public class Square{//custom object for map class
private int type = 0;
private boolean special = false;
public int getType(){//returns type of square
return type;
}
public boolean isSpecial(){//returns boolean for whether square is special or not
return special;
}
public void setType(int a){//sets type for square if input is between 1 and 5
if(a>=1&&a<=5){
type = a;
}
}
public void setSpecial(){//sets special status to true
special = true;
}
}
I've tested the square class to make sure it works, I am getting trouble in my Map class when i try to create a method that returns the type of square at a given coordinates
here is the applicable code from that class
public class Map{
private int mapWidth;
private int mapHeight;
Square newMap[][] = new Square[0][0];
public Map(int width, int height){//constructor sets map height and width and instantiates a 2d array with the arguments
if(width <= 0){//if user inputs numbers less than 1 will set according attribute to 1
width = 1;
}
if (height <= 0){
height = 1;
}
mapWidth = width;
mapHeight = height;
Square newMap[][] = new Square[mapWidth][mapHeight];
}
public void create(){
}
public int getWidth(){//accssesor methods
return mapWidth;
}
public int getHeight(){
return mapHeight;
}
public int getType(int x, int y){
return newMap[y][x].getType();
}
}
I know that i am probably doing something horribly wrong but any help will be greatly appreciated.

How to choose random move that takes highest value piece in chess?

So I have an array list of all the moves at the current board state in chess that take a piece.
ArrayList<Move> takePiece;
And all the pieces have a corresponding value:
public static final int PAWN = 1;
public static final int KNIGHT = 2;
public static final int BISHOP = 3;
public static final int ROOK = 4;
public static final int QUEEN = 5;
public static final int KING = 6;
I want to be able to select a random move from the array list that takes the highest value piece.
So if 3 different moves could take the king it would randomly choose one of the 3 moves (check and checkmate haven't been implemented).
How would i go about this?
public Move(Piece p , int x, int y, int dx, int dy, boolean t){
this.p = p;
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.t = t;
}
So this is what a move is so to check the piece value that was going to be taken i would check the piece at (dx,dy).
You have to check in your array the most valuable Piece and choose your move accordingly, to make this, you must iterate twice:
// get the max value of possible pieces that could be taken
ArrayList<Move> takePiece // here you must have all possible takes
int maxPieceValue = 0;
for (Move m : takePiece) {
if(PieceCode.charToInt(m.getChar()) > maxPieceValue)
maxPieceValue = m.getPiece.getType();
}
// get a list with best moves available
ArrayList<Move> bestMoves new ArrayList<Move>();
for (Move m : takePiece) {
if(PieceCode.charToInt(m.getChar()) > maxPieceValue)
bestMoves.add(m);
}
// choose randomly one of best moves
Random random = new Random();
Move choosenMove = bestMoves.get(random.nextInt(bestMoves.lenght));

How to create the correct relationship between classes

I have a feeling this question is going to be something really common sense that I am overcomplicating. I am working on a random maze generation program, so given a width, height, and maximum path length, it will randomly select a start point and generate a path until the max path length is reached or it dead ends/gets stuck, then it will pick a new start point for another path and repeat until the whole grid is filled. I am just creating it for the practice.
I have 3 classes, but I guess I do not really understand how they should interact, or how I should make them interact for the best performance and such. One thing in particular, I just know is terrible practice. Since my Path and Point classes have to operate on the grid of Points that is created in the Maze class, I pass the constructors for Path and Point that Array of Points. It "works"... but I just realized that in doing that, I get a seemingly infinite loop where I create a grid, and create all the points for that grid, and in those points I pass an Array of Points, and each of those Points gets passed an Array of Points, forever.
I thought about making Path and Point extend Maze, but I do not think that is the right relationship. I googled interfaces and abstract classes to see if maybe that is what I wanted, but those did not seem right either.
Maze constructor:
public class Maze
{
private int fileNum = 0;
private Random rand = new Random();
private Point[] grid;
private int width, height;
private int pathLength;
private int curLoc;
private boolean debug, toTxt, toPng, hasValidNewHead = true;
public int frameNum = 0;
public int lastPercent = 0;
public Maze(int iWidth, int iHeight, int iPathLength, boolean d, boolean txt, boolean png)
{
width = iWidth;
height = iHeight;
pathLength = iPathLength;
grid = new Point[width * height];
debug = d;
toTxt = txt;
toPng = png;
}
Path constructor:
public class Path
{
private Random rand = new Random();
private Maze maze;
private int length, maxLength, lastDir, height, width;
private int curLoc;
private boolean generating;
private Point[] grid;
private boolean debug, toTxt, toPng;
public Path(int head, int gridWidth, int gridHeight, int ml, Point[] iGrid, Maze m, boolean d, boolean txt, boolean png)
{
maze = m;
generating = true;
lastDir = -1;
length = 1;
grid = iGrid;
curLoc = head;
height = gridHeight;
width = gridWidth;
maxLength = ml;
debug = d;
toTxt = txt;
toPng = png;
}
Point constructor:
public class Point
{
private int x, y, width, height;
private Point[] grid;
private int type, curLoc;
public Point(int iX, int iY, int w, int h, Point[] iGrid)
{
x = iX;
y = iY;
width = w;
height = h;
grid = iGrid;
curLoc = Arrays.asList(grid).indexOf(this);
type = 0;
}
Mazes are annoying to model because they're either structured around rooms or walls, you need different ones at different times, and either way, you'll end up with tricky code or redundant data and awkward record keeping.
Thad said, Paths are sequences/Lists of moves (North, South, East West), a Maze is an array (or Map) from a coordinate to a Cell/Room, and Cells have boolean walls keyed on moves, so { East: true, North: false, South, false, West: true}.
Or you could just make it an undirected graph.
All I had to do was make the Path and Point classes inner-classes in my Maze Class. That way they have all of the instance data from Maze that they need without needing to pass it through their constructors.

Categories