I want to code a little text adventure/dungeon crawler type of game. At the moment I have the classes Creature, Player, and Enemy. The classes Player and Enemy are subclasses of Creature.
I want to make the level of the enemy dependent on the level of the player. So for example, the enemy's level should always be 1 level above the player's level. So when the player is level 4 you should only be able to face enemies which are level 5.
My idea was to put something like this in the constructor of the Enemy class:
public Enemy(String name, int hp, int atk, int exp) {
super(name, Player.getLevel + 1, hp, atk);
this.exp = exp;
}
But that is clearly not allowed. Now I have no idea how to achieve this result. I lack some basic understanding of Java, but I'm willing to learn.
My code looks like this at the moment. I left the getters and setters out for better readability.
public class Creature {
private String name;
private int level;
private int hp;
private int atk;
public Creature (String name, int level, int hp, int atk){
this.name = name;
this.level = level;
this.hp = hp;
this.atk = atk;
}
}
public class Player extends Creature {
private int currentEXP;
private int expBar;
public Player(String name) {
super(name, 1, 100, 10);
this.currentEXP = 0;
this.expBar = 50;
}
}
public class Enemy extends Creature {
int exp;
public Enemy(String name, int level, int hp, int atk, int exp) {
super(name, level, hp, atk);
this.exp = exp;
}
}
First of all, the private modifier makes level unavailable in the subclasses. To solve that, you can either make change private to protected (or nothing / default), or you can provide an accessible getter method (int getLevel() { return level; }).
Your Enemy constructor takes a level argument, so to implement the player level + 1 feature, you can simply pass player.getLevel() + 1, alternatively pass player.getLevel() and let the constructor take care of adding 1.
The method using these classes (assuming main for now) would look something like this:
public static void main(String[] args) {
Player p = new Player("Player1");
Enemy e = new Enemy("Enemy1", p.getLevel() + 1, 100, 10, 40);
}
To clarify, the reason why Player.getLevel + 1 doesn't work is because Player is a class, but you need a Player object (i.e. the result of calling new Player(...)) to refer to instance fields or methods, such as getLevel.
Related
I have 4 motors let's say, and for each, I have some constants like the ID, the maximum speed, and the minimum power. Let's say that at some point there are going to be many constants added to this MotorConstants class, and this is what it currently looks like:
public abstract class MotorConstants{
abstract final int ID;
abstract final double MAX_SPEED, MIN_POWER;
}
// And an implementation:
public class LeftMotorConstants extends MotorConstants{
final int ID = 3;
final double MAX_SPEED = 500, MIN_POWER = 10;
}
I understand that abstract fields are not possible. What could be a good replacement for them?
I'm afraid of passing everything through the constructor/getters and setters because then after adding a field would take a lot of time and lots of lines of code, instead of the (not working) code sample.
Constants cannot be inherited and then overwritten; that defeats the purpose of calling them "constant. Methods can be overridden to return differing values (even if they return an external constant variable).
If I understand your data model, and ID belongs to a specific instance of some "part". The other fields are also specific properties to some instance, which should not belong to the overall class, so that would be done with methods.
This is where you'd use interfaces to define those common "templates" that a class needs to implement.
E.g.
interface LimitedPower {
double getMinPower();
}
interface LimitedSpeed {
double getMaxSpeed();
}
interface Identifiable {
int getId();
}
abstract class AbstractMotor implements Identifiable {
protected int id; // available to all subclasses
#Override
public int getId() {
return this.id;
}
}
class LimitedMotor extends AbstractMotor implements LimitedSpeed, LimitedPower {
private double minPower, maxSpeed;
public LimitedMotor(int id, double minPower, double maxSpeed) {
this.id = id;
this.minPower = minPower;
this.maxSpeed = maxSpeed;
}
// TODO: implement interface getter+setter functions
}
class MotorPowered {
final AbstractMotor[] motors = new AbstractMotor[4];
public MotorPowered(AbstractMotor left, AbstractMotor right, AbstractMotor top, AbstractMotor buttom) {
this.motors[0] = left;
//... etc
}
}
Then, when you actually create a specific motor, you can pass in the details for it.
final AbstractMotor left = new LimitedMotor(3, 10, 500);
MotorPowered engine = new MotorPowered(left, ...);
If you want to say "all 'limited motors' will have the same id", then you can add some final static int ID to that class, and remove the constructor parameter.
class LimitedMotor extends AbstractMotor implements LimitedSpeed, LimitedPower {
private double minPower, maxSpeed;
public static final int ID = 3;
public LimitedMotor(double minPower, double maxSpeed) {
this.id = LimitedMotor.ID;
this.minPower = minPower;
this.maxSpeed = maxSpeed;
}
I'm making a game right now and I'm trying to setup a CreatePlayer method.
In the main class, I take the Player class as an object to get its variables, methods ect.
package com.deud07.main;
import com.deud07.player.Player;
public class Main {
public static Player player = new Player("Bob", 86, null);
public static void main(String[] args) {
System.out.println(player.Position);
}
}
The 3rd parameter of Player is the Position, which is an array.
The problem I'm having is that I'm not sure how to set each element of the array without writing:
position[0] = 1f;
position[1] = -6f;
position[2] = 0f;
The code for Player:
package com.deud07.player;
public class Player {
public static String Name;
public static int ID;
public static float x;
public static float y;
public static float z;
public static float[] Position = {x, y, z};
public Player(String name, int id, float[] pos) {
Player.Name = name;
Player.ID = id;
Player.Position = pos;
}
public void createPlayer(String name, int id, float[] pos) {
Player player = new Player(name, id, pos);
player.Name = name;
player.ID = id;
player.Position = pos;
}
}
Any solutions? And while you're at it, anything I can do to fix up my code?
I believe you're asking for a shorthand method. You might also find them as "one liners". The way to initiate an array in one line without a variable is as follows:
Player player = new Player("Bob", 86, new float[]{1f, -6f, 0f});
As for "fixing your code", it goes outside of the actual question you've posted. Two things I can say are
Java conventions state that variables must be camel case. So your Player class' attributes should be name, id and position.
Your method createPlayer() does exactly the same the constructor does, thus it is not necessary. To create a new Player, just use... well, new Player().
Also, x, y and z are kind of useless. If you need x for example, just use position[0] instead.
So I just started with java, so this is just a simple problem ig, but I have to make a small project for school. I made 2 classes, one called Pokémon and one called trainer. In the Pokémon class I made a constructor and a method to create objects, because I couldn't just create the object:
public class Pokemon {
public String name;
public String typ;
public int maxLp;
public int aktLp;
public int ap;
public Pokemon(String pname, String ptyp, int pmaxLp, int paktLp, int pap) {
name=pname;
typ=ptyp;
maxLp=pmaxLp;
aktLp=paktLp;
ap=pap;
}
public void CreatePokemon(String[] args) {
Pokemon Squirtle = new Pokemon("Squirtle", "Water", 20, 20, 5);
Pokemon Charmander = new Pokemon("Charmander", "Fire", 20, 20, 5);
}
}
In the other class, Trainer, I wanted to use these created objects (Pokemon Squirtle and Pokemon Charmander) to let them fight, the "fight" is basically just one pokemon, I wanted to use Squirtle in the function Squirtle attack, attacking Charmander dealing as much damage as declared in ap, changing the variable aktLp in the object Glumanda, which is the current hp of glumanda:
public class Trainer
{
public String name;
public String gender;
public int money;
public int amountPokemon;
public int amountFights;
public Trainer(String tname, String tgender, int tmoney, int tamountPokemon, int tamountFights) {
name=tname;
gender=tgender;
money=tmoney;
amountPokemon=tamountPokemon;
amountFights=tamountFights;
}
public void ChooseSquirtle() {
System.out.println("You choose Squirtle!");
}
public void ChooseCharmander() {
System.out.println("You choose Charmander!");
}
public void SquirtleAttack() {
System.out.println("Squirtle attacks Charmander!");
Charmander.aktLp = Charmander.aktLp - Squirtle.ap;
}
}
So for this project I have to use - even if I don't like it - BlueJ. BlueJ says: "cannot find symbol - variable Glumanda" - but why? Do I have to call the method CreatePokemon() ? Well I thought I had to and added CreatePokemon(); ,pressed compile and there was another error, but there is no explanation whatsoever. I can't find the problem even though it might be easy. As I said I pretty much just started with java so tips are appreciated - also, I tried my best translating the variables, sorry if you don't understand them and if they are inacurrate.
Your code is not very abstract and has a few flaws:
You're creating pokemon object inside the pokemon class definition. What you should do instead is create it in some higher level method, e.g.: main.
The trainer class uses two pokemons to attack each other. The problem is, the pokemon classes have not been instantiated in a scope that trainer can access. What you should do instead is either instantiate a new pokemon inside the trainer class, or pass pokemon objects as parameters to the generic attack function.
The trainer class could like this with instantiating new pokemon inside.
class Trainer {
public String name;
public String gender;
public int money;
public int amountPokemon;
public int amountFights;
private Pokemon squirtle;
private Pokemon charmander;
public Trainer(String tname, String tgender, int tmoney, int tamountPokemon, int tamountFights) {
name = tname;
gender = tgender;
money = tmoney;
amountPokemon = tamountPokemon;
amountFights = tamountFights;
squirtle = new Pokemon("Squirtle", "Water", 20, 20, 5);
charmander = new Pokemon("Charmander", "Fire", 20, 20, 5);
}
public void ChooseSquirtle() {
System.out.println("You choose Squirtle!");
}
public void ChooseCharmander() {
System.out.println("You choose Charmander!");
}
public void SquirtleAttack() {
System.out.println("Squirtle attacks Charmander!");
charmander.aktLp = charmander.aktLp - squirtle.ap;
}
}
Or like this with accepting pokemons as parameters:
class Trainer {
public String name;
public String gender;
public int money;
public int amountPokemon;
public int amountFights;
public Trainer(String tname, String tgender, int tmoney, int tamountPokemon, int tamountFights) {
name = tname;
gender = tgender;
money = tmoney;
amountPokemon = tamountPokemon;
amountFights = tamountFights;
}
public void SquirtleAttack(Pokemon attacker, Pokemon defender) {
System.out.println(attacker.name+" attacks "+defender.name+"!");
defender.aktLp = defender.aktLp - attacker.ap;
}
}
public class Main {
public void CreatePokemon(String[] args) {
Pokemon squirtle;
Pokemon charmander;
squirtle = new Pokemon("Squirtle", "Water", 20, 20, 5);
charmander = new Pokemon("Charmander", "Fire", 20, 20, 5);
}
}
Just a couple of hints:
Not sure what your project structure is, but you cannot have 2 public classes in a single file. Public class has to have the same name as filename. You can, however, have multiple non-public classes in a single file. But generally it is not recommended to define multiple classes in a single file anyways.
Per Java naming conventions, you should name variables or object instances beggining with lowercase letter. Read more: https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html
Try to use public class properties as least as possible and private as often as possible. To manipulate private properties values, use getters and setters. more info here: https://www.freecodecamp.org/news/java-getters-and-setters/
I am rather new to Java, rather only a week's worth of learning so I am still very inexperienced. I have spent a few days on polymorphism and know that I can extend a parent class to a child class, but I would like to know how to have a grandparent class have all the attributes of the parent classes. I have done a bit of research but haven't found what I was looking for. What I am working on is creating objects of clothing. I have one grandparent which is 'Clothing' three parents 'Upper_wear', 'Lower_wear', and 'Shoes' with many children such as 't-shirts', 'shorts' and 'sandals'. Currently what I have in the parents code is:
public class Upper_wear
{
private String fabric;
private int numb_zippers;
private String draw_string;
private int numb_pockets;
private int size;
private String color;
private double length_sleeves;
private int length_shirt;
private String collar;
private String hood;
private int code;
private double price;
private String name;
Upper_wear(String fabric,int numb_zippers,String draw_string,int numb_pockets,int size,String color, double length_sleeves, int length_shirt, String collar, String hood, int code, double price, String name){
this.fabric = fabric;
this.numb_zippers = numb_zippers;
this.draw_string = draw_string;
this.numb_pockets = numb_pockets;
this.size = size;
this.color = color;
this.length_sleeves = length_sleeves;
this.length_shirt = length_shirt;
this.collar = collar;
this.hood = hood;
this.code = code;
this.price = price;
this.name = name;
}
public String get_fabric(){
return fabric;
}
public int get_numb_zippers(){
return numb_zippers;
}
public String get_draw_string(){
return draw_string;
}
public int get_numb_pockets(){
return numb_pockets;
}
public int get_size(){
return size;
}
public String get_color(){
return color;
}
public double get_length_sleeves(){
return length_sleeves;
}
public int get_length_shirt(){
return length_shirt;
}
public String get_collar(){
return collar;
}
public String get_hood(){
return hood;
}
public int get_code(){
return code;
}
public double get_price(){
return price;
}
public String get_name(){
return name;
}
}
And for the children's code I have:
public class Jacket extends Upper_wear
{
Jacket(String fabric,int numb_zippers,String draw_string,int numb_pockets,int size,String color, double length_sleeves, int length_shirt, String collar, String hood, int code, double price, String name){
super(fabric, numb_zippers, draw_string, numb_pockets, size, color, length_sleeves, length_shirt, collar, hood, code, price, name);
}
}
The reason why I don't just extend clothing with all the variables is because I don't want to state if or not 'Upper_wear' has 'Shoe_laces' which is a variable in 'Shoes'. Yet, I want to gather all parent classes into one because when I go to the run class. In the for loop, I want to list out the prices of every item of Clothing and not just of a parent class. I feel that I am limited to only iterating through one parent class at a time such as what I currently have:
public class Run
{
public static void main (String[]args){
Shoes Tennis_shoes_01 = new Shoes("Canvas", 0, "yes", 10, "red and white", 0,0.5,2.5, 00001, 750.99,"Tenny shoey");
Upper_wear T_shirt_01 = new Upper_wear("Cotton", 0, "no", 0, 14, "yellow", 14.5, 15, "v-neck", "no", 00002, 990.50, "Yel-ow");)
Shoes[]In_Stock = {Tennis_shoes_01};
Upper_wear[]In_Stock_upper = {};
Lower_wear[]In_Stock_lower = {};
System.out.println("Price");
System.out.println("-------");
for(Shoes x : In_Stock){
System.out.println(x.get_name() + ": " +x.get_price());
}
for(Upper_wear x : In_Stock_upper){
System.out.println(x.get_name() + ": " + x.get_price());
}
}
What I am wanting is something more like this:
public class Want_run
{
public static void main(String[]args){
Clothing Tennis_shoes_01 = new Shoes("Canvas", 0, "yes", 10, "red and white", 0,0.5,2.5, 00001, 750.99,"Tenny shoey");
//Not sure if this is possible to have a class that's different than the constructor but I am looking for it to come from clothing class with properties of Shoes.
Clothing T_shirt_01 = new Upper_wear("Cotton", 0, "no", 0, 14, "yellow", 14.5, 15, "v-neck", "no", 00002, 990.50, "Yel-ow");
//So I want all properties to be in clothing but the ones that the childeren don't have I want to be just blank.ex. Upper_wear is blank on the shoe_laces.
Clothing[]In_Stock = {Tennis_shoes_01, T_shirt_01};
//I really want everything to be just in one list to iterate through but I can't currently do that with multiple parents of my knowledge.
for(Clothing x : In_Stock){
System.out.println(x.get_name() + ": " + x.get_price());
}
//this way I have only one for loop for every item,and for parents that don't have 'price' I am hoping would just not print.
}
}
So I want clothing to have every attribute of 'Upper_wear', 'Lower_wear', and 'Shoes', but not the parents to have every attribute of Clothing. Such that the attributes that are specific to Shoes, I wish to be blank for the other two parents when it iterates through methods specific to Shoes. I'm not sure if what I am looking for is even possible to do. If you cannot understand what I am looking for, I am sorry for being confusing. Thank you for taking your time to read this and helping me.
What you are trying to do is a classic application of polymorphism. You just need to clarify a few concepts.
Your grand parent will contain all the attributes that are common to all children, such as item ID, name, colour(s), price, etc. It should also contain common functions, such as a print() function which is what you require in your main.
All children (including parents) will introduce their specific attributes in their classes, such as hood/collar for uppers, and inner lining for jacket. They will also override (provide their own implementation of) functions they need to customize according to their needs. So, in your case, while the Clothing will have a print() function, each sub class will have its own implementation of it, in which it will print all its own properties such as number of zippers, shoelaces.
Finally, in your main, you will have a list of type Clothing, which will contain references to objects of all types you want. A parent can point to an object of a child type. For example,
Clothing c = new Jacket(...);
c.print(); // This will call the print() of class Jacket, not Clothing
I suggest reading up on dynamic polymorphism. This link contains a quick introduction and a nifty example.
I have been experimenting with Classes in Java over the last few days, learning about them from "TheNewBoston" on youtube and from the java docs.
I have created the following scenario and seek your guys' (girls too) professional criticism and in depth knowledge regarding a few questions I have.
There are two classes, person and person_financial, a base class and sub class respectively.
person class:
public class person {
private String name;
private String sex;
private int age;
private double height;
private double weight;
private double intelligence;
// person constructor arguments order: name, height, weight, age, sex, intelligence
public person(){
this("noname",0,0,0,"undefined",5);
}
public person(String n){
this(n,0,0,0,"undefined",5);
}
public person(String n, double h){
this(n,h,0,0,"undefined",5);
}
public person(String n, double h, double w){
this(n,h,w,0,"undefined",5);
}
public person(String n, double h, double w, int a){
this(n,h,w,a,"undefined",5);
}
public person(String n, double h, double w, int a, String s){
this(n, h, w, a, filterSex(s), 5);
}
public person(String n, double h, double w, int a, String s, double i){
name = n;
height = h;
weight = w;
age = a;
sex = filterSex(s);
intelligence = i;
}
public void setName(String n){
name = n;
}
public void setHeight(double h){
height = h;
}
public void setWeight(double w){
weight = w;
}
public void setAge(int a){
age = a;
}
public void setSex(String s){
sex = filterSex(s);
}
public void setIntel(double i){
intelligence = i;
}
public String getName(){
return name;
}
public double getHeight(){
return height;
}
public double getWeight(){
return weight;
}
public int getAge(){
return age;
}
public String getSex(){
return sex;
}
public double getIntel(){
return intelligence;
}
public String getInfo(){
return String.format("Name: %s,\nSex: %s,\nAge: %d,\nIntelligence: %.2f,"
+ "\nHeight: %.2f,\nWeight: %.2f\n", name, sex, age,
intelligence, height, weight);
}
private static String filterSex(String s){
return ((s.equalsIgnoreCase("male") ||
s.equalsIgnoreCase("female")) ? s : "undefined");
}
}
person_financial class:
public class person_financial extends person {
private double monies = 0;
public void definePerson(String n, int a, String s, double i, double h, double w){
setName(n);
setAge(a);
setSex(s);
setIntel(i);
setHeight(h);
setWeight(w);
}
public person_financial() {
this(0);
}
public person_financial(double m) {
monies = m;
}
public void depositMonies(double m) {
monies += m;
}
public void withdrawlMonies(double m) {
if (m <= monies) {
monies -= m;
}
}
public double getBalance() {
return monies;
}
}
and then in the main class I have this:
public class Main {
public static void main(String[] args) {
person p1 = new person("I have no Name", 180, 72, 38, "Alien", 7.2);
System.out.println(p1.getName());
person_financial pf1 = new person_financial(100.00);
pf1.depositMonies(50.02);
System.out.printf("%s has %.2f monies.\n", pf1.getName(), pf1.getBalance());
pf1.definePerson("some_name", 42, "male", 10, 180, 72);
System.out.println(pf1.getInfo());
}
}
in the person_financial class, I have made a method called "definePerson()" which I use to define all the characteristics that would otherwise have been defined from the 'person()' constructor from the 'person' class. I'm sure there is a more professional way for assigning values to variables in a base class from a sub class, I just dont know of any...
Also, is there any way to call the constructor from the "person" class to define characteristics for 'pf1'? rather than having to, for example, manually set each attribute, i.e. pf1.setName("something"); , or pf1.setAge(1000000); etc... or have a method do it for me, as in 'definePerson()'.
Any help is much appreciated,
Thanks =).
You use the super() call to call the constructor of the parent class. It has to be the first call in the constructor of the derived class, but you call it (and pass in arguments) like any other function and it will call the constructor that way.
It's common to declare a class 'abstract' to prevent creation of generic objects - based on your usage-code at the bottom you seem not to want that and that's fine. Just remember that you can declare declare a class abstract.
The best way to use class hierarchy is to ensure that (buzzword alert) any class in a useful hierarchy should be declarable as anythin in the hierarchy (i.e. you should be able to access any methods in your concrete object from the base-class (person in this case).
Your financial_person object extends person, but the ideal is to have a class that you can declare at a high level and call methods polymorphically. Consider for a minute that all people are able to draw and deposit money (different from your classes, but bear with me for a minute).
drawMoney method would exist in person, but be marked abstract - forcing the subclasses financial_person and regular_person to implement draw_money, deposit_money etc.
each class would have an implementation that suits their reality (financial person would have access to all kinds of special accounts, discounts etc., and regular_person would have a simpler set of - but still the same external behavior).
Then you could declare like this:
Person finPerson = new FinancialPerson(... etc.);
Person regPerson = new RegularPerson(....etc);
note now that you are able to do this code below:
finPerson.drawCash(12300.0);
regperson.drawCase(100.0);
The identical behavior.
You could have a List of thousands of people, and would not have to do if-then-else or switch statements to execute the finer-tuned behaviors of each.
The acid-test for class-hierarchy is this: "my (sub-class) really 'a kind of' (superclass)?"
In other words, "does my subclass have behaviors of the superclass?"
If not, you should think carefully about class hierarchy. There's a buzzword for this : Liskov Substitution Principle, and I cannot do a better job of this than Robert. C. Martin - one of the software-design gurus:
http://www.objectmentor.com/resources/articles/lsp.pdf
In this article he shows what happens when you have inadvisable hierarchy, using the "a square is a kind-of rectangle" example.
Google "template method pattern" for a summary of another aspect of effectively using inheritance. You will see that it is much more powerful than the simple inheritance that most people dismiss it as being.
Also remember that no single pattern is a silver-bullet for everything. Some people will call class-hierarchy evil and tell you to use interfaces only; others will say the reverse. There are choices to make, and sometimes they will not be obvious.
There are many pitfalls, and missing LSP is just one of them. Others are (examples only) overriding concrete methods, having concrete classes not marked final, enabling mutability of "identifying" fields (eg fields used in equals/hashcode, etc.) Imagine if "customer" objects at bank allowed resetting of first-name, or account-number at runtime, once these fields were already set).
My answer is more generally related to OO design, inheritance etc. than specific coding questions - hope it's of some use to you.