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.
Related
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 !
So I am doing a project for my JAVA class finals. During the assignment, there is a question ask me to randomly assign one of four images (the flower images I have) to the image field in my Flower constructor. But I did not seem to understand this requirement. Can somebody help me with this? I will greatly appreciate. Here is my code. Also, my teacher has given us a hint that we should use an "if" statement for this.
import java.awt.Point;
import javax.swing.ImageIcon;
public class Flower {
private ImageIcon image;
private Point pos;
public Flower(int x, int y) {
pos = new Point(x,y);
}
}
Generating a random number from 0 to 4 will do the trick for you.
Suppose the 4 images you have is in the form of array of type ImageIcon.
If the name of the array is list_flowers.
your constructor can be-
public Flower(int x, int y) {
Random rand = new Random();
pos = new Point(x,y);
image = list_flowers[rand.nextInt(4)];
}
First things first, you need to change Flower so you can pass it the image to be used.
public class Flower {
private ImageIcon image;
private Point pos;
public Flower(ImageIcon image, int x, int y) {
pos = new Point(x,y);
}
}
Personal thing, but I prefer it this way, as the result of initialising the class can be reasoned about.
One solution would be to make use of the available functionality in the Java API. Because I'm lazy, this would mean making use of Collections.shuffle to "randomise" a list of objects.
It might go something like....
List<ImageIcon> images = new ArrayList<>(4);
images.add(new ImageIcon(...)); // Flower 1
images.add(new ImageIcon(...)); // Flower 2
images.add(new ImageIcon(...)); // Flower 3
images.add(new ImageIcon(...)); // Flower 4
for (int index = 0; index < numberOfFlowersToCreate; index++) {
int xPos = ...; // Calculate x position
int yPos = ...; // Calculate y position
Collections.shuffle(images);
ImageIcon image = images.get(0);
Flower flower = new Flower(image, xPos, yPos);
// Do something with the instance of Flower
}
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];
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.
public class Ctrl {
Graph g = new Graph();
Edge[] edges = new Edge[g.getM()];
int[] verteY = new int[g.getM()];
int[] verteX = new int[g.getM()];
int[] vCost = new int[g.getM()];
int contor=0;
public void add(int x,int y,int c) {
System.out.println("contor:" + this.contor);
System.out.println("M:" + g.getM());
verteX[this.contor] = x;
verteY[this.contor] = y;
vCost[this.contor] = c;
this.contor = this.contor + 1;
}
and the output is
contor:0
M:5
why do I get java.lang.ArrayIndexOutOfBoundsException: 0 then?
It seems likely that a newly-initalized Graph's getM() returns zero, making all four arrays zero-size.
If g.getM() later changes, the arrays don't automatically get resized.
My recommendation would be to use ArrayList instead of raw arrays. This would make it easy to append to them.