I will start by explaining the scenario.
I have to create a Vector to hold a list of Circles.
Then I create a circle object, and add it to the Vector.
Finally I have to print the state of each circle in the list (the state isn't important to define, just it's colour and position etc).
Basically my problem is, how do I hold the circles so that I can then pass in the name of one of them and it will print the correct circle's state. It may be clearer to show you my code.
I have 3 classes, that main one called Lab83Test, the Vector one, called CircleList, and the Circle one, called Circle. (The formatting has gone weird and I can't fix it, so apologies!)
Lab83Test:
public class Lab83Test {
public static void main(String[] args) {
makeNewCircle();
}
public static void makeNewCircle() {
CircleList newList = new CircleList();
Circle newCircle = new Circle();
newList.addCircle(newCircle);
newCircle.makeVisible();
newList.printDetails();
}
}
CircleList:
import java.util.Vector;
public class CircleList {
private Vector circleVector;
public CircleList() {
circleVector = new Vector();
}
public void addCircle(Circle circleName) {
circleVector.add(circleName);
printDetails();
}
public void addCircleToPlace(Circle circleName, int pos) {
circleVector.add(pos, circleName);
printDetails();
}
public void removeCircleFromPos(int pos) {
circleVector.remove(pos);
printDetails();
}
public void removeAllCircles(int pos) {
circleVector.clear();
printDetails();
}
public void printDetails() {
}
}
The circle class isn't too important, and it has a lot of methods for moving the circle and stuff. The main thing is that it has to return its state.
If you just want to iterate over all Circel in your list and print their name, you can do it this way:
public void printDetails() {
for (Circle c: circleVector) {
System.out.println(String.format("%s: center=(%.1f/%.1f) radius=%.1f", c.getName(), c.getCenterX(), c.getCenterY(), c.getRadius()));
}
}
I don't know how your Circle class looks so I just assumed some method names.
If you want to find a specific circle by name:
for (Circle c: circleVector) {
if (c.getName().equals(nameToFind)) return c;
}
Or you could use a Map<String, Circle> instead of your vector and just do return circleMap.get(name);. Your addCircle() would then look like this:
public void addCircle(Circle circle) {
circleMap.add(circle.getName(), circle);
printDetails();
}
Edit1: regarding your comment: Your vector does not have a defined type. Change this:
...
public class CircleList {
private Vector<Circle> circleVector;
public CircleList() {
circleVector = new Vector<Circle>();
}
...
Related
I have the task of creating a simple drawing app, where one can draw basic shapes (ovals,lines,rectangles) with border and fill colors of choice, using Java Swing and MVC.
The shapes part of the model is implemented using the composite pattern. The functionality to be implementing is drawing (this is already handled by the shapes classes themselves), resizing, moving and deleting shapes and I am supposed to use chain of responsibility (CoR) pattern to accomplish this.
CoR makes sense to me in theory, but I have difficulty grasping how I can apply it for implementing the functionality in practice. I understand that when I click on the drawing panel the program should recognize which shape is selected and then I can implement the methods for resizing,moving,deleting.
So what I need advice on is:
1) how to practically implement CoR pattern here?
2) what is a good way to implement the functionality for resizing, moving, deleting? In own concrete handler classes, as methods in the shapes classes, other?
Many thanks for help.
Here is a proposed basic implementation of CoR.
For ease of use the following code is a one-file mre : the entire code can be copy-pasted into ShapeManipulator.java and run:
public class ShapeManipulator {
public static void main(String[] args) {
Shape s1 = new Shape();
Shape s2 = new Shape();
Shape s3 = new Shape();
ShapeManipulationBase move = new MoveHandler();
ShapeManipulationBase resize = new ResizeHandler();
ShapeManipulationBase delete = new DeleteHandler();
move.setXparam(50).setYparam(25).handle(s1);
resize.setXparam(100).setYparam(250).handle(s1);
resize.setXparam(200).setYparam(20).handle(s2);
delete.handle(s3);
}
}
//CoR basic interface
interface ShapeManipulationHandler {
void handle(Shape shape);
}
//base class allows swtting of optional x, y parameters
abstract class ShapeManipulationBase implements ShapeManipulationHandler {
protected int Xparam, Yparam;
//setters return this to allow chaining of setters
ShapeManipulationBase setXparam(int xparam) {
Xparam = xparam;
return this;
}
ShapeManipulationBase setYparam(int yparam) {
Yparam = yparam;
return this;
}
#Override
public abstract void handle(Shape shape) ;
}
class MoveHandler extends ShapeManipulationBase {
#Override
public void handle(Shape shape) {
System.out.println("Moving "+ shape + " by X="+ Xparam + " and Y="+ Yparam);
}
}
class ResizeHandler extends ShapeManipulationBase {
#Override
public void handle(Shape shape) {
System.out.println("Resizing "+ shape + " by X="+ Xparam + " and Y="+ Yparam);
}
}
class DeleteHandler extends ShapeManipulationBase {
#Override
public void handle(Shape shape) {
System.out.println("Deleting "+ shape);
}
}
class Shape{
private static int shapeCouner = 0;
private final int shapeNumber;
Shape() {
shapeNumber = ++shapeCouner;
}
#Override
public String toString() {
return "Shape # "+shapeNumber;
}
}
I intend to write a program that simulates particles collisions in one or more dimension. For the 2D case, I would also like to make a GUI that shows the particles.
I have a main class, ParticleCollider, which contains an inner class, Particle, an array of said Particlesas well as some methods for updating the positions and velocities of the particles. The class roughly looks like this:
class ParticleCollider {
class Particle {
private double mass;
private double[] pos;
//plus some other private class variables
public Particle(double mass, double[] pos) {
this.mass = mass;
this.pos = pos;
}
}
private Particle[] pArray;
//Details of constructor are irrelevant
public ParticleCollider() {
}
//Do stuff to particles in pArray, i.e. change their positions and velocitites
public void update() {
//For example
pArray[0].pos[0] = 0;
}
}
In the graphics class, I want to be able to access the Particles so that I can find their positions and radii for drawing purposes. One way would of course be to add a method getParticlesin ParticleColliderto return the array of Particles, pArray. My question is now if this would be considered a violation of encapsulation. Because the Particleclass has no setters, I cannot change the Particles. Also, because an array hase fixed length, I cannot add any Particles. The only thing I could do, which I guess is pretty bad, is take some Particleand assign it the value of null.
EDIT
It has been suggested that I use a List instead of an array and provide an iterator to said List. It would seem to me that this would not solve the encapsulation problem. Regardless, I'm relucant to abandon the array because I need to be able to select a random Particle in the collection of Particles and then iterate it cyclically.
How about using this pattern:
public class Particle {
// Particle code
}
public class Particles implements Iterable<Particle> {
ArrayList<Particle> myParticles = new ArrayList<Particle>();
public void add(Particle particle) { myParticles.add(particle); }
public Iterator<Particle> iterator() {
return myParticles.iterator();
}
// more code on particles
}
void bla() {
Particles particles = new Particles();
particles.add(new Particle());
particles.add(new Particle());
for (Particle particle : particles) {
System.out.println("P="+particle);
}
}
If you want to inhibit the remove() on this iterator you might use this pattern:
public static class Particles implements Iterable<Particle> {
ArrayList<Particle> myParticles = new ArrayList<Particle>();
public void add(Particle particle) { myParticles.add(particle); }
public Iterator<Particle> iterator() {
return new Iterator<Particle>() {
Iterator<Particle> listIterator = myParticles.iterator();
#Override
public boolean hasNext() {
return listIterator.hasNext();
}
#Override
public Particle next() {
return listIterator.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
I have:
public class HFSim extends ApplicationTemplate
{
private static class AppFrame extends ApplicationTemplate.AppFrame
{
void setBuoy()
{
//code
Position buoypos=Position.fromDegrees(buoylat, buoylon);
}
void setVehicle()
{
//code
Position vehiclepos=Position.fromDegrees(lat, lon, elev);
}
double findDistance()
{
//find distance between marker (vehicle) and a buoy
Earth earth= new Earth();
double radius = earth.getEquatorialRadius();
double distancebetween=LatLon.ellipsoidalDistance(buoypos, vehiclepos, radius, 6356752.3);
return distancebetween;
}
How can I use the objects buoypos and vehiclepos in the setBuoy and setVehicle methods in the findDistance() method?
You have two clearcut options here:
Make buoypos and vehiclepos instance variables, or..
Provide more descriptive names for setVehicle() and give it a Position return type.
Option 1 would look like this:
...classname...
{
private Position vehiclePosition;
private Position bouyPosition;
public void setVehiclePosition()
{
this.vehiclePosition = ....
}
}
Option 2 would look like this:
...classname...
{
public Position createVehiclePosition()
{
vehiclePosition = ....
return vehiclePosition.
}
}
Finally, you would use them as either:
...classname...
{
public double findDistance()
{
...this.vehiclePosition...
or
Position vehiclePos = this.createVehiclePosition();
}
}
The option you choose is highly dependent on how the class is supposed to behave.
Use variables with the class scope. This essentially means
///outside of a method but within the class you'll want to set:
private this.bouypos = new Position;
private this vehiclepos = new Position;
//method1 {
Position this.buoypos=Position.fromDegrees(buoylat, buoylon);
//method2 {
Position this.vehiclepos=Position.fromDegrees(lat, lon, elev);
//method3 calls things set in method1 & 2
findDistance(){
//code
double distancebetween=LatLon.ellipsoidalDistance(this.buoypos, this.vehiclepos, radius, 6356752.3);
}
Make the findDistance method take two Positions as parameters
double findDistance(Position buoypos, Position vehiclepos){
}
I am currently making a terrain generator, everything works fine in one class but I am going to be expanding my application.
Currently I have a JFrame class which holds everything, generating the terrain, painting the terrain, finding locations etc.
I want to add another class that will generate the terrain but when I create this class I need to access fields from the main JFrame class and when I do I get a stack overflow error - here is my code.
public class Simulator extends Applet
{
//fields
public Simulator()
{
grid = new int[100][100];
inhabGrid = new boolean[grid.length][grid.length];
gridSize = grid.length - 1;
dist = grid.length;
TerrainGenerator gen = new TerrainGenerator();
setSize(dist,dist);
seedGrid();
findInhabLocation();
printGridToConsole();
}
public void paint(Graphics g)
{
//panting the grid
}
public void seedGrid()
{
//seeding
}
public boolean generateTerrain(int x1,int y1, int x2, int y2)
{
//terrain generator
}
public boolean mouseUp(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public boolean keyEvents(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public void findInhabLocation()
{
//find best inhabitant location
}
public int locateWater(int x, int y)
{
//finding closest water
}
public int locateJungle(int x, int y)
{
//finding closest jungle
}
}
}
That works fine in its own class but when I create a class for example:
public class TerrainGenerator
{
Simulator sim = new Simulator();
}
I know this has something to do with the constructor and it's something silly I am doing, what would be the best way of splitting up this app into classes, for example terrain generator, inhabitants etc
For example I want to be able to call a method from the 'TerrainGenerator' class and call i.e. terrainGenerator.generateTerrain
Your TerrainGenerator creates a Simulator object and vice versa, hence you'll end up with infinitely many objects (but at some point the stack is full and a stack overflow exception is thrown instead...)
Instead of creating a new Simulator in your TerrainGenerator, you should pass a reference to your current Simulator (well, actually, that is not a great design either, but I'm not gonna confuse you with the problems of circular references).
Heuster answer is correct, furthermore, I think you could take look at MVC to help you organize your classes.
Depending which should be the parent, you can pass in the instantiated class to the other, ie;
private final TerrainGenerator gen; //if you need to save this.
public Simulator(TerrainGenerator terrainGenerator)
{
this.gen = terrainGenerator;
....etc
}
public class TerrainGenerator
{
Simulator sim = new Simulator(this);
}
or
private final TerrainGenerator gen; //if you need to save this.
public Simulator()
{
this.gen = new TerrainGenerator(this);
....etc
}
private final Simulator sim; //If you need to save it.
public class TerrainGenerator
{
public TerrainGenerator(Simulator simulator) {
this.sim = simulator;
}
}
I'm trying to design an undo/redo mechanism to my Chess game.. I decided to use stack data structure which is going to build on an ArrayList.. I also want that my UndoStack and RedoStack classes should be singleton.. However i'm getting
method does not override or implement a method from a supertype
pop() in UndoStack cannot implement pop() in IStackable
return type Move is not compatible with cgas5.Move
where Move is a type-variable:
Move extends Object declared in class UndoStack
error..
Here is my IStackable interface:
package cgas5;
public interface IStackable {
abstract public Move pop();
abstract public void push(Move m);
}
and my UndoStack class
package cgas5;
import java.util.ArrayList;
public class UndoStack<Move> extends ArrayList<Move> implements IStackable {
UndoStack undoStack;
private UndoStack() {
undoStack = new UndoStack();
}
public UndoStack getUndoStack() {
if (undoStack == null) {
undoStack = new UndoStack();
}
return undoStack;
}
#Override
public Move pop() {
Move m = get(size() - 1);
remove(size() - 1);
return m;
}
#Override
public void push(Move m) {
add(m);
}
}
and if it's necessary my Move class:
package cgas5;
public class Move {
private Piece pieceToMove;
private Square currentSquare;
private Square targetSquare;
private Piece capturedPiece;
private Piece promotedPiece;
public Move(){
}
public Move(Piece pieceToMove, Square currentSquare, Square targetSquare){
this.pieceToMove = pieceToMove;
this.currentSquare = currentSquare;
this.targetSquare = targetSquare;
}
public Piece getPieceToMove() {
return pieceToMove;
}
public void setPieceToMove(Piece pieceToMove) {
this.pieceToMove = pieceToMove;
}
public Square getCurrentSquare() {
return currentSquare;
}
public void setCurrentSquare(Square currentSquare) {
this.currentSquare = currentSquare;
}
public Square getTargetSquare() {
return targetSquare;
}
public void setTargetSquare(Square targetSquare) {
this.targetSquare = targetSquare;
}
public Piece getCapturedPiece() {
return capturedPiece;
}
public void setCapturedPiece(Piece capturedPiece) {
this.capturedPiece = capturedPiece;
}
public Piece getPromotedPiece() {
return promotedPiece;
}
public void setPromotedPiece(Piece promotedPiece) {
this.promotedPiece = promotedPiece;
}
}
Thanks in advance..
This is the problem:
public class UndoStack<Move> extends ArrayList<Move>
That's using Move as a generic type parameter, whereas really you don't want a generic type at all - you just want to use Move as the type argument for ArrayList<E>. You want:
public class UndoStack extends ArrayList<Move>
That should fix the problem - although personally I'd strongly recommend using composition instead of inheritance here. (In other words, make your UndoStack type contain an ArrayList<Move> - or something similar - rather than subclassing it.)
Additionally, this is never going to work:
UndoStack undoStack;
private UndoStack() {
undoStack = new UndoStack();
}
That means that to create an UndoStack, you need to create another UndoStack... how do you expect that to happen? You'll currently get a stack overflow exception... why do you need the variable at all?