1

So I have a rather simple piece of code:

    Soldier Horseman = new Soldier("Horseman",Archer, 20);
    Soldier Spearman = new Soldier("Spearman",Horseman, 10);
    Soldier Archer = new Soldier("Archer",Spearman, 10);

Where the constructor for soldier takes the arguments

    Soldier(String name, Soldier target, double range)

The target is then used to calculate distance between the two in a method.

public double DistanceCalculation() {
    distanceToTarget = ((Math.pow((soldierPosition[0] - soldierTarget.soldierPosition[0]), 2)) + Math.pow((soldierPosition[1] - soldierTarget.soldierPosition[1]), 2));
    return distanceToTarget;

However, when I try to create this code, the top most soldier cannot be created because its target doesnt exist yet. I tried using String instead of Soldier in the constructor, but then I cannot figure out how to convert string into Soldier so that the SoldierTarget.soldierPosition works. Any ideas?

8
  • when do you callDistanceCalculation() Commented Nov 4, 2015 at 21:02
  • 1
    On a side note, please use camelCase (first letter lowercase) for objects / variables - it's Java convention and so easier to read for most of us. Commented Nov 4, 2015 at 21:05
  • 2
    Why does a Soldier need a target immediately upon creation? Why not have a method in Soldier like setTarget(Soldier target) that targets a particular Soldier object and remove target from the constructor? Seems your design might need a little revision. Commented Nov 4, 2015 at 21:06
  • 1
    You should be able to make target a different type then the soldier itself. Commented Nov 4, 2015 at 21:06
  • 1
    you may want to create a Target interface and use that instead of Soldier directly. What if you want to shoot at a building? Commented Nov 4, 2015 at 21:29

4 Answers 4

4

It may be a better idea to store the information about targets in a separate data structure, e.g. a HashMap<Soldier, Soldier>. Then you can make Soldier immutable, and all the circularity problems disappear.

Soldier horseman = new Soldier("Horseman", 20);
Soldier spearman = new Soldier("Spearman", 10);
Soldier archer = new Soldier("Archer", 10);
Map<Soldier, Soldier> targets = new HashMap<>();
targets.put(horseman, archer);
targets.put(archer, spearman);
targets.put(spearman, horseman);
Sign up to request clarification or add additional context in comments.

2 Comments

I really like this solution, although I need to read up on how maps work because Ive never used them. Thank you
Glad I could help. It's a good idea to learn about maps anyway. HashMap is a very popular class.
3

Don't set the target in the constructor. Set it in another method:

Soldier target;
Soldier(String name,double range) {
  // etc
}
public void setTarget( Soldier s ) {
   target = s;
}

Then you can do this:

Soldier horseman = new Soldier("Horseman", 20);
Soldier spearman = new Soldier("Spearman", 10);
Soldier archer = new Soldier("Archer", 10);

horseman.setTarget(archer);
spearman.setTarget( horseman );
archer.setTarget(spearman);

This way each soldier knows about his current target. Then if (for example) horseman vanquishes the archer, you can just call horseman.setTarget(spearman) to set a new target. I was assuming range was the soldier's maximum attack range, but if it is the distance to the target it should not be set in the constructor either.

1 Comment

Although I find Pauls anwser more useful in the long term, this is much simpler for what I need right now, so I am accepting you
2

You could create another constructor (in addition to your already existing one):

Soldier(String name, double range)

and then in your DistanceCalculation method, perform a hasTarget() check.

Comments

0

How about something like:

Soldier Horseman = null;
Soldier Spearman = null;
Soldier Archer = null;
Horseman = new Soldier("Horseman",Archer, 20);
Spearman = new Soldier("Spearman",Horseman, 10);
Archer = new Soldier("Archer",Spearman, 10);

2 Comments

This compiles, but you're still passing null into your constructor. Changing your local variables later to be non-null won't change the value you already passed into the previous constructor.
That will compile, but Horseman won't have the reference to Archer, which I believe is the intent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.