patternjavaModerate
Does this simulation follow abstraction and encapsulation?
Viewed 0 times
thissimulationencapsulationabstractionfollowdoesand
Problem
This below code implements a simulation of an ocean(as 2d-array of cells) which currently have Shark, fish or be Empty. User can run this simulation, as shown below:
With this command, SimText will animate a 25x30 ocean array with a
```
/ Critter.java /
package Project1;
/**
* The abstract class Critter defines a base class for any creature
* that can exist at a specific location in the ocean.
* @author mohet01
*
*/
abstract class Critter {
/**
* Below data member defines a location of a Critter in an Ocean
*/
Point location;
public Critter(int x, int y){
location = new Point(x,y);
}
public Point getLocation(){
return location;
}
/**
* This method computes the behavior of the Critter in the Ocean.
* Computes new value
> java Simtext 25 30 1With this command, SimText will animate a 25x30 ocean array with a
starveTime of 1 unit./* point.java */
package Project1;
/**
* The Point class defines a location (x,y) in the Ocean.
*
* @author mohet01
*
*/
class Point {
/**
* Here top-left of Windows screen is considered as origin.
* x is an x-coordinate of a location in an ocean
* y is an y-coordinate of a location in an Ocean
*/
private int x;
private int y;
/**
* Constructor creates a Point object below co-ordinates
* @param x
* is an x-coordinate of a Critter location in an Ocean
* @param y
* is an y-coordinate of a Critter location in an Ocean
*/
public Point(int x, int y){
this.x = x;
this.y = y;
}
/**
* This method returns the x-coordinate of Critter in an ocean
* @return
* x-coordinate of a Critter location in an Ocean.
*/
public int getX(){
return this.x;
}
/**
* This method returns the y-coordinate of Critter in an ocean
* @return
* y-coordinate of a Critter location in an Ocean.
*/
public int getY(){
return this.y;
}
}```
/ Critter.java /
package Project1;
/**
* The abstract class Critter defines a base class for any creature
* that can exist at a specific location in the ocean.
* @author mohet01
*
*/
abstract class Critter {
/**
* Below data member defines a location of a Critter in an Ocean
*/
Point location;
public Critter(int x, int y){
location = new Point(x,y);
}
public Point getLocation(){
return location;
}
/**
* This method computes the behavior of the Critter in the Ocean.
* Computes new value
Solution
Ahhh, tile based 2D grid layouts.
It's an OO problem for sure. How can you keep things separate if objects on tiles need to know what tile they're on and their neighboring tiles and what's on their neighboring tiles?
I did a similar exercise and I still need to think carefully about it.
I do feel the best solution is the following:
Create an enum
Create a class
Give a Cell a possible
Give a Cell a
Remove a
This is something I can do due to my design; it's not something you should do before thinking hard about what a position means and how to identify an object's position. In my case, I place the responsibilities all on cells. As
And lastly, give Game a 2D array (
And have the game just go through the cells, asking how many neighbors have
This solves your problems where your Ocean is recreated each frame. This solves your problems where Critters of various sorts need to hassle with
The hassles you gain are that you now need two iterations. First iteration is to find out what needs to happen to all the cells. Second iteration is to apply the changes. I think you'll want to make a new 2D array of objects to place on the cells. The alternative is storing a set of commands per critter; Whilst this does make more sense, it doesn't scale. ... in a functional programming language it would: one would create a set of delayed function calls, then execute them all after another.
But that's my solution. What about yours?
Well, you have a few issues.
How would you go about solving these issues?
Personally, I take a whiteboard and start by drawing the domain model classes. These are things that are mentioned in a problem statements. You have the disadvantage of a biased problem statement. Here's the bias:
(If you are foolish enough to try to implement a timestep using just a single Ocean object, you will modify the values of cells whose old values are still needed to compute the new values for other cells, and thus you will compute the wrong answer.)
But I digress. One starts by identifying objects and concepts.
The first paragraph ("The ocean is rectangular, but the edges...") talks at length about an
We have thusly identified an object
The third paragraph is a hint regarding the implementation of the grid concept. They're leading you w
It's an OO problem for sure. How can you keep things separate if objects on tiles need to know what tile they're on and their neighboring tiles and what's on their neighboring tiles?
I did a similar exercise and I still need to think carefully about it.
I do feel the best solution is the following:
Create an enum
Direction.Create a class
Cell, give it a Map neighbors.Give a Cell a possible
CellObject (like Fish and Shark).Give a Cell a
Point so it knows where it is. (see below in "how do we simulate a timestep")Remove a
Critter's x and y. It's not supposed to know those things. Sharks don't have GPS. This is something I can do due to my design; it's not something you should do before thinking hard about what a position means and how to identify an object's position. In my case, I place the responsibilities all on cells. As
CellObjects gain more responsibility, my design falls apart. There is no clean way to make an object on a grid navigate through the grid without telling it about the grid. However, take a look at yourself: without a map OR your memory, you too must rely on your own senses to navigate a maze. And in all cases, you do this via looking at your surroundings (the Cell). Thus in my design, CellObjects never gain much responsibility. They're just for holding state. Simply put; you know you are "here", but you don't know your longitude and latitude. That's why you don't have x or y. To put x or y on an object like that is to pull it away from the actual world - you're not "there" any more, but you're a map marker. Map markers can access the map, yes, map markers can pathfind, yes, but map markers cannot eat fish.And lastly, give Game a 2D array (
[x][y]) for storing cells. This array is for iterating cells. The array is not for searching for things. That's what Cell's neighbors are for.And have the game just go through the cells, asking how many neighbors have
Shark.class and Fish.class instances on them. Add the relevant changes to a list, then make the relevant changes.This solves your problems where your Ocean is recreated each frame. This solves your problems where Critters of various sorts need to hassle with
x and y. This solves your problem where adding a Critter to an Ocean means you need to hassle with x and y. This localizes your game rules in one location.The hassles you gain are that you now need two iterations. First iteration is to find out what needs to happen to all the cells. Second iteration is to apply the changes. I think you'll want to make a new 2D array of objects to place on the cells. The alternative is storing a set of commands per critter; Whilst this does make more sense, it doesn't scale. ... in a functional programming language it would: one would create a set of delayed function calls, then execute them all after another.
But that's my solution. What about yours?
Well, you have a few issues.
- Duplicated information. Both
CritterandGameknow where they are.
- Ocean is recreated every timestep. This might be okay for your assignment; but for real life simulations, this sort of thing kills performance. Bad performance results in scaled down models, which means something meant to simulate global populations can only handle a single sea.
- Empty critter. This just doesn't make sense. Isn't it the Cell that's empty?
- Fish needs to know about Shark. Shark needs to know about Fish. What happens when I add an extra step to the chain and BigFish need to eat SmallFish? All the classes change.
How would you go about solving these issues?
Personally, I take a whiteboard and start by drawing the domain model classes. These are things that are mentioned in a problem statements. You have the disadvantage of a biased problem statement. Here's the bias:
(If you are foolish enough to try to implement a timestep using just a single Ocean object, you will modify the values of cells whose old values are still needed to compute the new values for other cells, and thus you will compute the wrong answer.)
But I digress. One starts by identifying objects and concepts.
The first paragraph ("The ocean is rectangular, but the edges...") talks at length about an
Ocean of sorts. It goes into detail on how there's a grid in it. The second paragraph continues on stating that the grid has x and y coordinates, how you need to support values that are out of bounds due to the shape of the ocean... We have thusly identified an object
Ocean and a concept grid. The difference between objects and concepts is that objects are described as what they are and what they can do, and concepts are described as a set of requirements. This difference is important. You see, objects WILL end up in your eventual result. Concepts might be integrated - you'll see them back in multiple pieces.The third paragraph is a hint regarding the implementation of the grid concept. They're leading you w
Code Snippets
/**
* Here top-left of Windows screen is considered as origin.
* x is an x-coordinate of a location in an ocean
* y is an y-coordinate of a location in an Ocean
*/
private int x;
private int y;/**
* Here top-left of Windows screen is considered as origin.
* x is an x-coordinate of a location in an ocean
*/
private int x;
/**
* Here top-left of Windows screen is considered as origin.
* y is an y-coordinate of a location in an Ocean
*/
private int y;int r = random.nextInt();
if (r < 0) {
sea.addCritter(new Fish(x,y));
} else if (r > 1500000000) {
sea.addCritter(new Shark(x,y,hungerLevel));
}Context
StackExchange Code Review Q#68481, answer score: 10
Revisions (0)
No revisions yet.