Problem with creating objects in a multi dimensional array [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I currently have a problem with creating objects using two-dimensional arrays in Java.
I'ld like to display bricks on a playing board (like in the classic "BreakOut games), therefore I created a class "Stone" for the stone-objects, the constructor of the class is:
public Stone (Position pos, int value){
this.pos = pos;
this.type = type;
}
I also created a 2D-array (int) called "stoneTypes" for the pattern of the Stones, in which I saved a matrix from a JSON file.
I ld' now like to create Stone-objects in my class "Level" by using the values of the stoneTypes-matrix, which currently looks like this (I included an if-condition, so Stone-objects are only created for stoneTypes value >= 1):
private Stone[][] stones = new Stone[25][20];
private int[][] stoneTypes;
JSONReader reader = new JSONReader("res/Level" + levelnr +".json");
stoneTypes = reader.getStones2DArray();
for (int w = 0; w < stoneTypes.length; w++) {
for (int h = 0; h < stoneTypes[w].length; h++) {
if (stoneTypes [w][h] >= 1) {
Position pos = new Position(width * w, height * h);
this.stones[w][h] = new Stone(pos, stoneTypes[w][h]);
}
}
}
I also included a get-Method for the Stone-array, so I could use it to draw the Stones in my "Field" class:
public Stone[][] getStones(){
return this.stones;
}
The method for drawing the Stones in my "Field" class currently looks like this:
private void drawStones(Graphics2D g2) {
stones = view.getGame().getLevel().getStones();
for (int i = 0; i < stones.length; i++) {
for (int j = 0; j < stones[i].length; j++) {
*** int x_position = (int) stones[i][j].getPosition().getX(); ***
int y_position = (int) stones[i][j].getPosition().getY();
g2.fillRoundRect(x_position, y_position,
(int) ((double)Constants.SCREEN_WIDTH/Constants.SQUARES_X)-2,
(int) ((double)Constants.SCREEN_HEIGHT/Constants.SQUARES_Y)-2 ,1,1);
System.out.println(x_position);
}
}
}
Eclipse doesn't show any syntax errors but I do receive a NullPointerException at the spot I marked with the ***, as soon as I start the programm. I am not sure if my get-Method isn't implemented correctly or if the process of creating new Stone-objects is simply wrong. I tried hundreds of things but couldn't find a solution, I hope you guys can help me.
Thx in advance, Scoopa!

Here:
if (stoneTypes [w][h] >= 1) {
Position pos = new Position(width * w, height * h);
this.stones[w][h] = new Stone(pos, stoneTypes[w][h]);
}
You are only creating new stones when that condition is met. All other fields will stay with their default initial value. And that would be: null.
When you do that, you can't just go in (unconditionally) and do:
int x_position = (int) stones[i][j].getPosition().getX()
You would need a
if (stones[i][j] != null)
to guard such accesses!

Related

Write a Java method changeBlue(weight) [closed]

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 6 years ago.
Improve this question
Write a method changeBlue(weight). Do not change any color of the pixels in the first half of the picture. For the second half, change blue value of each pixel by new blue=original blue * weight.
For example, if a pixel has values (200,100,100) and weight is 0.5,
then the new values will be (200,100,50). If the weight is 1.5, then
the new values will be (200,100,150).
You can use any image to test this method.
Here's what I have. I think I'm pretty close, but I'm getting some errors. Any advice is appreciated.
public void changeBlue(int weight)
{
Pixel[] pixelArray = this.getPixels();
Pixel pixelObj = null;
int value = 0;
int index = 0;
while (index >= pixelArray.length/2)
{
pixelObj = pixelArray[index];
value = pixelObj.getBlue();
value = (value * weight);
pixelObj.setBlue(value);
index++;
}
}
For a start, the parameter of the changeBluemethod is an int, shouldn't this be a double given your specification?
You also have index initially set to 0, and your loop only runs whilst index >= half the pixel array length (pixels.length / 2). So this loop won't ever start unless pixels.length / 2 returns 0. Once it has started, it'll also never terminate.
You would be best to use a for statement. Initialise an int to half the array length (pixels.length / 2), set it to terminate after the loop executes the last pixels array index (pixels.length - 1), and make sure it increments by 1 each time.
See https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html for details and how to use a for statement.
Additionally, if setBlue() takes an int as a parameter, you should cast it. e.g. (int) (weight * value). But you do not provide any details of the Pixel class.
Example implementation:
public void changeBlue(double weight) {
for (int i = pixelArray.length / 2; i < pixelArray.length; i++) {
pixelArray[i].setBlue((int) (pixelArray[i].getBlue() * weight));
}
}
On a practical note, if blue becomes 0 you won't be able to change it using changeBlue, but this behaviour would be somewhat logical in this case.
Not the best implementation but try :
public void changeBlue(int weight)
{
Pixel[] pixelArray = this.getPixels();
Pixel pixelObj = null;
int value = 0;
int index = 0;
int halfSize = pixelArray.length/2;
for (index = 0; index <= pixelArray.length; index++) {
if (index <= halfSize){
// FIrts half of the file
}
if (index > halfSize) {
// Seconde part of the file
pixelObj = pixelArray[index];
value = pixelObj.getBlue();
value = (value * weight);
pixelObj.setBlue(value);
}
}
}

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1? [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 7 years ago.
So, I've been doing this java class for several months now, and I've been assigned a project before the end of the year. I'm trying to rewrite some old code to use vectors and arrays, but... I get the topic title error. Here is the relevant code:
public static double VectorX(int len, double angle) {
return Math.cos(angle)*len;
}
public static double VectorY(int len, double angle) {
return Math.sin(angle)*len;
}
public static class Projectile {
public int x;
public int y;
public double angle;
public int speed;
public boolean Player;
}
...
public static Projectile[] Shoot = new Projectile[0];
public static double RadianAngle(int x1, int y1, int x2, int y2) {
return Math.atan2(x2-x1, y2-y1);
}
...
for (int i = 1; i <= Shoot.length; i++)
{
Shoot[i].x += VectorX(Shoot[i].speed, Shoot[i].angle);
Shoot[i].y += VectorY(Shoot[i].speed, Shoot[i].angle);
}
...
if (Cooldown == 75 || Cooldown == 25)
{
Projectile Hey = new Projectile();
Hey.x = EX;
Hey.y = EY;
Hey.Player = false;
Hey.speed = 2;
Hey.angle = RadianAngle(Hey.x, Hey.y, X, Y);
Projectile[] Shoot2 = new Projectile[Shoot.length + 1];
for (int l = 0; l <= Shoot.length - 1; l++)
{
Shoot2[l] = Shoot[l];
}
Shoot2[Shoot2.length - 1] = Hey;
Shoot = Shoot2;
}
I've no idea what is going on. I imported these Vector functions from a C#-based language that I am well versed in, but translated them to java. I am getting the error at
Shoot[i].x += VectorX(Shoot[i].speed, Shoot[i].angle);
Shoot[i].y += VectorY(Shoot[i].speed, Shoot[i].angle);
Could you guys give me a hand?
You're getting an ArrayIndexOutOfBoundsException because you are initializing the Shoot array with a size of 0 :
public static Projectile[] Shoot = new Projectile[0];
so the call to
Shoot[0].x += VectorX(Shoot[0].speed, Shoot[0].angle);
in your loop is invalid.
for (int i = 1; i <= Shoot.length; i++)
should be
for (int i = 0; i < Shoot.length; i++)
the reason why
int[] arr = new int[]{ 0, 1, 2 };
arr.length will now equal 3, my array does not have an index at 3, instead, it has indexes at 0, 1, and 2.
Your definition for the shoot array creates an array of length 0: Shoot = new Projectile[0];
Yet when you iterate over the array, you are setting the bounds of your loop variable incorrectly:
for (int i = 1; i <= Shoot.length; i++)
Arrays are zero-indexed (meaning an array of length 1 will have index [0] and no more). So starting your loop index at 1 (int i = 1) is bad to begin with.
Then you are looping too far. Say you have 3 elements in your array, the indexes will be 0, 1 & 2. And your array.length will be 3, but you never want to index 3. So your loop condition needs to be < array.length, not <= array.length.

How to create a number generator that will only pick a number 1 time?

I am creating a concentration game.
I have an buffered image array where I load in a 25 image sprite sheet.
public static BufferedImage[] card = new BufferedImage[25];
0 index being the card back. and 1 - 24 being the values for the face of the cards to check against if the cards match.
What I am tying to do is this I will have 4 difficulties Easy, Normal, Hard, and Extreme. Each difficulty will have a certain amount of cards it will need to draw and then double the ones it chosen. for example the default level will be NORMAL which is 12 matches so it need to randomly choose 12 unique cards from the Buffered Image array and then double each value so it will only have 2 of each cards and then shuffle the results.
This is what I got so far but it always seems to have duplicates about 99% of the time.
//generate cards
Random r = new Random();
int j = 0;
int[] rowOne = new int[12];
int[] rowTwo = new int[12];
boolean[] rowOneBool = new boolean[12];
for(int i = 0; i < rowOneBool.length; i++)
rowOneBool[i] = false;
for(int i = 0; i < rowOne.length; i++){
int typeId = r.nextInt(12)+1;
while(rowOneBool[typeId]){
typeId = r.nextInt(12)+1;
if(rowOneBool[typeId] == false);
}
rowOne[i] = typeId;
j=0;
}
the 3 amounts I will be needing to generate is Easy 6, Normal 12, and Hard 18 extreme will use all of the images except index 0 which is the back of the cards.
This is more or less in the nature of random numbers. Sometimes they are duplicates. You can easily factor that in though if you want them to be more unique. Just discard the number and generate again if it's not unique.
Here's a simple method to generate unique random numbers with a specified allowance of duplicates:
public static void main(String[] args) {
int[] randoms = uniqueRandoms(new int[16], 1, 25, 3);
for (int r : randoms) System.out.println(r);
}
public static int[] uniqueRandoms(int[] randoms, int lo, int hi, int allowance) {
// should do some error checking up here
int range = hi - lo, duplicates = 0;
Random gen = new Random();
for (int i = 0, k; i < randoms.length; i++) {
randoms[i] = gen.nextInt(range) + lo;
for (k = 0; k < i; k++) {
if (randoms[i] == randoms[k]) {
if (duplicates < allowance) {
duplicates++;
} else {
i--;
}
break;
}
}
}
return randoms;
}
Edit: Tested and corrected. Now it works. : )
From what I understand from your question, the answer should look something like this:
Have 2 classes, one called Randp and the other called Main. Run Main, and edit the code to suit your needs.
package randp;
public class Main {
public static void main(String[] args) {
Randp randp = new Randp(10);
for (int i = 0; i < 10; i++) {
System.out.print(randp.nextInt());
}
}
}
package randp;
public class Randp {
private int numsLeft;
private int MAX_VALUE;
int[] chooser;
public Randp(int startCounter) {
MAX_VALUE = startCounter; //set the amount we go up to
numsLeft = startCounter;
chooser = new int[MAX_VALUE];
for (int i = 1; i <= chooser.length; i++) {
chooser[i-1] = i; //fill the array up
}
}
public int nextInt() {
if(numsLeft == 0){
return 0; //nothing left in the array
}
int a = chooser[(int)(Math.random() * MAX_VALUE)]; //picking a random index
if(a == 0) {
return this.nextInt(); //we hit an index that's been used already, pick another one!
}
chooser[a-1] = 0; //don't want to use it again
numsLeft--; //keep track of the numbers
return a;
}
}
This is how I would handle it. You would move your BufferedImage objects to a List, although I would consider creating an object for the 'cards' you're using...
int removalAmount = 3; //Remove 3 cards at random... Use a switch to change this based upon difficulty or whatever...
List<BufferedImage> list = new ArrayList<BufferedImage>();
list.addAll(Arrays.asList(card)); // Add the cards to the list, from your array.
Collections.shuffle(list);
for (int i = 0; i < removalAmount; i++) {
list.remove(list.size() - 1);
}
list.addAll(list);
Collections.shuffle(list);
for (BufferedImage specificCard : list) {
//Do something
}
Ok, I said I'd give you something better, and I will. First, let's improve Jeeter's solution.
It has a bug. Because it relies on 0 to be the "used" indicator, it won't actually produce index 0 until the end, which is not random.
It fills an array with indices, then uses 0 as effectively a boolean value, which is redundant. If a value at an index is not 0 we already know what it is, it's the same as the index we used to get to it. It just hides the true nature of algorithm and makes it unnecessarily complex.
It uses recursion when it doesn't need to. Sure, you can argue that this improves code clarity, but then you risk running into a StackOverflowException for too many recursive calls.
Thus, I present an improved version of the algorithm:
class Randp {
private int MAX_VALUE;
private int numsLeft;
private boolean[] used;
public Randp(int startCounter) {
MAX_VALUE = startCounter;
numsLeft = startCounter;
// All false by default.
used = new boolean[MAX_VALUE];
}
public int nextInt() {
if (numsLeft <= 0)
return 0;
numsLeft--;
int index;
do
{
index = (int)(Math.random() * MAX_VALUE);
} while (used[index]);
return index;
}
}
I believe this is much easier to understand, but now it becomes clear the algorithm is not great. It might take a long time to find an unused index, especially when we wanted a lot of values and there's only a few left. We need to fundamentally change the way we approach this. It'd be better to generate the values randomly from the beginning:
class Randp {
private ArrayList<Integer> chooser = new ArrayList<Integer>();
private int count = 0;
public Randp(int startCounter) {
for (int i = 0; i < startCounter; i++)
chooser.add(i);
Collections.shuffle(chooser);
}
public int nextInt() {
if (count >= chooser.size())
return 0;
return chooser.get(count++);
}
}
This is the most efficient and extremely simple since we made use of existing classes and methods.

Java: ArrayIndexOutOfBoundsException when trying to change position of rectangle [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 7 years ago.
I am developing a Java game, and am currently writing a map maker. I can make the map and draw tiles, but i need to be able to change the position of those tiles so the character can see different locations of the map. When I try to change it, in the moveMap() method, It gives me this error:
Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 570
at Base.moveMap(Base.java:88)
at Base.run(Base.java:55)
at java.lang.Thread.run(Unknown Source)
I have no idea why this is happening - could someone please help me understand the problem. Is there any alternate way to move the tiles?
Here is my code...
public class Base extends JPanel implements Runnable {
private static String[] line = {
"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww",
"wwwwwwwwwwwwwwwwfffffffffffwwwwwwwwwww",
"wwwwwwffwwwwwwwwfwwwwwwwwwwwwwwwwwwwww",
"wwwwwwfffffffwwwfwwwwwwwwwwwwwwwwwwwww",
"wwwwwwffwwwffffffwwwwwwwwwwwwwwwwwwwww",
"wwwwwwffwwwffffffwwwwwwwwwwwwwwwwwwwww",
"wwwwwwfffffffwwwwwwwwwwwwwwwwwwwwwwwww",
"wwwwwwffwwwwwwwwwwwwwwwwwwwwwwwwwwwwww",
"wwwwwwffwwwwwwwwwwwwwwffffffffwwwwwwww",
"wwwwwwffwwwwwwwwwwwwwwwwwwwwffwwwwwwww",
"wwwwffffffwwwwwwwwwwwwwwwwwwffwwwwwwww",
"wwwwffffffffffffffffffffffffffwwwwwwww",
"wwwwffffffwwwwwwwwwwwwwwwwwwwwwwwwwwww",
"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww",
"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww",};
private Rectangle[] colRect;
private int tileWidth = 30;
private int tileHeight = 30;
public Base() {
colRect = new Rectangle[line.length * line[0].length()];
for (int i = 0; i < line.length; i++) {
for (int f = 0; f < line[i].length(); f++) {
colRect[counter] = new Rectangle(f * tileWidth, i * tileHeight,tileWidth, tileHeight);
if (counter != colRect.length) {
counter += 1;
}
}
}
}
public void moveMap(){
for(int i = 0; i <= colRect.length; i++){
colRect[i].setLocation(colRect[i].x+1, colRect[i].y+1);
}
}
}
You almost certainly mean this:
for (int i = 0; i < colRect.length; i++) {
Instead of this:
for(int i = 0; i <= colRect.length; i++){
Remember that if an array has length n, the indexes go from 0 to n - 1.
I would suggest you just to modify the accessor to your geometry, than the map itself. Because it looks like, the function moveMap could have some kind of "loop" behaviour
getLocation (int index, offset = 0){
int accIndex = (index + offset) % colRect.length;
// ... probably better to modify your data-structure to simplify the handling
}

Getting a NullPointerException when trying to pass an ArrayList to another class

In my current project I have an ArrayList of PVectors that store xyz coordinates for 3d points. I'm passing the ArrayList to another class that manipulates it, however, I'm getting a NullPointerException when doing so. I'm assuming that one of the PVectors is null, but I checked for this by assigning any null objects to (0,0,0) and I'm still getting the error. Also, is it more effecient to have an array of PVectors or an ArrayList of PVectors? Either way I'm still getting the error. Here is the line that produces it.
trip.pass(pointCoordinates);
And here is the main class
import org.openkinect.*;
import org.openkinect.processing.*;
Kinect kinect;
Trip trip;
boolean tripOn;
int w = 640;
int h = 480;
int distance = 5;
float[] depthLookUp = new float[2048];
ArrayList pointCoordinates = new ArrayList();
float factor = 400;
float a = 0;
float angle = 0;
float frequency = .05;
void setup() {
size(800,600,P3D);
kinect = new Kinect(this);
kinect.start();
kinect.enableDepth(true);
kinect.processDepthImage(false);
stroke(255);
for (int i = 0; i < depthLookUp.length; i++) {
depthLookUp[i] = rawDepthToMeters(i);
}
for(int i = 0; i < 31920; i++) {
pointCoordinates.add(new PVector(0, 0, 0));
}
}
void draw() {
background(0);
pushMatrix();
translate(width/2 + width/3,height/2, -200);
//add 1/3 width to account for rule of thirds
popMatrix();
int[] depth = kinect.getRawDepth();
calculate(depth);
if(!tripOn) {
for(int i = 0; i < pointCoordinates.size(); i++) {
PVector temp = (PVector) pointCoordinates.get(i);
point(temp.x, temp.y, temp.z);
}
}
if(frameCount % 10 == 0) {
if(tripOn) {
tripOn = false;
trip.clear();
}
else {
tripOn = true;
trip.pass(pointCoordinates);
}
}
if(tripOn) trip.run();
}
void stop() {
kinect.quit();
super.stop();
}
I can paste more classes if it helps to clarify the problem. Thanks!
You are not initializing your "trip" variable and therefore a call to trip.pass(..) would throw the NullPointerException.
You never seem to assign a value to the variable trip. That would certainly cause a NullPointerException at the line that you've shown.
From your code snippet its hard to get the source of your problem. But my first guess is a threading issue.
You are trying to use the trip.pass(pointCoordinates); in a worker thread. Although it appears that ArrayList pointCoordinates = new ArrayList(); is not part of that thread.
A possible solution could be:
check whether the pointCoordinates is initialized or not. If not then wait for it to get initialized.
Update
My bad. I have missed out the initialization of the trip object. :(
My +1 to Dan Breslau and jerluc

Categories

Resources