I'm making a new version of this foxes and rabbits Simulation - https://www.youtube.com/watch?v=F7KtfGELZsM
What I would like to do is be able to store multiple animals within the same square of the grid, not just one at a time. At the moment, Animals are stored in a 2d multidimensional array Animal[x][y] which if an animal is already in this location then it will replaced with the new animal. Perhaps this needs to be changed to a HashMap or something similar? For example -
http://comscigate.com/HW/cs302/BlueJ/projects/chapter10/foxes-and-rabbits-v2/Field.java
Potentially something like this:
// Storage for the animals.
private List<Field> field;
private List<List<Animal>> animalsList;
public void place(Animal animal)
{
Location location = animal.getLocation();
animalsList = new ArrayList<List<Animal>>();
field = new ArrayList<Animal>;
field.add(Field(location.getRow(), location.getCol()));
animalsList.add(field, animal);
}
Id use a simple storage system. Lets assume you have a 10*10 field :
You need a List<List<Animal>> list=new ArrayList<List<Animal>>();
You need 100 spaces that are all empty(well, you could also use an array) :
for (int i=0; i < 100; i++) {
list.add(new ArrayList<Animal>());
}
Your method :
public void addAt(int x, int y, Animal a) {
int w=10; //WIDTH
int h=10; //HEIGHT
List<Animal> animals_here=list.get(y*h+x);
animals_here.add(a);
list.put(y*h+x,animals_here);
}
if youd like to extract the position from an index :
- x=index%h;
- y=index/h; //Integer divison, no doubles/floats !
Another, probably easier accessable attempt would be a Map :
class Point {
public int x;
public int y;
public Point(int x, int y) {
this.x=x;
this.y=y;
}
}
Map<Point,List<Animal>> map=new HashMap();
public void addAt(int x, int y,Animal a) {
if (map.get(new Point(x,y))==null) {
List<Animal> animals_here=new ArrayList<Animal>();
animals_here.add(a);
map.put(new Point(x,y),animals_here);
}
else {
List<Animal> animals_here=map.get(new Point(x,y));
animals_here.add(a);
map.put(new Point(x,y),animals_here);
}
}
EDIT :
Efficiency :
CPU :
- Solution 1 : Indices are calculated each time, not so easy acess
- Solution 2 : Map is very fast.
RAM :
- Solution 1 : Less animals than cells : -, because you have unused cells
More animals than cells : +, because almost every cell will be used and the keys havent to be stored
- Solution 2 : Less animals than cells : +, because they are saved with keys
More animals than cells : -, because keys are always stored too
About the code you provided on GitHub :
Make another class for the field.
class Field {
public Map<Point, List<Animal>> map;
public int w,h;
public Field(int w, int h) {
this.w=w;
this.h=h;
map=new HashMap<Point, List<Animal>>();
}
public void addAnimal(int x, int y) {
if (map.get(new Point(x, y)) == null) {
List<Animal> animals_here = new ArrayList<Animal>();
animals_here.add(animal);
map.put(new Point(x, y), animals_here); //Set
}
else {
List<Animal> animals_here = map.get(new Point(x, y));
animals_here.add(animal);
map.put(new Point(x, y), animals_here); //Overwrite
}
}
public List<Animal> animalsAt(int x, int y) { //If it returns null, there isnt an animal
return map.get(new Point(x,y));
}
public void doStuff() {
for (int x=0; x < w; x++) {
for (int y=0; y < h; y++) {
List<Animal> animals_there=animalsAt(x,y);
if (animals_there != null) {
for (Animal a:animals_there) {
//Do your stuff
}
}
}
}
}
}
The point class is only to store two values : x and y. You dont need anything more.
class Point {
public int x;
public int y;
public Point(int x, int y) {
this.x=x;
this.y=y;
}
}
Dont make all vars private. Then you wont have to use getters and setters, you can access them easier.
BUT I THINK ITS MAYBE EASIEST TO STORE THE POSITION IN EVERY ANIMAL((-)very memory inefficent, but since you're not going to have 1000000 animals, it will be enough)
class Animal {
public String type;
public Location location;
public Animal(String type, Location location) {
this.type=type;
this.location=location;
}
}
//When you want to have specific methods(and vars) for different animals, create subclasses :
class Lion extends Animal {
public Lion(String type, Location location) {
super(type,location);
}
public void live(List<Object> other_animals) {
List<Integer> toRemove=new ArrayList<Integer>();
int index=0;
for (Object o:other_animals) {
if (o instanceof Mouse) {
Mouse m=(Mouse)o;
if (m.location.equals(this.location)) {
toRemove.add(index);
}
}
index++;
}
}
}
class Mouse extends Animal {
public Mouse(String type, Location location) {
super(type,location);
}
}
//Your field :
class Field {
public List<Object> animals;
public Field() {
animals=new ArrayList<Object>();
}
public void add(Object o) {
animals.add(o);
}
public List<Object> getAt(Location l) {
List<Object> animals_there=new ArrayList<Object>();
for (Object o:animals) {
if (((Animal)(o)).location.equals(l)) {
animals_there.add(o);
}
}
return animals_there;
}
}
Related
I am trying to make a videogame that is similar to "Turing Complete". In this game you are supposed to connect circuit pieces to create a computer by the end. So I have a question on inheritance. I have a class called "Circuitware" and every object extends this as follows
public Circuitware implements connectable {
protected int x;
protected int y;
protected int allowedConnetions;
protected Ciruitware[] connections;
private int totalConnections;
public Circuitware(int x, int y, int allowedConnections, Circuitware[] connections) {
this.x = x;
this.y = y;
this.allowedConnections = allowedConnections;
this.connections = new Array[allowedConnections];
for (Object O: connections) {
if (O != null) {
this.totalConnections += 1;
}
}
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public<T> void addConnection(T connection) {
if (this.totalConnections<this.allowedConnections) {
this.connections.add(connection);
}
}
}
Now an example of a subclass is
public class LogicGate extends Circuitware {
String type;
public LogicGate(int x, int y, int allowedConnections, Circuitware[] connections, String type) {
super(x, y, allowedConnections, connections);
this.type = type;
}
public boolean output() {
//Depending on the gate and input we output things
}
}
Now the thing is that the number of allowed connections depends on the type of the circuit, for example logic gates in my game can have 1 connection if it is an NOT gate, 2 connections if it is an AND, XOR, NOR gates or 3 connections if it is and extended OR, extended AND gates, where are switches can only have 0. Is there are better way of doing this?
I also need help understanding that if I have an array of type Circuitware can I add objects from its subclasses? Because the output of logic gates and inputs of other logic gates while they can be inputs to clocks.
Would it be better, design-wise, if I got rid of the "Circuitware" class altogether? But then wouldn't that make connections between different classes harder?
I have class of (sub)Objects
public class SubObjects {
int depth;
public SubObjects(int d) {
this.depth = d;
}
}
And a class of Objects
public class Objects {
private int height;
private int width;
ArrayList<SubObjects> liste;
public Objects(int h, int w) {
this.height = h;
this.width = w;
this.liste = new ArrayList<>();
}
}
The Objects hold the values height and width and an ArrayList of SubObjects. This works as intended, I do however want to store multiple types of SubObjects from different classes in these ArrayLists.
After a bit of googling I changed the Objects class to
public class Objects {
private int height;
private int width;
ArrayList<Object> liste;
public Objects(int h, int w) {
this.height = h;
this.width = w;
this.liste = new ArrayList<Object>();
}
}
This allows me, as I intended, to store Objects from a second class SubObjects2 inside the ArrayList
public class SubObjects2 {
int weight;
public SubObjects2(int weight) {
this.weight = weight;
}
}
This was great and I thought I had solved it, but then I ran the main class and while I, with the earlier implementation could return values with a getter from the objects in the ArrayList
... liste.get(i).depth (in a for loop)
The same query now returns the following error
Unresolved compilation problem:
depth cannot be resolved or is not a field
How do I access the values inside the SubObjects that are stored in the ArrayList now?
Your problem is that the Object class has no field with the name depth and only SubObject has this attribute
If all of your types have common attributes that you want to get it, you can create an interface and all of them should implement it it for example
interface SubObject {
int value();
}
public class SubObjects implements SubObject {
...
#Override
public int value() {
return depth;
}
}
public class SubObjects2 implements SubObject {
...
#Override
public int value() {
return weight;
}
}
and now you will create a list of SubObject and in the loop, it will be
for (int i = 0; i < lists.size() ; i++) {
int value = lists.get(i).value();
}
The other solution is to check for the type and cast it before getting the value for example
List<Object> lists = new ArrayList<>();
for (int i = 0 ; i < lists.size(); i++) {
Object object = lists.get(i);
if (object.getClass() == SubObjects.class) {
SubObjects subObject = (SubObjects) object;
int depth = subObject.depth;
}
else if if (object.getClass() == SubObjects2.class) {
SubObjects2 subObject2 = (SubObjects2) object;
int weight = subObject2.weight;
}
}
If there's no relationships between two classes other than that they both extend Object class which all objects do and you want to store objects of those two classes in the same list, you can store them in a list of objects.
Before you can access attributes of the object, you need to cast it to the type you want to use. This is how it's done before generics.
List list = new ArrayList(List.of(Integer.valueOf(1), "hello"));
for(Object o: list){
if (o instanceof Integer){
System.out.println("o is an integer.");
Integer i = (Integer) o;
System.out.println(i.intValue());
} else if (o instanceof String){
System.out.println("o is a string.");
String s = (String) o;
System.out.println(s.length());
}
}
I'm newbie in Java. I'm not sure why line my2.print_list(); is printing only object my2. I want to print every time whole list of objects. I'm adding every object to list in constructor. I'm 90% sure that for loop in function print_list is good. The compiler shows no problems. I'll appreciate all help.
public class Main {
public static void main(String[] args) {
// write your code here
rectangle my = new rectangle(5);
rectangle my1 = new rectangle(3,6);
rectangle my2 = new rectangle(10,7);
System.out.println( my2.getCounter());
my2.print_list(); ////////////////////<- described line
}
}
/// my class rectangle
import java.util.ArrayList;
import java.util.List;
public class rectangle {
public static int counter =0;
public int x;
public int y;
public List<rectangle> List = new ArrayList<rectangle>();
public rectangle(int x, int y) {
this.x = x;
this.y = y;
System.out.println("Rec");
List.add(this);
counter++;
}
public rectangle(int x) {
this.x = x;
this.y = x;
System.out.println("Sqr");
List.add(this);
counter++;
}
#Override
public String toString() {
return "x->"+x+" y->"+y+" Field: "+(x*y);
}
public void print_list()
{
for(rectangle x : List)
{
System.out.println(x);
}
}
Every instance of your class has its' own instance of List. Make it static if it should be shared (which is the only way your List will be populated). Also, please rename the variable List (it looks exactly like the interface java.util.List). Also, there's no reason to make it public.
private static List<rectangle> myList = new ArrayList<rectangle>();
And then change print_list like
public void printList()
{
for(rectangle x : myList)
{
System.out.println(x);
}
}
Also, the class name should be Rectangle (to follow Java naming conventions).
Change
public List<rectangle> List = new ArrayList<rectangle>();
to
public static List<rectangle> List = new ArrayList<rectangle>();
So there's only one instance of List.
I've got this code:
int width = 1280;
int height = 720;
List<ElectronicDevice> devices = new ArrayList<ElectronicDevice>();
class ElectronicDevice {
int x;
int y;
// ...
}
class EClock extends ElectronicDevice {
int hz;
EClock(int x, int y, int clock) {
this.x = x;
this.y = y;
this.hz = hz;
}
// ...
}
class EBulb extends ElectronicDevice {
EClock(int x, int y) {
this.x = x;
this.y = y;
}
// ...
}
class ToolbarElement {
ElectronicDevice dev;
ToolbarElement(ElectronicDevice dev) {
this.dev = dev;
}
public void addDevice() {
// somehow add a copy of `dev` to the `devices` list
}
}
List<ToolbarElement> elements = new ArrayList<ToolbarElement>();
elements.add(new EClock(width/2, height/2, 5));
elements.add(new EBulb(width/2, height/2));
elements.get(0).addDevice();
I need to add a copy of ToolbarElement dev to devices, but I don't know how. It needs to be a deep copy. In the program I don't know the constructors of all devices, I'd like to just deep clone dev into devices.
I tried adding implements Cloneable to the ElectronicDevice class, but then I would need to add that and a clone() method to every class that extents ElectronicDevice.
After adding the implements Cloneable to ElectronicDevice it mostly worked, but all the clocks had desynchronized after adding more than 1 of them (this is a graphical application in Processing, every class that extends ElectronicDevice can have a behavior() method which specifies how it behaves and the clock oscillates between 0 and 1 with the frequency of hz Hz.)
This was my addDevice() implementation:
// In ElectronicDevice
class ElectronicDevice implements Cloneable {
// ...
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// end of class code
}
// In ToolbarElement
class ToolbarElement {
// ...
public void addDevice() {
try { devices.add((ElectronicDevice)object.clone()); }
catch (CloneNotSupportedException e) { e.printStackTrace(); }
}
// end of class code
}
Is there any solution that wouldn't require modifying every single class that extends ElectronicDevice?
I have this sparse matrix implementation:
I'm trying to write getter/setter methods for individual elements based on their key, but I'm not sure how to do this with my custom type Coordinates. For example, theMatrix.get(coordinates) (the usual way) doesn't work.
Could someone show me how to do this?
Class coordinate is not accessible outside of your Matrix class.
Indeed, its an implementation detail that you don't want to make visible to the end-user. Please check the getters and setters in the example below.
If you still want to make Coordinates class available to the end-user, you wan make it public.
public class Matrix
{
private static class Coordinates
{
private int x = 0;
private int y = 0;
private int data = 0;
public Coordinates(final int x, final int y)
{
this.x = x;
this.y = y;
data = ((x + "") + (y + "")).hashCode();
}
#Override
public boolean equals(final Object obj)
{
if (obj instanceof Coordinates)
{
Coordinates Coordinates = (Coordinates) obj;
return ((x == Coordinates.x) && (y == Coordinates.y));
}
else
{
return false;
}
}
#Override
public int hashCode()
{
return data;
}
}
private int numrows;
private int numcolumns;
private HashMap<Coordinates, Double> theMatrix;
public Matrix(final int numrows, final int numcolumns)
{
this.numrows = numrows;
this.numcolumns = numcolumns;
}
public Matrix(HashMap<Coordinates, Double> matrixdata)
{
theMatrix = new HashMap<Coordinates, Double>(matrixdata);
}
public Double get(int row, int col, double defaultValue)
{
Double ret = theMatrix.get(new Coordinates(row, col));
return ret != null ? ret : defaultValue;
}
public void set(int row, int col, Double value)
{
theMatrix.put(new Coordinates(row, col), value);
}
}