Counting the amount of a specific object in 2D Array Java - java

In a checkers game for my CS class I have run into trouble with counting how many of a specific color piece are on the board.
Here is the getter method:
public int getCheckersBlue()
{
int counter = 0;
for(int x = 0; x <= 8; x++)
{
for(int y = 0; y <= 12; y++)
{
if(c[x][y].equals(Color.BLUE))
{
counter++;
}
}
}
return counter;
}
The constructor for c:
private CheckersBoard[][] c = new CheckersBoard[8][8];
Whenever trying to run the game in Greenfoot a null pointer exception is thrown even when the code compiles. Even with everything declared, everything has something it's pointing to. Any suggestions?

I see two major problems in your code:
You're iterating over 0-8 elements for x and 0-12 for y, but in declaration you has 0-7 for x and the same for y
NullPointerException. This caused because array declaration will fill your array with null values, so you're comparing null with Color.Blue which is incorrect.
With the both fixes code will look like this
public int getCheckersBlue()
{
int counter = 0;
for(int x = 0; x < 8; x++)
{
for(int y = 0; y < 8; y++)
{
if(Color.BLUE.equals(c[x][y]))
{
counter++;
}
}
}
return counter;
}
But I think it's still logically incorrect.

Okay, a few of things...
You are iterating through 12 every time in the inner loop when it should be 8.
Color.Blue is a JavaFX Paint, I believe. This is not really what you should be using. Unless you have made your own Enumeration type of Color, you should do so. Here is a link for how to do so with relevant examples.
You are checking equality of two different types: CheckersBoard and Color. You should have a CheckersBoard.getSpace(x, y).getColor() or CheckersBoard.getSpace(x, y).getOccupancy() (which should have a NoOccupancy option) if we want to be completely logistically sound with our naming.

Related

I get "IndexOutOfBounds" in my Comets vs Spaceship Game

I began developing a "Spaceship vs Comets" style game last week and now I have come to a stop.
The purpose of the game is to shoot the comets before they pass your ship. You make the comets explode by firing at them. Simple idea!
However, sometimes when I play I get the "IndexOutOfBounds" error. It almost always appears when I haven't fired for a while (The size of my shots ArrayList is 0) and when I then fire and it collides it crashes.
So I have some kind of error in my code, but I really can't see it. I now hope that one of you might see why this accurs and save me from further "IndexOutOfBounds" errors! :)
Here is the part of the code that fails, including the functions that I use to move the comets and shots:
GAME CLASS
if(!Game.player.getShots().isEmpty() && !comet.getComets().isEmpty()) { //Om de är tomma så ignorera
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()) {
for(int y = 0; y < comet.getComets().size(); y++) { //Comets Y
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x)) && !comet.getComets().isEmpty() && !Game.player.getShots().isEmpty()) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
}
}
}
}
}
//Comet spawn timer
comet.addComets();
//Move the comets and shots!
Game.player.moveShots();
comet.moveComets();
repaint();
COMET CLASS
public ArrayList<Rectangle> getComets() {
return comets;
}
public void moveComets() {
if(!comets.isEmpty()) {
for(int x = 0; x < comets.size(); x++) {
comets.get(x).x -= cometSpeed;
}
}
}
PLAYER CLASS (Shots are in this class)
public void fire() {
shots.add(new Rectangle(x + player.width, y + 23, shotWidth,shotHeight));
}
public ArrayList<Rectangle> getShots() {
return shots;
}
public void moveShots() {
if(!shots.isEmpty()) {
for(int x = 0; x < shots.size(); x++) {
shots.get(x).x += fireSpeed;
}
}
}
Keep in mind that comets and shots are both "ArrayList out of the object Rectangle"
I will provide screenshots of error and a picture of the game below!
The error line is marked in the code above, the if statement should block it from crashing (I thought).
Thanks in advance! All help is appreciated! :)
You should change the order at the if statement to avoid it from evaluate one part of it.
You should change your condition to:
if( x < Game.player.getShots().size() && comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
That's because you're removing a shot and inside the comets for when the shoot is removed at the next comet iteration it will throw IndexOutOfBounds as the array no longer have the shot you're checking at the if, so you'll need to check again for the x existing on shots.
You can also do it at the for, you check for both conditions and you let the intersect as only check at the if.
A better performance if would be:
if(!Game.player.getShots().isEmpty() || !comet.getComets().isEmpty()) {
//if one of them is empty, won't be intersections
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
for(int y = 0; y < comet.getComets().size() && x < Game.player.getShots().size(); y++) {
//Comets Y only if the shoot still available
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
y = 0; // if you don't set the y = 0 the next shoot (as you removed the x, getShots.get(x) would be the x + 1 shoot) will only evaluate for the comets after y, won't evaluate the firsts comets at the array.
}
}
}
}
Try to adjust here if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()). You are checking for comet array twice.
Let me know if it works.
Is this code multithreaded?
I am also wondering why you are verifying comet.getComets().isEmpty() so many times.
My guess is that you are manipulating the ArrayList in some other part of your code. Reason I think this is because you are checking the size of the list multiple times and because within the for loop you are only deleting in the end, so that should not be the problem.
For instance if you run this method at two threads at the same time, the ArrayList can be checked at one point, but can reduce after checking the size. then when for instance the size was 10, but became 9, but you still try to delete x with value 10, you will get the out of bounds error.

Why is it allowed to declare a variable in a for loop?

I'm a student currently learning java at school (Beginner) and I was wondering about something.
I have a basic knowledge of coding from other languages and I don't understand a particular thing in Java.
If I were to declare a variable (let's use an int as a example) inside a loop wouldn't that mean that I'm declaring the same variable over and over?
This is what I mean:
for (int i = 0; i < 3; i ++) {
int x = 5;
}
Isn't it the same thing as this? (This one is incorrect)
int x = 5;
int x = 5;
If not, Why? Both of them are / declare the same variable twice, though I know that in loops the variable is local and can't be used outside of the loop (I don't think thats the issue though).
I also know that you can't declare the same variable twice so I don't understand how the first example is legal.
Thanks so much :D
This Question has be solved, Thanks to everyone that helped :D
for (int i = 0; i < 3; i ++) {
int x = 5;
}
is actually equivalent to:
{
int x = 5;
}
{
int x = 5;
}
{
int x = 5;
}
Each x variable is declared in a separate scope.
scope is in one iteration, after end of loop, scope doesn't exist.
simple example:
for (int i = 0; i < 4; i++) {
int x = 0;
System.out.println(x);
x++;
}
output:
0
0
0
0
Lets take 1st expression
for (int i = 0; i < 3; i ++) {
int x = 5;
}
Here scope of variable x is within the loop block
So each time a new loop starts scope is already released.
So there is no error
If you change the same code to like this
for (int i = 0; i < 3; i ++) {
int x = 5;
int x = 5;
}
Now there will be an error as x is already in scope and you are again trying to define.
This is allowed
for (int i = 0; i < 3; i ++) {
int x = 5;
x = 5;
}
as you are resigning the variable
the variable x has life time that begin at when you declare it and ends at the closing block for the for-loop.
in other word x is born when you enter new iteration and dies when iteration ends (or dies at the end of block that contains it)
In each iteration of your loop, a variable x of type int is "created" and assigned the value 5. As soon as the iteration finishes, this variable is "destroyed" and by the next iteration the cycle starts again.
So there are never 2 variables by the same name in the same scope.
It is generally good practice to make the variable avayable to the smallest context possible: if you only need it inside the loop declaring it inside it is considered good practice.
For the loop declaration case, your value gets reassigned basically.
This might proove interesting to read and add further informations on the matter: Declaring variables inside or outside of a loop
This is also a legal thing to do
for (int i= 0; i < 1000000000; i++) {
int j = i & i+1 ;
}
These are legal because at the end of the loop the declared variable "ceases to exists" in order to be reformed the next execution
Well, when you declare int x = 5; inside the loop, you're declaring it in a local scope (which starts from its { to }) so the variable x will be destroyed when it gets out of its scope which means for the next loop iteration, it's a new x so that's why you can do that and since it's destroyed when it gets out of scope it can't be used/seen outside the scope.
Just to clarify the concept of allowing variable declaration in a loop, I've declared the same variable again in the loop, and got error "A local variable or function named 'x' is already defined in this scope"(I wrote this code in C#, but you should get similar message in Java):
If I declare the variable in a different scope outside the loop, there will be no error as the scope is different:
for (int i = 0; i < 3; i++)
{
int x = 5;
}
{
int x = 5;
}
If we couldn't declare variables in loop, we had to write the following code:
{
int x = 5;
// Do something with x=5
}
{
int x = 5;
// Do something with x=5
}
{
int x = 5;
// Do something with x=5
}
But with loop, we can just write the following instead of writing 3 scopes:
for (int i = 0; i < 3; i++)
{
int x = 5;
// Do something three times with x=5
}

String Arrays not working. Compiler not interacting

I was learning how to sort arrays with different types of value holders. I tried to sort an array with Strings, but it comes up with the error message, Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
at SortingArrays.main(SortingArrays.java:50)
There aren't any errors the compiler found, but it comes up with this. The array with numbers worked fine, but the strings didn't. Here is my code.
import java.util.Arrays;
public class SortingArrays {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] aryNums;
aryNums = new int[6];
aryNums[0] = 7;
aryNums[1] = 89;
aryNums[2] = 45;
aryNums[3] = 234;
aryNums[4] = 2;
aryNums[5] = 75;
Arrays.sort(aryNums);
int i;
for (i = 0; i < aryNums.length; i++) {
System.out.println(aryNums[i]);
}
String[] aryStrings;
aryStrings = new String[5];
aryStrings[0] = "I have no idea what I'm doing.";
aryStrings[1] = "Should I know what I'm doing?";
aryStrings[2] = "I guess not.";
aryStrings[3] = "There's my boss.";
aryStrings[4] = "Whoop, he's looking. Hide!";
Arrays.sort(aryStrings);
int x;
for (x = 0; x < aryStrings.length; x++) {
System.out.println(aryStrings[i]);
}
}
}
You are getting runtime exception. ArrayIndexOutOfBoundsException means you are trying to access array beyond its capacity with what its defined.
Problem is with this code:
for (x = 0; x < aryStrings.length; x++){
System.out.println(aryStrings[i]);
^^
}
You are using i as index instead of x. Here i (after your print statements) would be 6 in your case and your array can hold 5 elements which start with 0 and ends with 5.
At the very end of your program:
System.out.println(aryStrings[i]);
i = 6, of course it out of bounds
What you need is:
System.out.println(aryStrings[x]);
i after your first loop is 6.
so here
for (x = 0; x < aryStrings.length; x++){
System.out.println(aryStrings[i]); // i here is 6 but there are 5 elements in aryStrings
}
use x in this loop not i
As other commenters have said, the problem is with your iterating variable.
But to completely avoid this problem, use a for-each loop.
As Joshua Bloch says in Effective Java, 2nd Edition (Item 46):
// The preferred idiom for iterating over collections and arrays
for (int aryNum : aryNums) {
System.out.println(aryNum);
}
Or better in Java 8:
Arrays.stream(aryNums).forEach(System.out::println);
You're using i instead of x in the second print statement
Change the index in x
System.out.println(aryStrings[x]);
As the other answers have stated, by the time you reach your second loop, i is equal to a higher integer than your String array has indices.
Another way to fix your issue is to reset the value of i:
int x;
i = 0;//re-initialize
for (x = 0; x < aryStrings.length; x++) {
System.out.println(aryStrings[i]);
}
However, this defeats the purpose of your x variable.
As a rule of thumb, I'd keep your incrementer local to your loop to prevent problems like this arising:
//declare x in the loop
for (int x = 0; x < aryStrings.length; x++) {
System.out.println(aryStrings[x]);
}

Local variables, "dead code" and 2D arrays problems in Java

I'm having a few problems while developing the following code in Java:
setPos(x, y);
for (int i = 0; x < size; i++) {
for (int j = 0; y < size; j++) {
if (board[x][y] == 'K')
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
Eclipse notice me that i and j, as local variables, they're not used : The value of the local variable i is not used . If I change the i and write the x instead, it tells me that I'm repeating the variable.
j++ is tagged as dead code ?
Also, I have to search for a concrete type of element on the diagonal of a bidimensional array, I've been trying this with 2 for loops, as above, but no result yet.
Hope you can help me, thanks in advance!
Eclipse notice me that i and j, as local variables, they're not used
That's because you're not using them. You've assigned them values, and you've later incremented (added to) those values, but you've never used them for anything.
j++ is tagged as "dead code" (?)
For the same reason, the code increments the value of j, but j is never used, so the code does nothing. "Dead code" refers to code that has no purpose or which is never run.
Your loops don't make a lot of sense. For instance:
for (int i = 0; x < size; i++) {
Normally with a for loop, the control variable (i in this case) should appear in all three of the parts of the for statement (the initializer, the test, and the increment), like this:
for (int i = 0; i < size; i++) {
// Change here -^
But you're not doing that, you're only using i in the initializer and the increment, never in the test (x < size). The same is true of your loop with j.
Similarly, unless there's something changing the value of x, y, and/or size, then your loops will either never run (because x or y is already >= size), run once (because it happens that board[x][u] == 'K'), or they'll run forever (because x or y is < size and since nothing changes that, they just keep looping...).
Eclipse is giving you a hint where the error is:
for (int i = 0; x < size; i++) {
for (int j = 0; y < size; j++) {
you iterate over i and j, but you specify x < size and y < size as a condition. Thus you never actually use the i and j value, thus j++ and i++ is dead code.
If you really would like to use a loop, you should use the variable you use for iteration in the for-loop's condition:
for (int i = 0; i < size; i++) { // i instead of x
for (int j = 0; j < size; j++) { // j instead of y
Also, I have to search for a concrete type of element on the diagonal of a bidimensional array, I've been trying this with 2 for loops, as above, but no result yet.
Why not use a single for loop, like this:
for(int i = 0; i< size; i++)
if(board[i][i] == 'K')
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
Look at this:
setPos(x, y);
if (board[x][y] == 'K') //no i or j so they are unused.
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
If I change the i and write the x instead, it tells me that I'm repeating the variable.
Because x is already a variable(your function argument).so you can't declare it again.
dead code : Code that has no effect on programme.Dead code
Note:it's not a solution of your problem(because i don't know). it is just to show you the mistake.

Passing a variable into an ActionListener

Ok, so I couldn't find exactly what I needed anywhere else, so here goes.
How would I go about passing a variable into a function inside an ActionListener()? This is my code.
for(int y = 0; y < 5; y ++) {
for(int x = 0; x < 5; x ++) {
currentRect = (y * 5) + x;
mainButtons.get(currentRect).addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
answerField.setText(questions.get(currentRect).getAnswer());
}
});
}
}
The error is on line six, where it underlines "currentRect", and then complains about this,
Cannot refer to a non-final variable currentRect inside an inner class defined in a different method
What is does is iterate through a group of JButtons (javax.swing) , and then assign the appropriate action listeners based on their position in the ArrayList, however, I can't seem to pass the variable storing their positions into the actionlistener itself, so I'm stuck. I realised while im writing this that I should really use a foreach, so ill change that later. (just a little note to who was gonna point that out) I realize that I cannot also make that variable final, as it is changed during the for loop. I also tried passing the value of the currentRect ((y * 5) + x) into the functions, but to no avail.
Thanks,
andrewgies17
The solution is simple, simply declare a new final variable inside of your block:
for(int y = 0; y < 5; y ++) {
for(int x = 0; x < 5; x ++) {
final int currentRect = (y * 5) + x;
or if you need the value of currentRect outside of the block:
for(int y = 0; y < 5; y ++) {
for(int x = 0; x < 5; x ++) {
currentRect = (y * 5) + x;
final int currentRect2 = currentRect;
and you use currentRect2 instead of currentRect in your anonymous class. This is counterintuitive because it looks like that the final variable is beeing re-initialised each time but in fact, you must see this as a new variable that is initialised only once for each loop of the block.
However, this is not the most intelligent way of solving this problem; because you are creating a brand new anonymous class for each button just for the purpose of storing a small value that is different between them. These can quickly add up on a limited device. A better idea would be to store the value of the currentRect as a tag for each button. This way, you can declare a single instance of the anonymous class in the outer class and reuse it for all buttons.

Categories