Having trouble filling the grid. Everytime I do it I get a stackoverflow error. Here is my current code :
public void removeSelfFromGrid() {
Grid<Actor> grid = getGrid();
int rows = grid.getNumRows();
int cols = grid.getNumCols();
for (int i=0; i<rows; i++) {
for (int j=0; j<cols; j++) {
Location loc = new Location(i, j);
laugh = new CKiller();
laugh.putSelfInGrid(grid, loc);
}
}
}
and here is the constructor if needed
public CKiller()
{
Color c = null;
setColor(c);
getGrid();
getLocation();
location = new ArrayList<Location>();
location.add(getLocation());
setDirection(direction);
}
And here is the error (part of it, too big to post all. it's just those 2 statements repeated):
java.lang.StackOverflowError
at info.gridworld.actor.Actor.putSelfInGrid(Actor.java:123)
at CKiller.removeSelfFromGrid(CKiller.java:120)
It's saying this is the problem
laugh.putSelfInGrid(grid, loc);
Go through the following:
-Are you defining laugh prior to the removeSelfFromGrid() method call? It doesn't have a type specified before it.
-Should the variable location not be an ArrayList? It might be a Location object.
-Is the int direction defined already?
-Why are you calling getGrid() and getLocation()? They aren't doing anything beneficial.
-Does CKiller inherit the putSelfInGrid() method from the Actor class?
Please include the full code of the CKiller class as well as the main class that contains removeSelfFromGrid().
I think your problem is that you overrode the removeSelfFromGrid() method. You should have created a new method, such as fillGrid().
When an actor calls putSelfInGrid(), if there is currently another actor in that Location it calls removeSelfFromGrid(), which you overrode to fill every Location on the Grid with an actor. If there are any other actors on the grid they will then call removeSelfFromGrid(), which leads to again filling the grid, etc.
Just fix the code in removeSelfFromGrid(), put it in a new method and restore the previous code, and you should be good.
Related
If I happen to use a few lines of code in the same method as the construction of the called variables, it works, but if I would create another method that would just do the same operation, copy-pasted and then just call the other method inside it, it wouldn't work.
private void initElements(){
TextView ageValue[] =
{
(TextView)this.findViewById(R.id.age1Value),
(TextView)this.findViewById(R.id.age2Value),
(TextView)this.findViewById(R.id.age3Value)
};
TextView ageText[] =
{
(TextView)this.findViewById(R.id.age1Text),
(TextView)this.findViewById(R.id.age2Text),
(TextView)this.findViewById(R.id.age3Text)
};
for(int i = 0; i<=2;i++){
intValues[i] = a.getHours((i));
stringValues[i] = String.valueOf(intValues[i]);
ageValue[i].setText(stringValues[i]);
}
//updateValues();
}
private void updateValues(){
for(int i = 0; i<=2;i++){
intValues[i] = a.getHours((i));
stringValues[i] = String.valueOf(intValues[i]);
ageValue[i].setText(stringValues[i]);
}
}
If I would uncomment the updateValues() function, the program wouldn't run, even though the same code would be executed in the function before. Moreover, debugging would lead after this statement:
ageValue[i].setText(stringValues[i]);
to this error
I've tried rebuilding and cleaning the program and reinstalling it. I tried it on a virtual device and my real smartphone. Same error over and over. (Moreover, it sometimes says that "Source code does not match the bytecode" when I hover on the error in the picture, but sometimes it also doesn't." Also tried the "this." keyword everywhere, but no success.
I am just baffled how this could happen. Maybe the method does not get some sort of right memory reference because it is not directly next to the declaration but I mean the two statements before the "error statement" work perfectly fine, despite them having the same nature. It would be great if you could like enlighten me why this does not work, thanks!
TextView ageValue[] = new TextView[3];
TextView ageText[] = new TextView[3];
int intValues[] = new int[3];
String stringValues[] = new String[3];
CalculateDates a = new CalculateDates();
This is the declaration of the used variables. (That's in the beginning of the class)
You need to use the global ageValue[] and ageText[] for that class.
private void initElements(){
ageValue[0] =(TextView)this.findViewById(R.id.age1Value);
ageValue[1] =(TextView)this.findViewById(R.id.age2Value);
ageValue[2] =(TextView)this.findViewById(R.id.age3Value);
ageText[0] = (TextView)this.findViewById(R.id.age1Text);
ageText[1] = (TextView)this.findViewById(R.id.age2Text);
ageText[2] = (TextView)this.findViewById(R.id.age3Text);
for(int i = 0; i<=2;i++){
intValues[i] = a.getHours((i));
stringValues[i] = String.valueOf(intValues[i]);
ageValue[i].setText(stringValues[i]);
}
Do not declare the TextViews inside the method also.
You were creating different instances of those textViews in initElements() method and the global TextViews were still null
I am trying to formulate a JUnit test for the below code and I am hoping someone might be able to point me in the right direction as I am completely stumped!
public ArrayList<PathData> tileClicked(Coordinate tile){
ArrayList<PathData> pathData = new ArrayList<>();
Tile clickedTile = gameBoard.getTile(tile);
int totalNumPlayers = clickedTile.getNumberOfPlayers();
Player cur;
//GuiInstruction guiInstruction = new GuiInstruction();
//guiInstruction
if (clickedTile.hasPort()){
//deal with ports
for(int j = 0; j < totalNumPlayers; j++){
cur = clickedTile.getPlayerIndex(j);
if(cur.equals(currentPlayer)){
pathData = specialCalculateMove(currentPlayer, true);
}
}
} else if (clickedTile.hasPlayer()){
for(int i = 0; i < totalNumPlayers; i++){
cur = clickedTile.getPlayerIndex(i);
if(cur.equals(currentPlayer)){ //TODO: Is this if statement stupid?
pathData = normalCalculateMove(currentPlayer);
}
}
}else{
//TODO: Does this actually do anything?
}
return pathData;
}
A pretty broad question, thus you only get some broad hints (not going to write code for you!):
You have to understand A) what are parameters going into the method B) what are results resp. "observable" effects that your method can have
From there: you provide a single tile parameter; and depending on the actual state of that object, your method under test is using different paths
That translates to: you want to have at least one "test method" for each possible path through your method. That test method calls the method under test with an argument designed to take a certain path. You invoke the method under test; and then you check whether the result that is returned meets your expectations.
I am working with a priority queue in Java for the first time and I can't for the life of me understand what I am doing that is leading to the exception. I'm attempting to implement an ant colony type solution to the traveling salesman problem. The following is the only code being called for my AntColony class.
public AntColony(TSPInstance p) {
PriorityQueue<Ant> ants = new PriorityQueue<Ant>(new AntComparator());
size = p.getDimension();
for (int i = 0; i < size; i++) {
ants.offer(new Ant(p));
}
shortestTour = Integer.MAX_VALUE;
}
public void nextMove() {
ants.poll();
}
The code that I'm running afterwards just as a test is as follows (just in a main method).
AntColony a = new AntColony(p);
a.nextMove();
The a.nextMove() throws a NullPointerException at the ants.poll() part, but yet if I change the constructor to (for debugging purposes)
public AntColony(TSPInstance p) {
PriorityQueue<Ant> ants = new PriorityQueue<Ant>(new AntComparator());
size = p.getDimension();
for (int i = 0; i < size; i++) {
ants.offer(new Ant(p));
}
ants.poll(); //ADDED THIS
shortestTour = Integer.MAX_VALUE;
}
and then just do
AntColony a = new AntColony(p);
I don't get an exception. I'm struggling to understand how I'm getting an exception from ants.poll(), but yet when I call it from the constructor everything works. Any help with this would be appreciated. There's a lot of code for various things in this project, so I didn't think uploading it all would help anybody so let me know if there's something I should include, but I don't see how the problem could lie outside these two bits of code.
Added: Actual exception
Exception in thread "main" java.lang.NullPointerException
at data_structures.AntColony.nextMove(AntColony.java:25) (the ants.poll() part)
at algorithms.ACTest.main(ACTest.java:6) The a.nextMove() part
The ants variable in your AntColony constructor is a local variable. So when you exit the constructor, it no longer exists. Apparently the ants variable that your nextMove method is calling, is a class member.
You need to change your constructor to have:
// initialize the class member, not a local instance.
ants = new PriorityQueue<Ant>(new AntComparator());
You can just remove the PriorityQueue declaration in your AntColony constructor.
public AntColony(TSPInstance p) {
ants = new PriorityQueue<Ant>(new AntComparator());
size = p.getDimension();
...
}
UPDATE: The cause for your NullPointerException is that you are not initializing your ants property in your constructor but you are creating a new local ants instead. So the ants object in nextMove method has the same value as you provided in your class level declaration, which it's probably null.
I am trying to solve a maze in an object oriented way.
My maze consists of fields, each field has an element attribute,
an element is a wall, player, helper or endpoint. A field with an empty attribute is a path.
Each field keeps track of his own neighbors in a HashMap.
When the player hits a helper, the helper should solve the maze and show the correct path.
I'm trying to find the endpoint by getting the current location of the helper and storing it's neighbors fields in a stack.
This is the code as far as helper goes.
The loop never ends, and I don't know why?
public void findRoute() {
Collection<Field> c = currentField.getHashMap().values();
Stack<Field> fieldNeighbours = new Stack<Field>();
for (Field field : c) {
fieldNeighbours.push(field);
}
while (!endpointReached) {
Field p = fieldNeighbours.pop();
if (p.getElement().getNaam().equals("endPoint")) {
System.out.println("endPoint Reached! ");
endpointReached = true;
return;
}
if (!p.getElement().getNaam().equals("Wall")) {
if (!p.getHashMap().get("north").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("north"));
}
if (!p.getHashMap().get("south").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("south"));
}
if (!p.getHashMap().get("east").getElement().getNaam().equals("Wall")) {
fieldNeighbours.push(p.getHashMap().get("east"));
}
if (!p.getHashMap().get("west").getElement().getNaam().equals("wall")) {
fieldNeighbours.push(p.getHashMap().get("west"));
}
}
}
In addition to the stack you need a set of already-visited cells to avoid searching cycles repeatedly.
I'll also point out that using hashes rather than simple references is bad design for most purposes.
I have an ArrayList of Minion objects, and when a shield collides with a minion, I want to remove that minion from the ArrayList. However, I can only get it to work in 1 way, but not the other way. can anyone plz explain why?
In all 3 cases, I'm using Android's Renderer's onDrawFrame() method... so I have no control over when it gets called. but here's the code for all 3 ways:
Method 1: (does not work)
public void onDrawFrame(GL10 gl) {
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
the problem is that that last line minions.remove(indexesToRemove.get(i)); doesn't ACTUALLY remove the minions. it DOES get called, with the proper index. i've stepped through the debugger, ran it straight up, and the arraylist isn't modified at all. why is this? actually, in the debugger, that line "minions.remove(indexesToRemove.get(i));" gets called a bijillion times.
Method 2: (still does not work)
public void onDrawFrame(GL10 gl) {
synchronized(minions){
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
}
In here, I thought... "oh maybe since it's not quite synchronized, the drawFrame sometimes gets called too many times and is accessing the arraylist at the wrong time and i need to lock it. but it still doesn't work. again, that line minions.remove(indexesToRemove.get(i)); gets called properly with the right index, but does NOT actually remove the object. i'm watching my shield on the screen slam right into the minion and nothing happens to the minion (it doesn't get removed from the arraylist)
Method #3 (this actually works)
public void onDrawFrame(GL10 gl) {
ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
int len = colliders.size();
for(int i=0; i<len; i++){
GameObject collider = colliders.get(i);
if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
minions.remove(collider); // <---- why does THIS work instead?
}
}
}
this code works perfectly. the shield smacks the minion and the minion drops dead. as you can see here, the ONLY difference is that i'm using the overloaded ArrayList.remove(object) method instead of removing by index. as in the line minions.remove(collider);. why does THIS work ?
can anyone please explain?
on a side note, aside from storing another instance variable copy of the arraylist, is there a better way to manage ArrayList<Minion> colliders = new ArrayList<Minion>(minions); ?
Note: both Shield and Minion are regular Java objects that have a rectangular shape as boundary. all that math checks out just fine. i've tested it in the debugger and the collision detection is accurate. I'm also updating the bounds/positions accurate in the onDrawFrame() method.
Because ArrayList provides two methods that are:
public E remove(int index)
public boolean remove(Object o)
When you invoke minions.remove(indexesToRemove.get(i)), since indexesToRemove is a List<Integer>, the invocation is bound to the second signature in which you remove an element by directly specifying the object, auto-unboxing doesn't turn your Integer into an int so the element is not found and nothing happens.
Try with: minions.remove((int)indexesToRemove.get(i)) so that static binding of the method is correctly applied.
#Jack's answer is correct. For posterity you should be using an Iterator here that you can remove with inside your loop:
// synchronization wrapper here
Iterator<Minion> iterator = minions.iterator();
while (iterator.hasNext()) {
Minion minion = iterator.next();
if( OverlapTester.overlapCircleRectangle(..., minion.bounds)) {
iterator.remove();
}
}
It's treating Integer as an object ref in the 1st two example, cast it to an int