user9479432
user9479432

Reputation:

Calling a setter on an array of objects

I'm trying to code a console-based farm simulator game. My classes are:

Board.java

public class Board {
    Spot[][] board = new Spot[50][50];
    Values free = new Values(1000,'_');
    Plant plant = new Plant(10,'@');

    public Board() {
        for(int i = 0; i < MAX_SIZE; ++i)
            for (int j = 0; j < MAX_SIZE; ++j)
                board[i][j] = new Spot(plant);
    }
}

Spot.java

public class Spot {

    Values values;

    public Values getValue() {
        return values;
    }

    public void setValue(Values values) {
        this.values = values;
    }
}

Values.java

public class Values{
    private int price,time;
    private char sign;

    public Values(int price, char sign){
        setPrice(price);
        setSign(sign);
    }
    // All the setters and getters...
}

Plant.java

public class Plant extends Values {
    private boolean onfire;

    public Plant(int price, char sign)
        super(price,sign);
        setOnFire(false);
    }    
    // Setter and getter for onfire...
}

The problem: when calling (Plant)(board[0][0].getValue()).setOnFire(true), it applies for each element of board that has an instanceof Plant.

Upvotes: 1

Views: 718

Answers (2)

WaterGenie
WaterGenie

Reputation: 139

The reason why all of the plants were set on fire when you've only called on one is that you've assigned all of the spots the exact same plant in the board initialisation hence there's ever only 1 plant to begin with.
Try board[i][j] = new Spot(new Plant(...)); so that each spot gets its own default plant that are independent of one another.
Although this wasn't part of the question: you will run into the same problem once you start calling setValue() on any of the free values for the same reason!

It looks as though you were trying to create a default Value and Plant at the beginning of your board class. There are multiple ways around this in addition to the above such as:

  1. Explicitly listing out the default values that you can then feed into their respective constructors:
    private char valueSign = '_';
    private char plantSign = '@';, etc.
    Then you can do board[i][j] = new Spot(new Plant(plantValue, plantSign));.
  2. Create a default constructor in the spot classes.
  3. Leave your code as they are and just clone the default plant:
    board[i][j] = new Spot(plant.clone()).

All of these should fix the problem you are having. Whichever method you choose depends on how you want to organise your game and where the data should live. Good luck.

Upvotes: 1

Jaroslaw Pawlak
Jaroslaw Pawlak

Reputation: 5578

"it applies for each element" - this means that you all of those references point to a single object in memory.

Look at your loop in Board class. You create multiple Spots - you call its constructor in the loop. But your Plant is declared only once and passed as an argument in Spot's constructor. This means that all Spots share a single Plant.

Check it out by trying board[0][0].getValue() == board[0][1].getValue(). I guess the result is true, but what you want is false.

It is enough to move your Plant declaration to inside the loop (you might need to do the same with Values).

Upvotes: 1

Related Questions