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.
Related
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.
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 ?
I've recently started taking an intro java class(I apologize in advance for my lack of knowledge) and I've run into some trouble. I was required to make a program that contains 3 data fields, 2 constructors, and 4 methods.
I'm having a hell of a time trying to put some input into this, where the user would choose from 1 of the 3 data fields I made up for car prices and choose their vehicle. As far as the constructors go, I made a default one but I'm not sure on how to A) implement another constructor and B) how do I involve the input into this and C) where the methods go in that.
I'm thinking of putting the input first but that ruins my constructors?
I realize I asked a lot, but this is an online class without a text, and I'm basically starving for knowledge. I've included what I got so far below. Feedback is appreciated. Again, I apologize for the lack of knowledge but I'm trying --
public class Vehicle{
int truck;
int car;
int van;
public Vehicle(int t, int c, int v){
truck=t;
car=c;
van=v;
}
public Vehicle(){
truck=0;
car=0;
van=0;
}
}
public static void main (String[] args) {
Vehicle cost= new vehicle(25000,15000,22500);
//*cost.truck=25000; cost.car=15000; cost.van=22500;*//
Vehicle this Vehicle= new vehicle();
Vehicle choice Vehicle= new vehicle(25000,22500);
system.out.println("Default prices are 25000 for a truck, 15000 for a car, and"
+ "22500 for a van, you chose" +
}
}
Based from your question, you must be asking all about how to define classes and use them in general.
Question A. How to implement another constructor?
From your case, I see that you've already define your own constructor, but having problem to define another. To define another constructor, you have to know your parameters that
would be passed.
Here, you have three arguments. (variable t, c, v).
public Vehicle(int t, int c, int v){
truck=t;
car=c;
van=v;
}
Another, constructor with no arguments.
public Vehicle(){
truck=0;
car=0;
van=0;
}
When you define another constructor, you must not define another three arguments constructor of the same type, or another constructor with no arguments.
Therefore, you can have constructor method like this.
public Vehicle(int veh, int price){
switch (veh) {
case 0:
truck = price;
case ...
}
}
Question B. How do I involve the input? Where to involve them in methods
From your problem, this statement is already calling constructor, Which means, you are already involving an input to a class.
Vehicle cost = new Vehicle(25000,15000,22500);
Which is the same as calling a constructor with no arguments, and setting the current prices for the vehicles.
Vehicle choice = new Vehicle();
choice.truck = 25000;
choice.car = 22500;
Now, if you are thinking of is there another way to input datas through methods. It is called Encapsulation. To achieve this OOP concept, you should define data members as Private.
private int truck;
// public int truck; <- not like this.
Then, you can have involve input and probably output. Using the concept of getters and setters. In which you involve methods.
// simple setter
public void setTruckPrice(int t) {
truck = t;
}
// simple getter
public int getTruckPrice(int t) {
return truck;
}
P.S. i forgot to edit its encapsulation.
If you want more information, just refer to these links.
http://docs.oracle.com/javase/tutorial/java/javaOO/classes.html
http://www.tutorialspoint.com/java/index.htm
I'm working on a little project for fun, that's essentially a little combat emulator. I'm trying to use a class similar to struct in C++, as in using it to create an object (in this case, a character or "entity", as the class is called). I'm getting the error in the title when attempting to call any integer in said class from the main function.
class entity{
public int health;
public int accuracy;
public int power;
public int defense;
}
And
public class Tutorial {
static Random rnd = new Random();
entity player;
player.health = 100; // Issue on the health part
player.accuracy = 19; // Issue on the accuracy part
player.power = 15; // Issue on the power part
player.defense = 18; // I think you get it by now...
I've been looking around for a while to find some explanation, but there's none that I could find that explain the nature of the error as well as possible fixes for my situation. If I could get those, it would be wonderful.
The compiler is expecting a variable declaration on the line
player.health = 100;
but is finding an assignment instead. The statements
Entity player = new Entity();
player.health = 100;
player.accuracy = 19;
player.power = 15;
player.defense = 18;
should be in a code block such as a method or constructor rather than the class block
Procedural code cannot be written directly in a class definition. The code is causing syntax errors because it's not legal to do so.
Instead, put the code in an appropriate method or initialization block. (I do not think an initialization block is appropriate here, so I am trivially showing a "factory method".)
As such, consider an approach like
// This is a member variable declaration, which is why it's OK
// to have a (static) method call provide the value.
// Alternatively, player could also be initialized in the constructor.
Entity player = makeMeAPlayer();
static Entity makeMeAPlayer() {
// Create and return entity; the code is inside a method
Entity player = new Entity();
player.health = 100;
// etc.
return player;
}
(I've also cleaned up the type to match Java Naming Conventions - follow suite!)
Here is another way to suffer from highly accurate yet not terrible intuitive messaging for VariableDeclaratorId.
#PostMapping("/showCompany")
public String processForm(#ModelAttribute("company") CompaniesDAO company, company_name, company_function) {
Will produce:
Syntax error, insert "... VariableDeclaratorId" to complete FormalParameter
This is telling you that is need the variable type like String or int...
#PostMapping("/showCompany")
public String processForm(#ModelAttribute("company") CompaniesDAO company, String company_name, String company_function) {
It turns out VariableDeclaratorId is a class
public class VariableDeclaratorId
extends Expression
implements prettyprint.PrettyPrintable
If you read the class description using it with the error message to determine that you forgot to define the variable type, I am impressed; I simply made an educated guess.
It is because you forgot to add the main method,
public class Tutorial {
public static void main(String[] args) {
static Random rnd = new Random();
entity player;
player.health = 100; // Issue on the health part
player.accuracy = 19; // Issue on the accuracy part
player.power = 15; // Issue on the power part
player.defense = 18; // I think you get it by now...
}
}
and
class entity{
public int health;
public int accuracy;
public int power;
public int defense;
}
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);
}
}