I am now working on the AI section of my project. I am calling a method from my AI class which is intended to calculate where the Gladiator objects I have drawn need to actually end up. I passed to that method a List containing all my objects I want to place. A previous method from the AI class has determined where they want to be from each other, distance-wise and I have stored it as gladiator[0..1..2..etc].movementGoal.
Although the project is not real time, ie I will want to just "step" through it in the end, I do want simultaneous movement to occur. This means that my standard method of iterating through the list will not work as I need information about the other Gladiator's movement decisions in order to figure out any one Gladiator's actual movement as these decisions interact.
How can I access another specific gladiator's variables when I am outside the class and only have them in List form?
Edit:
I guess I could iterate through and test for a variable gladiatorNumber to be correct, then when it is pull that info? That would be pretty round-about but its all I can think of.
Edit2:
As requested, some code. My method in Ai class looks like this:
public void moveAI(List<Gladiator> gladiators) {
My gladiator is defined as such:
public class Gladiator {
Gladiator class is created as an array then added into a list in a separate main class. I don't really want to include more code than this, as there is a ton of it. Basically it boils down to how can I call gladiator[0] from AI class even though I created said object in the main class and only have them in list form in the AI class. Assume all variables in Gladiator are public. The error I am getting is cannot find symbol referring to gladiator[0...1...2...etc].
I think your problem boils down to wanting to pass the arrays of gladiators to another class. That should be fairly easy. If you in your main-class have these two defintions (note you only need one, I recommend the list as it is more versatile, arrays have fixed-length).
You want something like this:
public class Main {
// ....stuff
// This is the main class that keeps the list of gladiators
private List<Gladiator> gladiatorsList;
private Gladiator[] gladiatorsArray;
private MovementAI movementAI;
public Main() {
// You initialize gladiatorsList and gladiatorsArray as before
// gladiatorsList = ...
// gladiatorsArrray = ...
// Now you want to pass this list/array to another class (the AI), you
// can do this in the constructor of that class like so:
movementAI = new MovementAI(gladiatorsList);
}
// ...stuff as before
}
The AI
public class MovementAI {
private List<Gladiator> gladiators;
// Giving the class the list-reference, this list will be the same as the
// list in main, when main-list changes so does this one, they point to the
// same list-object, so the reference is only needed once.
public MovementAI(List<Gladiator> gladiatorsList) {
this.gladiators = gladiatorsList;
}
// The class already has a reference to the list from its constructor so it
// doesn't need the list again as a parameter
public void moveAI() {
}
// If you don't want to keep a reference to the list in this class but only
// use it in a method (I would not recommend this)
public MovementAI() {
}
// You need to pass it gladiatorsList everytime you call this method.
public void moveAI(List<Gladiator> gladiators) {
}
}
I see in your last comment that you have decided to let the AI decide to repaint if it meets a criteria, that is not recommended, you should keep responsibilities separate in your classes, less error-prone and better development. It is recommended to let the AI change the list of gladiators (move them, kill them etc) and the rendererclass simply paint every gladiator.
It also seems you want to have every gladiator be able to hold another gladiator as a target, it is better for them to hold the target as an Object, this way you don't have to search the entire list to find out which gladiator the gladiatornumber refers to and you don't have to think about ordering in the list. Something like this:
public class Gladiator {
// ..other stuff
private Gladiator target;
public Gladiator getTarget() {
return target;
}
public void setTarget(Gladiator target) {
this.target = target;
}
}
Related
Suppose I have a class train, two child classes intercity and sprinter which are types of trains. Now say I want to print a list of trains. When it is an intercity it shoud print intercity and when it is a sprinter it shoud print sprinter.
I thought this would imply that I create a method print in intercity and in sprinter. However as the program is iterating throug a list with trains java insists on creating a print method in the class train aswell.
So how do I cope with this. I thought of creating the print method which checks whether it is an instance of intercity or sprinter, then casts it into the corresponding type and then calls the print method of that type.
However I want to become a better programmer and it does not look like the best solution to me.
So my question therefore is how should deal with the above described situation?
You create a print method in the Train super-class and override it in the sub-classes. This way you don't have to check the type of a Train object before printing it, and no casting is required.
public class Train {
public void print ()
{
// here you might have a default printing logic, or you could keep this
// method abstract and leave the implementation to the sub-classes
}
}
public class Sprinter extends Train {
#Override
public void print ()
{
}
}
public class InterCity extends Train {
#Override
public void print ()
{
}
}
I'm having problem understanding "static". I have created class "pizzaMenu" containing ArrayList which contains pizzas. All pizzas are added within that class, and it shouldn't be modified later. But I want to access data about pizzas.
Everything is working properly, but I have to create object of "pizzaMenu" in "main" to make it work.
How can I properly initiate such instances, so I have access to them? But the initiation won't be visible in "main"? I'd like to keep "main" as clean as possible.
but I have to create object of "pizzaMenu" in "main" to make it work.
Yes, you need an instance of new PizzaMenu() in order to access that menu's items.
I'm having problem understanding "static".
Nothing in PizzaMenu should really be static (other than main, if you have it there). But, it basically mean it belongs to the class, and not any one instance of that class.
In other words, if you did make the list of pizzas static, then that says that all menus have the same pizzas, which shouldn't be true, right? Different places have different menus.
Here's an example.
public class PizzaMenu {
private List<String> pizzas = new ArrayList<>();
public void add(String name) {
pizzas.add(name);
}
public List<String> getPizzas() {
return pizzas;
}
// You can also move this to another class
public static void main() {
PizzaMenu menu = new PizzaMenu();
menu.add("Cheese");
for (String pizza : menu.getPizzas()) {
System.out.println(pizza);
}
}
}
All pizzas are added within that class, and it shouldn't be modified later.
You can use this, for example
private final List<String> pizzas = Arrays.asList("Cheese", "Pepperoni");
But, again, I think different instances of menus should have different pizzas.
You can declare pizzas as public static within pizzamenu.
public final static List<pizza> pizzas;
So you can access the pizza using
PizzaMenu.pizzas.
Also you mentioned
I'd like to keep "main" as clean as possible.
I think your concept about clean code is not fully correct.
I am having trouble with the syntax on an iterator I created. I would use a for-each loop, except I need to edit the elements that I would be pulling out of that loop. I created a class called Players which creates a List of 4 Hands(Hand is another class that represents an individual player) in a card game. I am trying to create an iterator for this class, which is giving me trouble. My implementation is as follows:
public class Players
{ ....
public class PlayerIterator implements Iterator<Hand>
{
private final Iterator<Hand> iterator;
private PlayerIterator()
{
this.iterator = players.iterator();
}
....
}
}
As far as I know, my implementation seems correct, based on the fact that I havent received any errors in eclipse. I am, however, having trouble declaring an iterator in the actual program. How would I declare an iterator like that?
Right now this is giving me an error:
Iterator<Hand> it = Players.PlayerIterator();
Hand: The class of variables I am iterating through: a list of 4 Hands
Players: The class that constructs the list of Hands and contains the iterator implementation
PlayerIterator: The class within the Players class that implements the iterator
Does this make sense? I have a very loose grasp on iterators, so if I have not provided enough information I could easily create more.
It is a bit difficult to tell from the code you have posted, but I think you might just be missing a new keyword. I assume you have something like the following outside of the Players class:
Players players = new Players();
where an instance of the Players class has some collection of Hands as one of its fields. In this case what you want to do is this:
Iterator<Hand> iterator = players.new PlayerIterator();
However, it also looks like you might have intended PlayerIterator to be a static class, which would be needed if the Players class has a static collection of Hands:
private static List<Hand> players = new ArrayList<Hand>();
Then you want to do this:
Iterator<Hand> iterator = new Players.PlayerIterator();
If you could post more of your code, it would be easier to guide you to the right solution. Another option might be to make Players implement Iterable<Hand>, which means you can directly loop over a Players instance in a for-each loop.
I don't see the point of creating a Hand iterator when your already have a list of Hands in your class. It's hard to understand what your code is trying to do, but if I understand your scenario correctly, the following should suffice:
public class Players implements Iterable<Hand> {
List<Hand> hands = ...
//...
#Override
public Iterator<Hand> iterator() {
return hands.iterator();
}
//...
}
I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.
===================================================================================================
UPDATE:
My problem was that I did not know that classes can indeed communicate with each other. For example, you can create 2 classes, instantiate an object of each class in your program, and then actually pass one object into the other. This not only directly solved my problem, it opens an entire world of possibilities for the future.
public class FirstClass {
int valueToPass = 100;
void methodToPass(){
//do stuff
return;
}
}
public class SecondClass {
FirstClass passedInObject;
int valueFromOtherClass = passedObject.valueToPass;
return;
}
}
===================================================================================================
I understand a class is a blueprint of attributes and actions that can be instantiated as an object.
I understand an inner class is a non static class defined within another class and has access to the outer class' data.
I understand a child class is a separate file defining a class that does not have access to its parent's data.
So I've got my main activity class of an Android application. I'm just making a simple dice game to help tie up all the loose ends. I've defined the follow child classes in separate .java files:
Dice
ScoreCard
I instantiate an array of 5 Dice objects and 1 ScoreCard object and attach those objects to a "view" in the android OS's window, then assign an action method to that view with the set click listener method inside the object. The objects work flawlessly. I can click the dice and they will hold and unhold themselves, roll, and update their own views. I can of course access the value of the dice from my main class by referencing their object.value variable. (I understand that accessors are presumed by many to be superior to directly interacting directly with a child class' variables, this app is just to solidify conceptual ideas of the overall flow of an application) I can click a slot on the scoresheet and it will toggle the highlight that slot as the slot to assign the score to. The scorecard object also updates the entire scorecard on the screen after each interaction.
So far so good, everything is working great, and I understand everything that is going on.
However, in my main activity class, I now want to create a roll function, and assign that function to the click listener for the roll button. That works, however, when assigning a function to the click listener, you can not reference any non final variables because the click listener of a given view actually instantiates an anonymous object (anonymous class?) of the View class and overrides the onclick method with its own, therefore you can not reference any non final variables from an inner class defined in another method. In other words, you can't pass the function you assign to the click listener any values from your main class, and although I do not understand why, the roll function I created can not access the main class' variables directly.
There is the first gap in my knowledge, and I've read dozens of tutorials, watched dozen's of videos, but I don't know why my roll function can't see the variables.
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll();
}
void roll(){
int funcVar = a;
return;
{
}
Eclipse says that a can not be resolved.
I try to make a public thinking that might allow the function to see it, but if I change
int a=7;
to
public int a=7;
then Eclipse says that it can't be public, only final.
A way around this is to create a new child class called Roll, or perhaps ActionButton to use it for other buttons in the future, just as I did with the ScoreCard and Dice classes. This works great, in so far as I can instantiate a roll button object, assign a view to the object and then set the click listener to one of the object's methods. However, this transfers the functionality of my rollbutton from my MainActivity class to my RollButton class, which doesn't have access to the data in my dice and scorecard objects. In other words, I can't figure out how to make my child classes talk to each other, I don't really think they are even supposed to. I imagine the main class is supposed to access each child class independently, but if that's the case then I'm not really sure what I'm supposed to do at this point.
The only solution I can think of is to put all those child classes into the same child class, DiceGame, and pretty much just use the MainActivity class to instantiate an object of the DiceGame class and transfer processing entirely over to that object. While that would work, all the methods in the class would have access to all the data in the class, it seems to contradict the entire purpose of object oriented programming.
Is this all so messed up because of the way the click listener in android apps is assigned through instantiating an anonymous inner class that can't access any non final variables, or I just missing a key concept in the way Java applications are structured?
I'm sorry this is so long, but I really couldn't shorten it and still convey the entire problem.
-------edit----------
public class MainActivity extends Activity {
public int a=7;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// my application starts here
Dice[] gameDice = new Dice[6];
for (int i=1;i<6;i++) gameDice[i]= new Dice();
for (int i = 1; i<6 ; i++){
gameDice[i].dieView = (ImageView) findViewById(R.id.die1 + (i-1));
gameDice[i].setListener();
}
int[] slotId = new int[] {R.id.val1,
R.id.val1,R.id.val2,R.id.val3,R.id.val4,R.id.val5,
R.id.val6,R.id.valsubtotal,R.id.valbonus,
R.id.val3k,R.id.val4k,R.id.val5k,R.id.valfh,
R.id.valsmstr,R.id.valstr,R.id.valdicey,R.id.valtotal
};
ScoreCard scoreCard = new ScoreCard();
scoreCard.NUMBER_OF_SLOTS = slotId.length;
for (int i=1 ; i<scoreCard.NUMBER_OF_SLOTS ; i++){
scoreCard.slotView[i]=(TextView) findViewById(slotId[i]);
if (i!=8 && i!=15) scoreCard.setListener(i);
}
scoreCard.initScoreCard();
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
roll();
}
});
}// end of overridden method
void roll(){
//do stuff
int funcVar = a; // can totally see a now that it is higher scope
return;
}
}//end of class
The suggestion to increase the scope of a did in fact work. However, a is just an example I was using for simplicity's sake. I really need to access those data contained in the objects I instantiated, and if I instantiate them in a higher scope the application abruptly ends upon launch.
Perhaps the confusion is between a variable and a field. A field is a property that is associated with an object. A variable exists only in the context of a method. When the method finishes, the variable vanishes.
A field, on the other hand, looks exactly the same as a variable except that a field is declared outside of any method, directly on the class "body". Fields and methods are declared at the same hierarchical level. You can see that on Eclipse. Check the "outline" view.
If you need several methods to read and write the same "variable", then what you need is a field. I hope this clarifies.
Variables can have different scopes:
public class MyClass {
static int a; // variable bound to class MyClass, seen from all instances
int b; // variable bound to instance, each instance of MyClass has its own value
public void foo(int c) { // parameter variable: local
int d; // local variable
}
}
Local variables in a method are visible only within the same method invocation (so each time foo() is invoked, new local variables are used).
Values can be passed indirectly by storing them in instance or class variables (global variables), but that's ugly and error prone. The better variant is to pass the values as method arguments, this works well with multiple invocations and also multiple Threads, and removes the side effects you'd have when passing values using global variables.
In your example, just pass the value of a to your method:
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll(a);
}
void roll(int funcVar){
// funcVar is whatever value was passed, here: 7
return;
{
}