can variable have multiple enum constants in java? - java

I am building simple java game which the user has to find gold. There are some obstacles like Orc, Goblin, and Poop.
What I am trying to do is that I am creating Cell and Board class.
Inside of my Cell class,
public Cell{
public enum TheCell { Orc, Goblin, Poop, Gold, Empty};
TheCell type;
public Cell(TheCell type){
this.type = type;
}
}
and I make two dimensions in Board class,
public Board{
Cell[][] grid = new Cell[7][7];
Random r = new Random();
for(int i = 0; i<3; i++){
int randNum1 = r.nextInt(7);
int randNum2 = r.nextInt(7);
grid[randNum1][randNum2] = new Cell(Cell.TheCell.Orc);
}
for(int i = 0; i<3; i++){
int randNum1 = r.nextInt(7);
int randNum2 = r.nextInt(7);
grid[randNum1][randNum2] = new Cell(Cell.TheCell.Goblin);
}
}
My question is that, in case of Orc and Goblin are same cell, I wanna keep them both monster in same cell. Is there some how I can keep both or multiple obstacles in same cell? Thank you!

One way to achieve this is to have the Cell class hold a list of all monsters/things that are currently on the cell (using the enum, that is already available)
A more "low level" approach is to use an Integer for the cell and then use bitflags to model multiple obstacles on the same cell.
Update:
I agree with #ajb, in this case an Enum Set should be used
As pointed out by #JimGarrison, the EnumSet approach only works until you need to have more than one instance of an enum value for one cell.

public Cell{
public enum TheCell { Orc, Goblin, Poop, Gold, Empty};
List<TheCell> type = new ArrayList<TheCell>();
public Cell(TheCell type){
addType(type);
}
public addType(TheCell type) {
this.type.add(type);
}
}

Related

Save all generation in Game of Life for later access

My Game of Life works perfectly. I also have a counter that shows the current generation (for each iteration generation++).
Now I want to be able to access and display any generation during the game. The whole game consists of a two-dimensional array (Cell[][]). So after each iteration, the respective array must be saved with a unique name.
But how can I save an array multiple times in a loop? I can't add the iteration-number to the array name like Cell[][] cells+generation = ... to become cells0, cells1, cells2... arrays.
Another idea was, to create a class generation and create a new object of this class for each iteration, but even then the problem of the name of the object generation remains (to be able to access the respective object, a unique name is required, e.g. generation13, generation154 ...).
public class Generation {
private Cell[][] cells;
public Generation(Cell[][] cells) {
this.cells = cells;
}
public Cell[][] getCells() {
return cells;
}
public void setCells(Cell[][] cells) {
this.cells = cells;
}
}
Does anyone have an approach on how to achieve this? I think that with the class generation makes the most sense, because this way you can also access (get) the constructor (two-dimensional array) for displaying.
What about making an ArrayList<Cell[][]>? So, If you want to add a new generation, just use
arrayListOfCells.add(generation);
And then access it with
arrayListOfCells.get(index);
You're almost there. Just add generation number to the Generation class.
public class Generation {
private final int generation;
private Cell[][] cells;
public Generation(int generation, Cell[][] cells) {
this.generation = generation;
this.cells = cells;
}
public Cell[][] getCells() {
return cells;
}
public void setCells(Cell[][] cells) {
this.cells = cells;
}
public int getGeneration() {
return generation;
}
}

How do I pull value from method designated with "this."

I have information like this:
xxx 0 1 2 ...
Name Fred0 Fred1 Fred2
Stamina 2 6 7
Intel 5 4 1
Heart 4 8 2
Speed 5 3 6
So, I was informed previously that creating a 2D ArrayList to store something like this is "archaic" and was provided with a different way to set my code up. The reason I was using ArrayList<> is because I want to be able to generate new racers as needed, rather than designating an array to a size. If I could just use a simple array this would have been done a week ago. Now I've been screwing with it for a week and I still don't get how it works.
public class test {
public String name;
private int stamina;
private int heart;
private int intel;
private int speed;
public ArrayList<String> racers = new ArrayList<String>();
private void racerInfo(String name) {
this.name = name;
this.stamina = (int) Math.floor(Math.random()*10);
this.heart = (int) Math.floor(Math.random()*10);
this.intel = (int) Math.floor(Math.random()*10);
this.speed = (int) Math.floor(Math.random()*10);
}
public void generate() {
for ( int i=0; i<=10; i++) {
String name = "Fred" + i;
System.out.println(name);
racerInfo(name);
racers.add(name);
}
}
public int getStamina() {
return this.stamina;
}
public int getHeart() {
return this.heart;
}
public int getIntel() {
return this.intel;
}
public int getSpeed() {
return this.speed;
}
}
public class main {
public static test test = new test();
public static void main(String[] args) {
test.generate();
//Put stuff here to pull stamina of Fred2 for example.
}
}
Now, in the main class. How would I do something that should be relatively simple like pulling the Stamina value for Fred2.
I've been following the exact directions I've been given by others here to write most of this code. But at this time, I'm getting to the point of just re-writing it all so that each stat (name, stamina, intel, speed, etc.) is just logged as a separate ArrayList<>. But I can't figure out how to make a 2D ArrayList containing the original ArrayLists ie.
ArrayList<String> name = new ArrayList<String>();
ArrayList<Integer> stamina = new ArrayList<Integer>();
ArrayList<ArrayList<Object>> arrayOfArray = new ArrayList<ArrayList<Object>>();
Yes, I know the arrayOfArray is probably done wrong, but, again, I just get told it's Archaic and nobody'll tell me how I can do it right so I can just go. arrayOfArray.get(2,1) and pull information that I want/need.
Sorry for the information overload here. but I'm trying to just find the best possible solution for what I want to do. If you can tell me how to correctly pull off either way I will be eternally grateful you you and all of your descendants.
First of you should refactor your class test to class Racer, which is a meaningful name and follows the convention to start classnames with an uppercase letter. Furthermore you should add Stamina, Intel, Heart and Speed to the constructor:
public Racer(String name, int stamina, int intel, int heart, int speed) {
this.name = name;
this.stamina = stamina;
this.intel = intel;
this.heart = heart;
this.speed = speed;
}
Now you can create your racer as following:
Racer fred2 = new Racer("Fred2", 7, 1, 2, 6);
You can store your values in a HashMap. HashMap is a collection consisting of key-value pairs. For the key you can use a string (the name of the racer) and as value you take an instance of your class Racer:
HashMap<String, Racer>() racerMap = new HashMap<>();
racerMap.put("Fred2", fred2);
This you can do in a for-loop for all of your racers. Now you can get the racer objects from your HashMap by calling the getMethod and putting the name as parameter in it. This will return an object of class Racer and you can call the getter methods on this object:
racerMap.get("Fred2").getSpeed();
or
racerMap.get("Fred2").getIntel();
Edit: I just saw your generate method. This method should return the HashMap of racers. In your main method you create a new HashMap:
HashMap<String, Racer> racerMap = generate();
Now you can use the map as described above.

Picking random unique items from an arraylist

Say I want to pick 5 random colors from an array list like this one:
static final List<Color> colors = new ArrayList<Color>();
static {
colors.add(Color.RED);
colors.add(Color.BLUE);
colors.add(Color.GREEN);
}
It's pretty easy I can just do this...
static Random random = new Random();
public static Color getRandomColor() {
return colors.get(random.nextInt(colors.size());
}
But what if I want to pick unique colors which aren't the same? So say I pick RED, how can I make sure to not pick RED again; preferably without removing it from the list, too.
EDIT:
I've found something that works:
Color generatedColor = Theme.randomColor();
for (int i = 0; i < pie.segments.size(); i++) {
if (generatedColor == pie.segments.get(i).getColor()) {
generatedColor = Theme.randomColor();
return;
}
}
this.color = generatedColor;
However someone suggested I just remove them all and re-add once I've finished generating them all, which method should I go for?
EDIT 2:
After shuffling, I get this:
http://i.imgur.com/HPKQNFH.png
Thanks! :)
Use remove method, which return the object at the position and then remove it.
list.remove(int i)
Then your method becomes:
public static Color getRandomColor() {
return colors.remove(random.nextInt(colors.size());
}
and when the list size is 0, reinsert all the colors.

Creating weapon classes and a Combat Class

I am creating a text based game and I am having some issues.. This is what I have so far. So far I have a Combat Class, and two Classes for two different Weapons. I am trying to assign hit points to the weapons themselves. But my biggest issue is in the Combat class. I am trying to create it to were there will be random weapon drops at random times and also random Weapons. So far in the Combat class I have this:
public class Combat {
final int chanceOfDrop = 3;
static Weapons[] wepArray = {new M4(), new M16()}
static boolean[] hasWeapon = {false, true};
public static int ranNumberGen(int chanceOfDrop) {
return (int) (Math.random()*1);
}
private void enemyDead() {
boolean canDrop = false;
if(ranNumberGen(chanceOfDrop)==0){
canDrop = true;
}
if(canDrop == true){
givePlayerWeapon(Weapon[Combat.ranNumberGen(Weapons.length)]);
}
private static void givePlayerWeapon(int w) {
hasWeapon[w] = true;
for w <(Weapons.length-1) {
if has weapon[w] {
System.out.println(wepArray[w].getWeaponName);
}
}
}
}
}
}
I have issues when I am creating the new M4(), and the new M16() it says Type mismatch: cannot convert form M4 to Weapons. I do have a class named Weapons, could that be the problem?
And here is my M4 Class, both M4 and M16 Classes are identical
public abstract class M4 {
private Integer weaponDamage = 5;
private Integer weaponAmmo = 25;
private String weaponName = "M4";
public M4(String name, int ammo, int damage) {
name = weaponName;
ammo = weaponAmmo;
damage = weaponDamage;
}
public String getWeaponName() {
return weaponName;
}
public Integer getAmmo() {
return weaponAmmo;
}
public Integer getDamage() {
return weaponDamage;
}
}
I don't think I have any issues here. Maybe my problem lies within this though. Although, I have a Weapons class, but nothing in it. Do I need that?
A few things to fix at first sight:
Create a generic Weapon class that defines some properties that apply to each weapon, like name, damage, ammo, scope multiplier, etc... Then create subclasses for Weapon, like M4 and M16, that specify the properties and eventually add weapon-specific properties.
Add brackets to this line:
System.out.println(wepArray[w].getWeaponName); // Change to getWeaponName()
Remove the abstract keyword from M4.
Fix the ranNumberGen method because it will always return 0 right now. Math.random() returns a float in the range [0,1[. This means that casting it to an int will always result in 0. Multiply it by n to have a random int in the range of [0, n[. You probably want this:
public static int ranNumberGen(int max) {
return (int) (Math.random() * max);
}
Change this line:
givePlayerWeapon(Weapon[Combat.ranNumberGen(Weapons.length)]);
to:
givePlayerWeapon(wepArray[Combat.ranNumberGen(wepArray.length)]);
The syntax of a for-loop is like this:
for (variable-initialization; condition; increment)
So in your case, you want:
for (int i = 0; i < hasWeapon.length; ++i)
{
if (hasWeapon[i]) System.out.println(wepArray[i].getWeaponName());
}
You might want to revisit your decision to use an inheritance-style heirarchy for game objects before it is too late.
In practice, I've found a component-entity model and/or prototype model to be much more effective. You could take a look at the code in my old Java roguelike game Tyrant for inspiration:
Weapon definitions: mikera/tyrant/Weapon.java (Github is down right now so can't find the exact link, but should be easy enough to Google)
The idea is that you make your objects by setting properties / composing compoenents in a Map-like game object rather than using static inheritance.
When you want to create a random weapon in this model, you can just get a list of all the possible weapon prototypes, and clone one of them at random to make a new weapon.
the mean of abstract in "public abstract class M4" is that you cannot make a new object with this class.
So you can put all commons fields of your weapons in the weapon class and make m4 and m16 extends the weapon and you code would compile.

Java: Adding to an array list

public class Maze
{
public static final int ACTIVE = 0;
public static final int EXPLORER_WIN = 1;
public static final int MONSTER_WIN = 2;
private Square[][] maze;
private ArrayList<RandomOccupant> randOccupants;
private Explorer explorer;
private int rows;
private int cols;
public Maze(Square[][] maze, int rows, int cols, int numTreasures, int numMonsters, String name)
{
int i;
this.maze = maze;
this.cols = cols;
this.rows = rows;
randOccupants = new ArrayList<RandomOccupant>();
for (i = 0; i < numTreasures; i++)
{
randOccupants.add(i) = new Treasure(this); //COMPILE ERROR
}...
Why can't I add this to the arraylist? I believe the java docs says that I'm doing this correctly.
You can do either:
randOccupants.add( i, new Treasure(this) );
...or...
randOccupants.add( new Treasure(this) );
Both are equivalent, since you're always appending the new element to the end of the array.
See https://docs.oracle.com/javase/1.5.0/docs/api/java/util/ArrayList.html.
First, Treasure would need to either inherit from RandomOccupant or implement it (if it is an interface).
Second, if you want to add it at a particular point in the list, the syntax is
randOccupants.add(i,new Treasure(this));
Although it's hard to see why you don't just do
randOccupants.add(new Treasure(this));
since the items will be added in order even if you don't specify a location.
You're trying to add a Treasure to an ArrayList of RandomOccupants, so unless Treasure is a RandomOccupant, that's not going to work. The given code does not make it clear whether Treasure is a subclass of RandomOccupant, so it's not possible from the code here to say whether that's part of the problem.
What you're actually doing is adding an int to the list here, which is definitely not a RandomOccupant.
ArrayList's add() method returns either boolean or void depending on the version that you're using, so you can't assign to it. You're using the method incorrectly.
The two versions of add() are:
boolean add(E e)
void add(int index, E element)
The second version inserts the element at the specified position, and the first one inserts it at the end. Presumably, what you're intending to do is this:
for(i = 0; i < numTreasures; ++i)
randOccupants.add(new Treasure(this));
But of course, that assumes that Treasure is a subclass of RandomOccupant. If it isn't, then you'll need to change the type of the ArrayList for it to hold Treasures.
Because it is not a RandomOccupant.
Because you're using the add method wrong. You would call:
randOccupants.add(new Treasure(this));

Categories