Recently I asked a question about why all my variables in spawned items were being set to the same damage value (Java switch statements outputting the same numbers) and that code wasn't to blame, however after some deep debugging i've found that when an item is spawned it randomises the damage and then for some reason sets that damage to every previously created item of the same type.
I have 'dagger' and 'sword' classes which extend my 'item' class. This is how I set the damage:
case 3: {Sword sword = new Sword(); World[X][Y].treasureName = "sword"; sword.setDamage(4); returnItem = sword; break;}
And this is my item class:
public abstract class Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
And my sword class:
public class Sword extends Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
I'm not sure what this problem is called and not sure what to google being fairly new still. I tried to override the item class but that didn't change anything and i've read about inheritance and I don't understand which part is setting every other weapon instance to the same damage. I wanted to remove the methods in the 'Item' class to see if that would fix it, however other code causing errors prevented me to do this when checking and adding together the damage of all the children of 'Item' - this required a cast of (Item) and i'm not sure of what else I can use as a cast.
Here are the referrals to the 'Item' method:
if (((Item) World[k][i].treasure).getDamage() > 9)
{
Without the cast the error is: getDamage() is undefined for the type Object.
and:
//Recalculates the players damage for recently equipped items.
for (int i = 0; i < numItems; i++) {
itemdamage += items[i].getDamage();
System.out.println("You have a " + itemNames[i] + " giving you " + items[i].getDamage() + " extra damage.");
}
What's wrong? I want to understand this so links to helpful information on why, and what i'm doing wrong would be good. Thanks.
static int damage = 0;
Having a static member means that all objects of the class same the same value. If you remove the static keyword, each object will be able to have a different value for damage.
As to the required cast, it seems that World is an array of Object type. Therefore World[k][i] is of Object type, and you can only call methods of the base Object class on it. If you want to call a method defined in the Item class, you must cast the Object to an Item (assuming the runtime type of that Object is an Item).
Your damage and defense variables should not be static. A static variable is tied to the whole class, not to any one instance of the class. As such, when you call setDamage(), even though the method is an instance method, it updates a static variable which is shared by every existing instance.
Remove the static (did you mean to use protected?) and you won't see the "for some reason sets that damage to every previously created item of the same type" behavior anymore.
See What does the 'static' keyword do in a class? for more. Here's the official Java Language Specification on static fields, as well.
You set the variables damage and defence (spelling mistake here - by the way) to be static. Which means that there's only one copy of each variables for the entire class.
Remove the static keyword before the declaration of both variables - and it'll make any new sword instance (object) - carry its own damage and defence.
Heyhey Fluidic,
I'm still fairly new to Java myself, but I think your problem is that your damage variables are set to static (and I would assume the problem would persist across your defence stats as well!)
I had this problem while learning to develop in C++. I would change a value of one of my constructors which referenced a static variable, and all of the instances would change. It's a constant belonging to the class itself, not the object.
So what's happening, is when you change the damage value; all references that use that static damage variable are being changed.
This site gives a bit of an insight on static variables!
http://www.javatpoint.com/static-keyword-in-java
Lemme know if that helps!
Andy
According to the error :
getDamage() is undefined for the type Object
I think you World array, is an array of Object instead of Item
Could you show us how you manage the World array ?
Related
This is probably a really silly question, but I figured I'd try asking! Basically the question is this: can I use a switch statement in my setters?
Here's what I'm doing: I've created a Monster class with the attributes of healthPoints, description, damage, and type, in which type is an enum. In my driver, I've written a few lines of code that will randomly generate a monster type from the enum values, and it will create a new monster using that type.
The issue is that when I display the monster stats, it shows healthPoints and damage as 0, and description as null. When I try to run the program using the default Monster constructor, it crashes and shows a NullPointerException error.
I think the error is in either my setters or the constructors. Each of the setters has a switch case inside, which sets a certain number of healthPoints, damage, and a specific description depending on the type of monster that is randomly generated. I'm not sure if it's even okay to use a switch statement in a setter because I've never really had to before.
Here is some of my code. First, my constructors.
public Monster(int healthPoints, monsterType type, int damage, String description)
{
setHealthPoints(healthPoints);
setType(type);
setDamage(damage);
setDescription(description);
}
public Monster(monsterType type)
{
setType(type);
}
Below is one of the setters.
public void setHealthPoints(int healthPoints)
{
switch(type)
{
case DROW:
healthPoints = 30;
break;
case LICH:
healthPoints = 40;
break;
case ORC:
healthPoints = 20;
break;
case OWLBEAR:
healthPoints = 20;
break;
case RUST_MONSTER:
healthPoints = 10;
break;
}
this.healthPoints = healthPoints;
}
And below is the line in the driver that creates the monster.
int number = new Random().nextInt(monsterType.values().length);
Monster monster = new Monster(monsterType.values ()[number]);
I want the monster's healthPoints, damage, and description to be set depending on the type of monster that is generated. I'm not sure if this can be done using switches in the setters, and I feel like my mistake is probably obvious and I'm just not seeing it because I've been staring at it for a long time...or, if there's a different or easier way to do this, please let me know! Thank you for taking the time to read; I tried to make my question/problems thorough.
Explanation
Yes you can use switch cases in the constructor and in methods. The issue is that you are calling setHealthPoints before setType but the first methods uses the type in its switch statement:
setHealthPoints(healthPoints);
setType(type);
Therefore the variable type is uninitialized when you visit the switch of setHealthPoints and thus currently null.
A switch statement will throw a NullPointerException if its argument is null. Thus you get the NPE.
You can fix this by first executing setType.
Advice on game architecture
You should create a more readable structure that is also easier to maintain and especially easy to extend.
Therefore consider creating a Monster interface or abstract class. After that create explicit monsters as subclasses. The class Monster will contain everything that is equal among all monsters, try to abstract from specific monsters. The monsters themselve will then only contain what differentiates them from the rest.
For example you could use some kind of this:
public abstract class Monster {
private int mHealthPoints;
private int mDamage;
private String mDescription;
public Monster(int healthPoints, int damage, String description) {
this.mHealthPoints = healthPoints;
this.mDamage = damage;
this.mDescription = description;
}
public int getHealthPoints() {
return this.mHealthPoints;
}
public int getDamage() {
return this.mDamage;
}
public String getDescription() {
return this.mDescription;
}
}
And then you have specific monster classes like
public class Orc extends Monster {
private static int HEALTH = 20;
private static int DAMAGE = 10;
private static String DESCRIPTION = "Nasty orc.";
public Orc() {
super(Orc.HEALTH, Orc.DAMAGE, Orc.DESCRIPTION);
}
}
You also don't need that monsterType enum anymore since you can differentiate via monster instanceof Orc. However for a really modular design you shouldn't work on specific classes. Instead use a lot of interfaces that describe properties and abilities.
For example interfaces like:
CanAttack
IsAttackable
HasHealth
CanWalk
CanFly
CanCollide
...
Your game logic then may be built only on those interfaces. For example CanAttack could look like:
public interface CanAttack {
void attack(IsAttackable target);
}
The huge advantage is that you then can easily extend your game. For example by creating monsters with arbitrary combinations of abilities:
public SuperFlyingPig extends Monster implements
CanAttack, HasHealth, CanWalk, CanFly {
...
}
And it magically will work without any additional coding effort since your logic will not care for the specific monster. It will only work on the interfaces.
General part first:
This is for my Java 1 final: I need to make an NFL playoff simulator. So, I would make a "Team" object that holds values for "Offense" and whatnot. I would need a method that holds an algorithm to calculate who wins each matchup. However, I don't know how to go about applying the method to the appropriate teams..
I was going to make another object called "Matchup" which would hold 2 "Team" objects, then comparing the 2 teams' values with the algorithm method. But, I don't think you can use objects inside another object, to my knowledge... Therefore, I've just been trying to hard-code everything in an ugly way.
Would anyone point me in the right direction of forming such a program?
Anyway, on to my immediate issue:
Here is my small bit of code thus far..
public class Final_Larrabee {
static Team pit = new Team("Steelers", "AFC", 3, 75, 70);
static Team bal = new Team("Ravens", "AFC", 6, 70, 80);
static String teamA1 = "bal";
public static void main(String[] args) {
System.out.println(+teamA1.seed);
}
}
And my other class:
package final_larrabee;
public class Team {
String name;
String conference;
int seed;
int offense;
int defense;
boolean wcWin;
boolean divWin;
boolean conWin;
boolean alive;
public Team(String n, String c, int s, int o, int d) {
name = n;
conference = c;
seed = s;
offense = o;
defense = d;
wcWin = false; // these wins will be used in the betting part
divWin = false;
conWin = false;
alive = true; // determines if team is out of playoffs or not
}
public String getName(){
return this.name;
}
public void setName(String n){
name = n;
}
public int getConference(){
return this.seed;
}
public void setConference(String c){
conference = c;
}
public int getSeed(){
return this.seed;
}
public void setSeed(int s){
seed = s;
}
public int getOffense(){
return this.offense;
}
public void setOffense(int o){
offense = o;
}
public int getDefense(){
return this.defense;
}
public void setDefense(int d){
defense = d;
}
}
I realize this won't work, because it is trying to access teanA1's seed value (which doesn't exist of course). But, what I wanted was to simply call the bal.seed value. I wanted to do it this way so that later, I can use teamA1 and teamA2 variables for the 2 teams in a given matchup. Is there a way to do it this way?
If not, perhaps ideally, it would be best to create a Team object called teamA1 which holds the values of whatever team I need at the time. It would need to change like a variable instead of make a million objects every time I need it (ideally..) I found the method 'clone' but I'm not sure this is what I want?
Any help, be it to my immediate question, or the general layout of my program, would be much appreciated. Thanks!
make team implements comparable this will give you the ability to write compareTo method and then you can put you win condition based
Just as your class Final_Larrabee holds 2 team objects in your code, your matchup class can also hold other objects.
Yes, you're on the right track with the idea of creating a matchup class which holds instances of team objects.
Inside your main class you can initialize 2 team objects. I would then create a matchup object, which gets passed the 2 team objects you have previously created and do some functionality.
Inside your team class you could implement a method, which returns a score based on the teams stats. For example it could calculate the offense * defence * seed or something like and return it that and then inside your match class, you can then implement a method such as playGame() which calls the getScore() method of each object and compares the values and then returns the winner (or prints them out for simplicity).
As regards your code, you're using the keyword static. Static is a keyword which changes a variable/object/method to a class variable/object/method. This means that every instance of the class shares this variable. I would not use it for creating the teams. An example of where to use static (a very basic example), would be if for some reason you needed to keep track of the amount of team objects you created. You could implement a static COUNT variable inside the team object and increase it by one every time the constructor is called. This could also be used for assigning IDs to the teams.
static int TEAM_COUNT = 0;
public Team()
{
this.id = ++TEAM_COUNT;
}
This would make the TEAM_COUNT be a value which shared by all instances of the class team. If you were to call
teamA.setTeamCount(0);
Then every other instance of Team would also be reset to 0.
Edit: With regards to your playoffs
public static void main(String args[])
{
Team team1 = new Team("parameters required here");
Team team2 = new Team("parameters required here");
Playoff p = new Playoff();
p.add(team1);
p.add(team2);
p.startPlayoffs();
}
If you create all of the objects inside the main class, then they are available to that method as they are local. When you call p.add(), you can add them to an array or collection, which is inside the Playoff class. Your startPlayoffs() method can then process the array of objects already stored inside the class.
so I'm making a card game.
I have an arrayList of type player in my main, and I have filled it with a certain type of player (in this case, a good player - good player being a subclass of player with a couple of additional methods)
I may just be brain dead from looking at this for too long however heres my code.
I create 4 good players - again - goodPlayer extends player
ArrayList<Player> players = new ArrayList<>();
for (int i = 0; i < 4; i++)
{
goodPlayer gp = new goodPlayer();
players.add(gp);
}
Then after a couple of methods are called I want to call a method from goodPlayer called count, on each of the goodPlayers in players arrayList
for (Player p : players)
{
count(p.getHand());
}
what am I doing wrong as what I currently have is incorrect, unless I make count static and call goodPlayer.count however I do not want the class to act in a static context.
Thanks.
Why don't you use type casting? You don't need to make count method a static one to use it. If you are 100% sure that all players in that list will be from GoodPlayer class (by convention, class names start with a capital), then just cast it as
((GoodPlayer) player).count();
If you're not sure if all players will be from the class GoodPlayer, then add a test to avoid a runtime error:
if (player instanceof GoodPlayer) {
((GoodPlayer) player).count();
}
A solution would be to add a method on your abstract player class and implement that differently in your derived types of player. For example:
public abstract class Player
{
public abstract int count();
}
public class GoodPlayer extends Player
{
public int count()
{
return totalHandsPlayed * 3; //Or something meaningful;
}
}
This example is showing the you have a base class that asks any inherited classes to implement the methods defined as abstract. (in this case count).
If your players list is always going to hold GoodPlayer objects, then it would be best to have it as a a list of GoodPlayers
Otherwise, the answer given by user mehmetakcay best suits your purpose.
though the information you have provided seems to be little bit abstract but you can do in following manner (using downcasting, though its not recommended):
for(Player p:players){
GoodPlayer gp=(GoodPlayer)p;
gp.count();
}
Sorry if the title was worded incorrectly, please change it if it's not quite what I describe here.
So I am creating a program to simulate some fictitious creatures, and I need many objects that all store different statistics about each individual creature with values that can all be checked at the same time. What would be the correct way to go about doing this?
For reference, here is the code that I have right now.
public class Model {
static int mfood;
static int mdefense;
static int mattack;
static int mhealth;
static int msize;
static int magg;
static boolean update = false;
public Model(int food, int meat, int defense, int attack, int health, int agg) {
mfood = food;
msize = size;
mdefense = defense;
mattack = attack;
mhealth = health;
magg = agg;
}
The problem is, of course, that I have variables that store the values that are put into the constructor that are changed each time the constructor is called. This works well if I have only one object running at a time, but I will have around a dozen, most likely. These values need to be called in other methods as well, such as
public void Attack() {
mhealth = (mhealth + mdefense) - mattack;
}
The mattack variable would be a different object from the mhealth and mdefense variables.
Thanks for any help I can get, I'm sure this is a simple fix, but I can't find the answer anywhere.
Your variables are static, meaning they exist at the class level, not the individual object level. This means no matter how many objects you create (new up), they all share the same variables. Remove the static keywords and each object will have it's own copy of the variables.
Just doing a quick edit up at the top of my post.
The question is if i extend a class and both classes have the same variable why is the extended class getting the original classes value.
This has been answered but would be more than happy to read more information about this.
Polymorphism isn't a strong suit of my so i'm having to relearn this stuff after not using it for months.
So i'm trying to program a game and one of the requirements is some type of list of object that can be scanned in a loop. The trouble starts with my test of ArrayList. I have 3 classes i made to be added in to my array list. Entities, Monster extends Entities, and Character extends Entities. do note Monster and Character both extends Entities class.
I decided that i should make the ArrayList and added new objects directly in to each element(the word element is normally used with array not ArrayList correct?) and use a log function i programmed to note down values of the objects in the ArrayList.
I made a for loop and ran both Monster and Character .getHP() method that they inherited from Entities and the results was the HP from Entities not Monster or Character unless i added a new value to the classes HP using the setHP(int i) method also inherited Entities.
Since my program requires most of the classes and we only need about 99% i decided to make a test project to basically do the above in a smaller form since i don't want to be copying pasting 20 or more .java files here. Anyways here's my test classes and results.
import java.util.ArrayList;
// class to test interactions between Extended classes
public class testHP {
ArrayList<Entities> ent = new ArrayList<Entities>();
public static void main(String[] args) {
///make reference varaible so i don't have to make test() and ent static.
testHP hp = new testHP();
hp.test();
}
void test(){
/// the 3 classes to the arraylist. I could of made a reference variable but didn't.
this.ent.add(new Character());
this.ent.add(new Monster());
this.ent.add(new NPC());
///prints out whats in the array list so i know that i have the correct objects.
System.out.println(this.ent);
/// this prints out { ent(i) HP "is" i } to tell which class is being called and it's HP at this point.
for(int i=0; i<ent.size();i=i+1) {System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
/// this adds i plus 10 then does the same as the last for loop.
for(int i=0; i<ent.size();i=i+1) {
this.ent.get(i).gainHP(i+10);
System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
}
}
abstract public class Entities {
private int HP = 1;
int getHP(){
return HP;
}
void gainHP(int hp){
HP = this.HP + hp;
}
}
///Character is to show what happens when i change the value and make it static.
public class Character extends Entities {
private static int HP = 4;
}
///monster is to show a changed variable from the super which is entities.
public class Monster extends Entities {
private int HP = 4;
}
/// NPC is a class that just to have variables from entities class that aren't edited or made static.
public class NPC extends Entities {
}
here is my results with these files as they are above. I should have put HP next to the number to the left but you get the idea.
[Character#67f1fba0, Monster#3fbefab0, NPC#133c5982]
1 is Character#67f1fba0
1 is Monster#3fbefab0
1 is NPC#133c5982
11 is Character#67f1fba0
12 is Monster#3fbefab0
13 is NPC#133c5982
My test class for the original ArrayList looks like this.
import java.util.ArrayList;
public class AreaMap extends Map {
String CLASS = "Area Map";///log requires.
ArrayList<Entities> ent = new ArrayList<Entities>();
AreaMap(){
Log.Logging(CLASS,"Testing arrayList");
//random text added to the array.
ent.add(new Character());
ent.add(new Monster());
Log.Logging(CLASS, "ent 1 has " +ent+ " in it");
for(int i=0; i < ent.size();i = i+1){
Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
}
for(int i=0; i < ent.size();i = i+1){
this.ent.get(i).setHP(10+i);
Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
}
}
}
And here are my result from that.
[Area Map]##[Testing arrayList]
[Area Map]##[ent 1 has [Character#2bd1e730, Monster#61a116c9] in it]
[Area Map]##[ArrayList 0 i=0]
[Area Map]##[ArrayList 0 i=1]
[Area Map]##[ArrayList 10 i=0]
[Area Map]##[ArrayList 11 i=1]
Do note that "Log" is a class i made and the method is "static Logging(String origin, String Action){System.out.println([origin]+"##"+[Action]);"
origin is always the class not that it has to be.
Sorry if this isn't clear. If you need more information to help me i'm more than willing to answer.
Basically the problem is that you're trying to declare extra variables in subclasses as if they can "override" the variable in the superclass. Variables don't work that way - they're not polymorphic.
If you need to give each class a different starting number of hit points, I suggest you create a protected constructor in Entities (which should be renamed, btw - e.g. AbstractEntity) to take the initial value of HP (which should probably be renamed hitPoints). Then each subclass would have a public constructor to call the superconstructor with an appropriate value.
For example:
public abstract class AbstractEntity {
private int hitPoints;
protected AbstractEntity(int initialHitPoints) {
this.hitPoints = initialHitPoints;
}
public int getHitPoints(){
return hitPoints
}
void gainHitPoints(int amount) {
hitPoints += amount;
}
}
public class Monster extends AbstractEntity {
public Monster() {
// Every monster starts off with 4 hit points
super(4);
}
}
Now that's just a matter of changing the initial state. If you wish the different entities to behave differently, you should override the abstract class methods within the subclasses.
I believe your problem is scoping. The HP that Entities* is accessible from your getHP, but your HP in Character and Monster are different variables that happen to have the same name. Additionally, marking HP as private means that subclasses can't access that variable - I think you have protected.
What is probably the correct solution to get rid of HP in Monster and Character, make HP in Entities protected, and set the default HP in the default constructor for Monster and Character.
* It's good style to name your objects in the singular, so this is better named as Entity.
If I understand it correctly, the problem is as follows:
You declared the attribute HP as private in class Entities and declared a new(!) variable in the subclass (see the other answers).
You can resolve the behavior by setting HP by a constructors, e. g.,
class Entitites {
private int HP;
public Entities(int hp) {
this.HP = hp;
}
}
class Monster extends Entities {
public Monster() {
super(4);
}
}