How to design an RPG class system with OOP in java? - java

I am making a roguelike based on Trystan's Tutorial and running into issues with implementing a class system. I'm pretty sure the solution is simple, but bear with me.
class Creature {
int HP;
CharacterClass playerClass = new Wizard();
HP = playerClass.hitDie;
ArrayList<Ability> creatureAbilityList = new ArrayList<>();
creatureAbilityList.add(classAbilityList.get(1));
}
class CharacterClass {
int hitDie;
ArrayList<Ability> classAbilityList = new ArrayList<>();
}
class Wizard extends CharacterClass {
Wizard() {
hitDie = 6;
classAbilityList.add(new Ability(magicMissile));
}
}
I'm getting a "Syntax error on token ";", , expected", on the semicolon following "new Wizard()". I'm fairly sure that this isn't the issue however, but instead the way that my classes and inheritance is set up. How should I set up the code instead? Any help would be appreciated.

The problem is the row below. It should be
int HP=playerClass.hitDie;
(and remove the line int HP;)

you should make hitDie private, and make it accessible with getter and setter to enable the polimorphism (and so the getHitDie() invoked will be the one of the class Wizard instead of the one of the class CharacterClass)

Related

how to draw sequence diagram from java code

currently I am drawing sequence diagram from java code, I know there are several shortcut extension software exist, still, I want to draw it by my hand and to figure out what is going on.
I am working with these piece of code from java:
import java.util.List;
public static void main(String[] args) {
Student student = new Student(2);
student.addClass(new Class("SE 450"));
student.addClass(new Class("SE 550"));
System.out.println(student.getFormattedSchedule());
}
class Student {
//instance field;
private final List<Class> classes;
private final int maxNumberOfClasses;
//constructor
Student(int maxNumberOfClasses){
classes = new ArrayList();
this.maxNumberOfClasses = maxNumberOfClasses;
}
//Mutator Method
void addClass(Class newClass){
if(classes.size() < maxNumberOfClasses)
classes.add(newClass);
}
List<Class> getClasses(){
return classes;
}
String getFormattedSchedule(){
if(classes.size() == 0)
return "No classes added.";
String schedule = "";
for (Class studentClass : classes) {
schedule += studentClass.getName() + "\r\n";
}
return schedule;
and what I draw from this code something like that:
In this case, I do not know how to continue to draw the diagram because i do not know how draw the diagram for this piece of code:
classes.add(newClass);
Does anyone have idea about that? Any suggestions are appreciated!
Well, you could treat classes as an own lifeline and send the add message to it. But that just looks like overkill. Either
you model it sort of a self-message (accompanied by a note) or
you just use a note at the location
or (what I suggest) you don't go into that detail.
An SD is no visual programming aid. It shall give an overview of complex procedures so one get's an idea of what's going on. Reduce to the max.

Restricting a class to a certain amount of objects in Java

I would like to ask if there is a way to restrict a certain class to make more than a certain amount of instances. And if it is possible to make the compiler ("Eclipse") underline that line, when you try to make another instance (like it is an error in the code), or something along those lines?
Just to clarify for those who would say this is a bad idea, I am making a chess game, so I need it to not be able to make more than certain amount of playing pieces.
Eclipse can't do that at compile time, because it can't tell how many times a piece of code will be executed, and thus how many instances are created.
But you can design your class to only create a given number of instances, and make it impossibale to create more. For example:
public class Limited {
public static final List<Limited> ALL_INSTANCES =
Collections.unmodifiableList(createInstances());
private int id;
private static List<Limited> createInstances() {
List<Limited> result = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.add(new Limited(i));
}
}
private Limited(int id) {
this.id = id;
}
}
Since the constructor is private, the only 10 instances available are the ones in ALL_INSTANCES.
That said, that is not necessarily a good idea. Let's say you're creating a chess game. So by your logic, you shouldn't be able to create more than 2 King instances. What if your app handles 10 games at a time? Do you really want at most 2 Kings, or do you just want each ChessGame instance to have a black and a white King? Maybe all you need is something like
public class ChessGame {
private King blackKing = new King(BLACK);
private King whiteKing = new King(WHITE);
...
}
You can simply create the required number of objects - say by instantiating your class within a loop and then set a flag which is checked by the constructor so as to throw exception when an attempt is made to create one more. You can make the constructor private and have a static method to generate your instances.

Java OOP: Building Object Trees / Object Families

Been a while since I used Java and was wondering if this was a decent or even correct way of setting this up.
FYI, userResults refers to a JDBI variable that isn't present in the code below.
Feel free to suggest a better method, thanks.
public class Stat
{
private int current;
private int max;
public int getCurrent() {return current;}
public void setCurrent(int current) {this.current = current;}
public int getMax() {return max;}
public void setMax(int max) {this.max = max;}
}
public class Character
{
Stat hp = new Stat();
Stat mp = new Stat();
}
Character thisCharacter = new Character();
// Set the value of current & max HP according to db data.
thisCharacter.hp.setCurrent((Integer) userResults.get("hpColumn1"));
thisCharacter.hp.setMax((Integer) userResults.get("hpColumn2"));
// Print test values
System.out.println (thisCharacter.hp.Current);
System.out.println (thisCharacter.hp.Max);
Correct? Well, does it work? Then it probably is correct.
Wether or not it is a decent way to do it then the answer is "maybe". It is hard to tell from what context this code is in. But there are some things you could keep in mind though:
In which class (or object rather) are the Stat set in? Do you feel is it the responsibility of the class to do this and know what database values to get them from? If not, consider making some kind of a class that does this.
Making chained calls such as thisCharacter.hp.setCurrent(...) is a violation of principle of least knowledge. Sometimes you can't help it, but usually it leads to kludgy code. Consider having something that handles all the logic surrounding the stats. In your code you may need a HealthStatsHandler that have methods such as loadStats(), saveStats(), and mutator actions such as takeDamage(int dmg) and revive(int health).
If you have trouble figuring things out if it has the correct object design, then study up on the SOLID principles. They provide nice guidelines that any developer should follow if they want to have code that is extensible and "clean".
This is not really a tree. It is not possible two have more than one layer of children.
Usually you define an interface let's call it Node where both Stat and Character implements it and the two children of Character would have the type Node.
I would consider creating the Stat objects seperately and passing them into Character, and making the character attributes private as follows:
public class Character
{
private Stat hp;
private Stat mp;
public Stat getHp() {return hp;}
public void setHp(Stat h) {this.hp = h;}
public Stat getMp() {return mp;}
public void setMp(Stat m) {this.mp = m;}
}
// Set the value of current & max HP according to db data.
Stat hp = new Stat();
hp.setCurrent((Integer) userResults.get("hpColumn1"));
hp.setMax((Integer) userResults.get("hpColumn2"));
Character thisCharacter = new Character();
thisCharacter.setHp(hp);
// do the same for mp
One additional simple step would be to create a Character constructor that would take an hp and an mp

What's wrong with this error? ----Syntax error on token ";", { expected after this token

Syntax error on token ";", { expected after this token.
I got this error on the 11th line and 19th line. Is there anyone can tell me what's the problem with it?
import java.util.*;
class veding_machine{
State st;
veding_machine vm;
private int price;
private int k;
private int k1;
private int t;
private int s;
State Ls[]=new State[7]; // 11th line
Ls[0]=idle;
Ls[1]=coins_inserted;
Ls[2]=sugar;
LS[3]=nsc;
Ls[4]=nlc;
Ls[5]=et;
Ls[6]=st; // 19th line
public veding_machine(){ k=0; k1=0; t=0; price=0;
}
public void setK(int k){
this.k=k;
}
Initialize that array inside a Constructor, you can't initialize them like that, initialize them when you declare the array, or in a Constructor or in a initialization block. And correct the spelling mistake. Have look on this tutorial.
Ls[0]=idle;
Ls[1]=coins_inserted;
Ls[2]=sugar;
Ls[3]=nsc;
Ls[4]=nlc;
Ls[5]=et;
Ls[6]=st
;
The initialization of Ls should be inside the vending_machine constructor and should be creating instances of the classes "idle" and "coins_inserted", etc...
Ls[0] = new idle();
Ls[1] = new coins_inserted();
Ls[2] = new sugar();
Ls[3] = new nsc();
Ls[4] = new nlc();
Ls[5] = new et();
Ls[6] = new st();
and these classes need to extend the State class
class idle extends State {
// ...
}
They don't need a state instance inside them.
// removed, State st;
public coins_inserted(){
// removed, st=new State();
}
State Ls[]=new State[7]; // 11th line
This is an instantiated array. You should place it in the constructor or initialization block. Also it is better to init the reference in the Java way:
State[] Ls = new State[7];
This
LS[3]=nsc;
should be
Ls[3]=nsc;
And again init those elements in the constructor or init block.
Also, I know this doesn't answer the question but I just have to say something about naming and style. Please name vending_machine class like VendingMachine and give the other objects more descriptive names instead of vague letters. Following convention helps when you come back to your code a week/month/year later and saves you from trying to figure out what the hell you were doing. Even if it is just a little project in school that is where it matters most that you learn and practice these conventions.
Also, it's nice when code is aesthetically pleasing.

How to refactor a method to make it easier to test

Below is a method that I'm having a hard time figuring out how to test using JUnit.
This method is difficult to test because it depends on the results of other methods (e.g. getClosestDcoumentCode).
Based on my reading of JUnit, this suggests I should refactor the method. But how? And if refactoring is not necessary, how do you test a method that depends on other methods?
Thank you,
Elliott
private static String findPrincipal(List<DocumentKey> documentkeys_) {
Hashtable<String, Integer> codecounts = new Hashtable<String, Integer>();
for (DocumentKey document : documentkeys_) {
int x = 0;
String closestCode = getClosestDocumentCode(document.candidates);
if (closestCode == null) continue;
int thecount = 0;
if (codecounts.containsKey(closestCode))
thecount = codecounts.get(closestCode);
if (document.hasKey)
thecount += 2;
else
thecount++;
codecounts.put(closestCode, new Integer(thecount));
x++;
}
String closestCode = getClosestCode(codecounts);
return closestCode;
}
Well, first of all, I wonder if the method really needs to be static, and what that class is doing. It looks like it might be a GOD class, or at the very least it's violating the single responsibility principle. What does getClosestCode do? If it was a class, you could inject it with a stub in your tests into the test class.
EasyMock will let you mock the method response, but I'm not sure how you mock static methods.
In general, you probably need to
Extract long functions into classes
Make functionality non-static
Maintain the single responsibility principal
It sounds to me like getClosestCode and getClosestDocumentCode belong to a different set of responsibilities than the findPrincipal method. So you'll want to begin by separating these into two different classes. Create an interface for each class to implement. The class that implements the findPrincipal method can then rely on the other interface as a constructor argument, like this:
public class PrincipalFinderImpl implements PrincipalFinder
{
private CodeFinder codeFinder;
public PrincipalFinderImpl(CodeFinder codeFinder) {
this.codeFinder = codeFinder;
}
public String findPrincipal(List<DocumentKey> documentkeys_) {
Hashtable<String, Integer> codecounts = new Hashtable<String, Integer>();
for (DocumentKey document : documentkeys_) {
int x = 0;
String closestCode = codeFinder.getClosestDocumentCode(document.candidates);
if (closestCode == null) continue;
int thecount = 0;
if (codecounts.containsKey(closestCode))
thecount = codecounts.get(closestCode);
if (document.hasKey)
thecount += 2;
else
thecount++;
codecounts.put(closestCode, new Integer(thecount));
x++;
}
String closestCode = codeFinder.getClosestCode(codecounts);
return closestCode;
}
}
Now it should be easy to create another class the implements the CodeFinder interface, either manually or using a Mocking framework. You can then control the results of each call to getClosestCode and getClosestDocumentCode, and ensure that each of these methods gets called with exactly the arguments you expect it to be called with.
I don't read the method deeply. But if a private method needs to test, it indicates something wrong with your design. At least Kent Beck thinks so.
There is a chapter on stub calls on JUnit Second Edition, i recommend you have a look at that if you think your existing codes are not written to test-driven development standards.

Categories