Java android multidimensional array (hash maybe) with string and nested class - java

I'm trying to track class stats for an android game I'm working on.
public static class characterClasses {
public String class_name;
public int base_hp;
public int base_attack;
public float base_defense;
}
I want to access these directly by name so I won't have to iterate over them repeatedly. From my research it looks like a hashmap or map would be what I need but everything I've seen is only for a single key/value pair. I need to access each stat value directly by class and value, something like
classList.get("warrior").get("base_hp");
Can someone point me in the right direction?

You are correct to think of using HashMap. You can use the characterClass String names as keys and the characterClasses as values. You can then use your getter methods to access your specific fields i.e.
classList.get("warrior").getBase_HP();
You could also forget maps entirely since these stats seem constant by using inheritance
public class Character {
int hp;
int attack;
int defense;
public Character (int hp, int attack, int defense) {
this.hp = hp;
this.attack = attack;
this.defense = defense;
}
public int getHP() {
return hp;
}
...
}
For your Character subclasses, you can preset those values in the constructor
public class Warrior extends Character {
public Warrior() {
super(2, 10, 8);
}
public int getHP() {
return super.getHP();
}
}
public class Wizard extends Character {
public Wizard() {
super(10, 3, 1);
}
public int getHP() {
return super.getHP();
}
}
This way all your Warrior and Wizard Objects will have the same stats that can be accessed any time simply by invoking their getters.

Related

Why does setting class a to class b work?/How can I make my method universal?

So before I start this off I would like to give a little disclaimer. I do not really understand what is happening here so I apologize if my paragraph does not make much sense. I will try my best to convey my question, and, hopefully, y'all will be able to help me. So here goes.
I have been working on a basic test based adventure game/dungeon crawler. While creating an encounter method for when you find a monster, I realized that I needed a way to parse through my Hashtables full of my monster classes. Problem was, I had set the keys to Strings for easier access when wanting to add a specific item to the player's storage or to add a specific monster to a fight. So I decided to create a method which would receive a Hashtable I fed it and spit back out a random key, which I would then use to get the monster from my database. I attempted to create a method that would work for all Hashtables with a String, class format, and a sample of my attempted parsing code resides below.
for(String key: table.getkeys())
{
if(num_of_loops_to_do==times_looped)
{
return key;
}
}
This didn't work, as the program complained about the table (which I fed like so(Hashtable table)) was an object and therefore the program would have a seizure if it was forced to try to pull keys out of it. Now if someone can explain this, I would appreciate it, but it is not the core of my question. Eventually, I changed my path of attack to a try-catch system where I would have two Hasthables that shared the same types as the two database Hashtables in my program. Then the program would try to set the provided hashtable to one and if that failed stick it in another. The funny thing is, I fed my method my monster class, and it set it to a Hashtable that stores data as String, item. Now, since I only am getting the key from these I guess it doesn't really matter what happens to the class, but how is monster changed to item without any errors being thrown? I mean I guess they both take data in the following order (int, int, String, int) so I guess the creation could work, and I assume this is what happened. Am I correct in this? Is this a problem? Since I'm using just the key can I somehow make the method universal where it only takes the keys from table instead of the keys and values?
Here is my item class.
static class item
{
private int durability;
private int damage;
private String name;
private int rarity_level;
item(int durability, int damage, String name, int rarity_level)
{
this.durability=durability;
this.damage=damage;
this.name=name;
this.rarity_level=rarity_level;
}
String get_name()
{
return name;
}
int get_durability()
{
return durability;
}
int get_damage()
{
return damage;
}
void change_durability(int change_in_durabilty)
{
durability=durability+change_in_durabilty;
}
int get_rarity_level()
{
return rarity_level;
}
}
Here is my monster class.
static class monster
{
private int health;
private int damage;
private String name;
private int level;
monster(int health, int damage, String name, int level)
{
this.health=health;
this.damage=damage;
this.name=name;
this.level=level;
}
String get_name()
{
return name;
}
int get_health()
{
return health;
}
int get_damage()
{
return damage;
}
void change_health(int change_in_durabilty)
{
health=health+change_in_durabilty;
}
int get_level()
{
return level;
}
}
And finally, here is my Method.
public static String get_Ran_Object_From_Dict(Hashtable table)
{
Random rand=new Random();
int object_num_to_retrieve=rand.nextInt(table.size());
Hashtable<String, Data.item> item_data_base=new Hashtable<String, Data.item>();
Hashtable<String, Data.monster> monster_data_base=new Hashtable<String, Data.monster>();
try {
item_data_base=table;
}
catch(Exception e)
{
monster_data_base=table;
}
int num_looped=0;
System.out.println(item_data_base.size());
System.out.println(monster_data_base.size());
if(monster_data_base.size()>0) {
System.out.println("monster");
for(String key : monster_data_base.keySet())
{
if(num_looped==object_num_to_retrieve)
{
return key;
}
num_looped+=1;
}
}
else
{
System.out.println("item");
for(String key : item_data_base.keySet())
{
if(num_looped==object_num_to_retrieve)
{
return key;
}
num_looped+=1;
}
}
return "System_fail";
}
I believe the reason it works is that when item_data_base is set equal to table the original parameters of item_data_base are overwritten. So one last question, why does that work when just using the raw table value doesn't?
(Working code)
public static String get_Ran_Object_From_Dict(Hashtable table)
{
//By creating dictionary with defined parameters I can then set it to table and it wont explode.
Random rand=new Random();
int object_num_to_retrieve=rand.nextInt(table.size());
Hashtable<String, String> hashtable=new Hashtable<String, String>();
hashtable=table;
int num_looped=0;
for(String key :hashtable.keySet())
{
if(num_looped==object_num_to_retrieve)
{
return key;
}
num_looped+=1;
}
return "System_fail";
}
(Broken Code)
public static String get_Ran_Object_From_Dict(Hashtable table)
{
Random rand=new Random();
int object_num_to_retrieve=rand.nextInt(table.size());
int num_looped=0;
for(String key :table.keySet())
{
if(num_looped==object_num_to_retrieve)
{
return key;
}
num_looped+=1;
}
return "System_fail";
}

Shallow Copy of Instance of Class within an ArrayList

I have an ArrayList which contains n instances of the class Boat. The class Boat has a number of methods which alter the instance variables of that boat.
For example:
public void Command(String command)
{
int inefficientwayofdoingthis=0;
if(command.equals("power on"))
{
inefficientwayofdoingthis++;
int x=1;
setpower(x);
System.out.println(name+" is on and is travelling in the direction of "+angle+" deg. with speed: "+ speed+"mph");
}
//...
The issue I am having is that this Command method should set the value of [instancename].power to 1.
The instances are contained in an ArrayList, data:
I am using the following code to alter the instances within the arraylist:
int numberinArray = whatever;
String theorder = "power on";
data.get(numberinArray).Command(theorder);
Each time I do so however, the command works and an output is produced, but subsequent commands do not seem to recognize that data.get(numberinArray).power should equal 1. I think I'm having a problem in that this is a deep copy of each instance of the class rather than a shallow copy. Would anyone have any suggestions on how to alleviate this issue?
if you want the power stay "attached" to the boat instance, this should be an instance variable. This could work in a way like this:
package com;
public class Boat {
private int power;
private String color;
Boat() {
// may want to initialize some values
this.setPower(0);
this.setColor("red");
}
public int getPower() {
return power;
}
public void setPower(int power) {
this.power = power;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
then you could add some other methods like applyCommand(String command) in your example

Are enums changeable at all?

I've been working on a game, and in the game I'm a summoner that has tamed monsters (much like pokemon).
What I want to do , is have a backpack of 5 tamed monsters, of which I can spawn 1 at a time.
Someone recommended me to use enums (I can't contact that person anymore :(), so I've been looking at a few enum tutorials and examples, and I can't figure out how this would help me.
Let us say that the enum would look like this :
public enum TamedMonsterStats {
ELF(0,"res/siren_monster_girl_sprite_by_tsarcube-d52y2zu.png",0,100);
DRAGON(0,"res/dragon.png",0,100);
private int haveit;
private String photoname;
private int typeOfDamage;/*
* 0: dark
* 1: light
* 2:
*/
private int HP;
TamedMonsterStats(int haveit,String photoname,int typeOfDamage,int HP){
this.haveit = haveit;
this.photoname = photoname;
this.typeOfDamage = typeOfDamage;
this.HP = HP;
}
public int getHaveIt(){
return haveit;
}
public String getPhotoName(){
return photoname;
}
public int getTypeOfDamage(){
return typeOfDamage;
}
public int getHP(){
return HP;
}
public void setHp(int hp) {
HP = hp;
}
}
This would kind of work, but as daveychu pointed out, this makes it impossible for me to have 2 instances of the same creature, so my idea was to have an enum backpack with monster1,monster2,monster3,monster4,monster5 , and then filling them with the values dynamically, but I feel like doing this means I shouldn't be requiring enums at all, is this true?
You can add a setter method on your enum:
public void setHp(int hp) {
HP = hp;
}
However, I'm a bit wary of your use of enum. In this situation, only one "DRAGON" instance could exist at any time so I wonder what you would do if the user wants to have more of them or if the enemy has one at the same time.
Your typeOfDamage on the other hand is an excellent candidate for an enum:
public enum DamageType {
DARK,
LIGHT,
NORMAL
}
You can then use this enum:
ELF(0, "res/siren_monster_girl_sprite_by_tsarcube-d52y2zu.png", DamageType.DARK, 100),
DRAGON(0, "res/dragon.png", DamageType.LIGHT, 100);
private DamageType typeOfDamage;
TamedMonsterStats(int haveit, String photoname, DamageType typeOfDamage, int HP) {
this.typeOfDamage = typeOfDamage;
}
public DamageType getTypeOfDamage() {
return typeOfDamage;
}
It makes it a lot more readable than having to pass some random integers.

Better way to map from String constants to int constants in Java

I have a load of images of musical symbols which I need to do some processing on and for each one I need to get the integer code corresponding to its file name. There are 23 possible file name strings and 23 integer code and there are many images with the same name under different directories.
The solution I have so far is given (abbreviated) below. I have just defined a load of int and String constants and then written a method which is just a huge chain of if statements to do the translation.
What would be a better way to achieve the same effect? The way I've done it seems really awful! I thought about using some kind of Map, but I wasn't sure of the best way to do so.
public class Symbol {
public static final int TREBLE_CLEF = 0;
public static final int BASS_CLEF = 1;
public static final int SEMIBREVE = 2;
// ...
public static final String S_TREBLE_CLEF = "treble-clef";
public static final String S_BASS_CLEF = "bass-clef";
public static final String S_SEMIBREVE = "semibreve";
// ...
public static int stringCodeToIntCode(String strCode) {
if (strCode == S_TREBLE_CLEF) {
return TREBLE_CLEF;
} else if (strCode == S_BASS_CLEF) {
return BASS_CLEF;
} else if (strCode == S_SEMIBREVE) {
return SEMIBREVE;
} //...
else {
return -1;
}
}
}
I think you are looking for Enum where you can have String constant and its value.
Example:
public enum YourEnumClass{
STRING_CONST (5),
STRING_CONST2 (7),
.....
//constructor
//getValue() method
}
read linked tutorial for more details.
enum StringToInt{
TREBLE_CLEF(0),
......
}
Enum is the way to go.
Another example:
public enum Color {
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
private int code;
private Color(int c) {
code = c;
}
public int getCode() {
return code;
}
how about a hashmap
HashMap<String,Integer> hm=new HashMap<String,Integer();
hm.put("treble-clef",0);
//rest
and get it by using this
int value=hm.get("treble-clef");

Using a String for an instance object name

I have this code which gets info from an other class but I have to add another line other code for every instance object.
public static int giveShipData(String shipName,int Data){
if(shipName.equals("Player")){i = Player.getData(Data);}
return i;
}
Is it possible to have something like:
public static int giveShipData(String shipName,int Data){
i = shipName.getData(Data);
return i;
}
Sorry if I am using the wrong terminology I am self taught and new.
I think you'd better to reconsider your design. If you have a ship name and ship data I assume you must have a Ship class which looks something like this:
public class Ship {
private String name;
private int data;
public Ship(String name, int data) {
this.name = name;
this.data = data;
}
public String getName() {
return name;
}
public int getData() {
return data;
}
}
Besides this class there should be a class like Shipyard:
public class Shipyard {
private Map<String, Ship> shipsByNameMap = new HashMap<String, Ship>();
public void registerShipByName(String name, Ship ship){
shipsByNameMap.put(name, ship);
}
public Ship getShipByName(String name){
return shipsByNameMap.get(name);
}
}
So, at first you invoke shipyard.getShip("Player") method to get ship object, than you can invoke ship.getData() method to retrieve ship data.
You might be able to do something like this...
int[] ships = new int[3]; // 3 ships
public void populateShips(){
for (int i=0;i<ships.length;i++){
ships[i] = giveShipData(shipname,data);
}
}
public int giveShipData(String shipName,int data){
return shipName.getData(data);
}
This would allow you to create any number of ships, just increase the size of the ships[] array to be however many ships you want.
Is this kinda what you're after?
As per your code "shipName" is a string...and it does not have getData() method. And why are you passing Data to the getData()... You could instead write something like this-
i = ClassObj.getData(shipname);
and in the method getData return the info regarding the "shipname".

Categories