I have a class
public class Coordinates {
public int x,y,z;
public Coordinates (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
}
In another class' method I want to get access on the coordinates, but I have to do the same long code for each coordinate x,y and z. Is there a way to use variables for the parameters such as :
Coordinates coords0 = new Coordinates(1, 2, 3);
Coordinates coords1 = new Coordinates(4, 1, 3);
Coordinates coords2 = new Coordinates(5, 1, 3);
Coordinates coords3 = new Coordinates(1, 1, 3);
Coordinates coords4 = new Coordinates(1, 2, 0);
Set<Coordinates> set = new HashSet<Coordinates>();
set.add(coords0);
set.add(coords1);
set.add(coords2);
set.add(coords3);
set.add(coords4);
int sum = 0;
for (int i = 0; i < 3; i++) {
String param = "";
if(i == 0) param = "x";
if(i == 1) param = "y";
if(i == 2) param = "z";
Iterator<Coordinates> it = set.iterator();
while(it.hasNext()) {
Coordinates currentCoords = it.next();
sum += currentCoords.param;
}
}
This does not work obviously, but is there a way to achieve something similar to this ?
As far as I understand, the problem is that you must apply the same code to a collection of coordinates, and this same code must be done for all the x of the coordinates, then to all the y of the coordinates, then for all the z of the coordinates.
So you probably need a method looking like this:
private void complexCode(Collection<Coordinates> collection, ToIntFunction<Coordinates> axisAccessor) {
// ...
for (Coordinates c : collection) {
int axis = axisAccessor.applyAsInt(c);
//...
}
// ...
}
You would then call your function three times using
complexCode(collection, coordinates -> coordinates.x);
complexCode(collection, coordinates -> coordinates.y);
complexCode(collection, coordinates -> coordinates.z);
Your current attempt is pretty close, only you don't need a param variable, println (and based on a comment, eliminate the i value). Like,
Coordinates coords = new Coordinates(1, 2, 3);
System.out.println("Coordinate x is " + coords.x);
System.out.println("Coordinate y is " + coords.y);
System.out.println("Coordinate z is " + coords.z);
or format it a little differently, and override toString() in Coordinates. Oh, and fix the constructor.
public class Coordinates {
public int x, y, z;
public Coordinates(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
#Override
public String toString() {
return String.format("x=%d, y=%d, z=%d", x, y, z);
}
}
Then you could print it like
Coordinates coords = new Coordinates(1, 2, 3);
System.out.println("Coordinate " + coords);
What you want is a getter method. It is a good idea to create setter methods as well. Heres what they look like for x. You'll need to make similar methods for y and z.
public int getX(){
return x;
}
public void setX(int newX){
x = newX;
}
you create these in your Coordinates class then from your other class you can do
if(i == 0) param = coords.getX();
You can use reflection like this:
int paramInt = Coordinates.class.getField(param).getInt(coords);
System.out.println("Coordinate "+param+" is "+paramInt);
Don't.
Related
I'm trying to print the coordinates of a translated point. If the point is translated outside of the 10, -10 range on both the x and y axes, then the original point should be returned and not the translated one. So, for p1 (5,4), if I were to translate it by (7,8), it should return (5,4). I'm having trouble figuring out how exactly to tell Java to print the original point in this case. Do I need to include a Boolean of some sort? Here's what I have so far. (The code is written in German, but "verschiebe" means translate.) Any help would be greatly appreciated! Thanks y'all in advance :)
public class Punkt2 {
private int x;
private int y;
public void setX (int i) {
x = i;
}
public void setY (int i) {
y = i;
}
public void verschiebe(int deltaX, int deltaY){
x = x + deltaX;
y = y + deltaY;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public static void main (String[] args){
Punkt p1 = new Punkt();
p1.setX(5); p1.setY(4);
Punkt p2 = new Punkt();
p2.setX(2);p2.setY(1);
p1.verschiebe(7,8);
if (p1.getX() > 10 || p1.getY() > 10 || p1.getX() < -10 || p1.getY() < -10){
System.out.println(new Punkt());
}
else {
System.out.println(p1.getX() + "," + p1.getY());
}
p2.verschiebe(3, 2);
if (p2.getX() > 10 || p2.getY() > 10 || p2.getX() < -10 || p2.getY() < -10){
System.out.println(new Punkt());
}
else {
System.out.println(p2.getX() + "," + p2.getY());
}
}
}
If you mean that you don't want the point's x or y value to be over 10 or below -10, you can just simply not change the values in the verschiebe method.
Like this:
public void verschiebe(int deltaX, int deltaY){
if(x + deltaX <= 10 && x + deltaX >= -10){
x = x + deltaX;
}
if(y + deltaY <= 10 && y + deltaY >= -10){
y = y + deltaY;
}
}
Then the point's x and y value will stay the same if they are about to get greater than 10 or lesser than -10. So now in the main class you can just print the point you want to and your verschiebe method will take care that your x and y will always be between -10 and 10.
The usual way of doing this would be to check the bounds inside of the translate() method.
For example:
private boolean outOfBounds(point, bounds) {
return (abs(point) > bounds);
}
public void translate(int deltaX, int deltaY) {
int newX = x + deltaX;
int newY = y + deltaY;
if(outOfBounds(newX, 10) || outOfBounds(newY, 10)) {
return;
}
x = newX;
y = newY;
}
Have a Punkt object be responsible for translating points by returning a "translated" point. It can return self when the translation results in point that is out of bounds.
class Punkt {
private int x;
private int y;
public Punkt(int x, int y) {
this.x = x;
this.y = y;
}
public Punkt verschiebe(int dX, int dY) {
int newX = x+dX;
int newY = y+dY;
if (abs(newX) > 10 || abs(newY) > 10) {
return this;
}
return new Punkt(newX, newY);
}
public void print() {
System.out.println(x + "," + y);
}
}
Would also advise that you have Punk print itself, so your clients can look as:
public static void main (String[] args){
Punkt p1 = new Punkt(5, 4);
Punkt p2 = new Punkt(2, 1);
p1.verschiebe(7,8).print();
p2.verschiebe(3,2).print();
}
Better still, if the client actually needs to print translated points the above code can be further improved to:
public static void main (String[] args){
Punkt p1 = new Punkt(5, 4);
Punkt p2 = new Punkt(2, 1);
p1.printTranslated(7,8);
p2.printTranslated(3,2);
}
It's not hard to have Punkt comply to client's needs.
After searching a large amount of sites, including this one, every solution i have came across seems to not work, or only work on the first object in the list.
The Problem
Slick2Ds Rectangle class offers many different methods for collision, one being the intersects(Rectangle box); method that correctly detects collisions when using this class in conjunction with javas built in ArrayList class,to an extent. The problem I'm having is that only the first object in the list is being detected and correctly collided upon.
The following code handles collisions:
public void move(float x, float y) {
if (blocks.size() > 0) {
for (int i = 0; i < blocks.size(); i++) {
Rectangle r = blocks.get(i);
Rectangle p = new Rectangle(xx + x, yy + y, 32, 32);
if (!r.intersects(p)) {
xp = xx;
yp = yy;
xx += x;
yy += y;
break;
} else {
xx = xp;
yy = yp;
xx += 0;
yy += 0;
System.out.println("Collide" + new Date());
break;
}
}
}else{
xp = xx;
yp = yy;
xx += x;
yy += y;
}
}
Key: xx = Player x; yy = Player y; xp = Players Last x Position; yp = Players Last y Position; r = Current Rectangle in the iteration list; p = Pre-calculated next position of the player
This basic codes job is to add movement by simulating a rectangle that will be in the next position the player is. if it does not collide then the player wont collide and we can move, but if it does collide then we don't move the player as the next location is not open.
But the code has a flaw as at some point during the iteration only the first box works, the others do detect collides but does not stop the box.
Correct Collision; logged in the console to confirm
Incorrect Collision; not logged in the console, even though its another instance of the same object
What happens if you use :
public void move(float x, float y) {
boolean intersectedBlock = false;
for (int i = 0; i < blocks.size(); i++) {
Rectangle r = blocks.get(i);
Rectangle p = new Rectangle(xx + x, yy + y, 32, 32);
if (r.intersects(p)) {
intersectedBlock = true;
break;
}
}
if (intersectedBlock) {
xx = xp;
yy = yp;
xx += 0;
yy += 0;
System.out.println("Collide" + new Date());
} else {
xp = xx;
yp = yy;
xx += x;
yy += y;
}
}
try to remove all the breaks.
because if it find the intersects or not, it will break out of the loop.
I have these two pieces of code:
int prevY = 0;
// this is the function InsertionSort applied to i
StdDraw.setPenColor(Color.blue);
for (int i = 1; i <= N; i++) {
int x = i;
int y = runInsertion(i);
int prevX = i - 1;
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
prevY = y;
}
prevY = 0;
// this is the function SelectionSort applied to i
StdDraw.setPenColor(Color.black);
for (int i = 1; i <= N; i++) {
int x = i;
int y = runSelection(i);
int prevX = i - 1;
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
prevY = y;
}
They both do the same thing except for a minor change in the color that will be used and in the sorting algorithm that will be used.
Is there any way to make an array for the colors and the sorting algorithms like:
String[] algorithms = {"runInsertion", "runSelection"}
String[] colors = {"blue", "black"};
And then with a for loop call the appropriate index so that the code has been shortened.
I know this will not work as I proposed it, but I just want to know if there is a way or a specific method that lets me do this.
Just extract your logic into method with required parameters:
void work(Color color, Function<Integer, Integer> algorithm) {
int prevY = 0;
StdDraw.setPenColor(color);
for (int i = 1; i <= N; i++) {
int x = i;
int y = algorithm.apply(i);
int prevX = i - 1;
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
prevY = y;
}
}
and call it:
work(Color.blue, this::runInsertion);
work(Color.black, this::runSelection);
or for arrays:
List<Function<Integer, Integer>> algorithms = Arrays.asList(this::runInsertion, this::runSelection);
List<Color> colors = Arrays.asList(Color.blue, Color.black);
for (int i = 0; i < algorithms.size(); i++) {
work(colors.get(i), algorithms.get(i));
}
The 'Design pattern' approach to this problem is called the Template method. It involves creating an abstract class for your algorithm, which would define and implement, for example, methods step1() and step3(), and an abstract method step2() to be implemented in different ways by different implementations of the algorithm. However, that seems like overkill for your purposes. It might be simplest just to reduce some of your duplication by using, say, a draw(x, y) method to contain the lines:
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
You can simply make a method which you can call with parameters to invoke the options that you want. In java 8 you can even refer to the different algorithms (runInsertion(i) and runSelection(i)) as method references which work as lambdas.
public void sortWithAlgorithm(Color color, Function<Integer, Integer> algorithm) {
int prevY = 0;
StdDraw.setPenColor(color);
for (int i = 1; i <= N; i++) {
int x = i;
int y = algorithm.apply(i);
int prevX = i - 1;
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
prevY = y;
}
}
And then to invoke the two, you can make a couple convenience methods:
void sortInsertion (){
sortWithAlgorithm(Color.Blue, this::runInsertion);
}
void sortSelection() {
sortWithAlgorithm(Color.Black, this::runSelection);
}
Yes, one possible way is using a Function object (unfortunately, it is not as easy as inputing the method variable name since methods are not first class objects as they are in a language like Javascript).
A Function class in Java looks like this:
public class Function<T,V> { // T is a generic for your input type
abstract V apply(T input); // V is a generic for your output type
}
Then it is as easy as extracting your code into a method where you input a color string and the corresponding Function object (Sounds like a good job for a Map!) The only caveat with the following implementation is that I'm not exactly sure how runSelection and runInsertion are implemented, but I'm going off the idea that they take in an int and output an int.
// Make the map somewhere earlier in the code
Map<String, Function<Integer, Integer> map = new HashMap();
map.put("blue", new Function<Integer, Integer>(){
Integer apply(Integer input) {
return runInsertion(input);
}
}
map.put("black", new Function<Integer, Integer>(){
Integer apply(Integer input) {
return runSelection(input);
}
}
for (Entry<String, Function<Integer, Integer>> entry : map.entrySet()) {
doExtractedMethod(entry.getKey(), entry.getValue());
}
...
public void doExtractedMethod(String color, Function<Integer, Integer> function) {
int prevY = 0;
// this is the function InsertionSort applied to i
StdDraw.setPenColor(color); // COLOR USED HERE
for (int i = 1; i <= N; i++) {
int x = i;
int y = function.apply(i); // FUNCTION USED HERE
int prevX = i - 1;
StdDraw.setPenRadius(lineRadius);
StdDraw.line(prevX, prevY, x, y);
StdDraw.setPenRadius(pointRadius);
StdDraw.point(x, y);
prevY = y;
}
}
I have a method which takes in 4 floats and modifies the value. Now I would like to set the floats of the parent class to the value that the method took in. Some code:
public void influence(float x, float y, float w, float h){
x += 5; y += 5; w += 5; h += 5;
}
Now that would be called from the parent class like this:
float x = 5, y = 5, w = 5, h = 5;
influence(x, y, w, h);
I would like to set the floats in the parent to the modified method. I know I could return a float[] and then manually set the floats of the parent class to that array but is there a better way to do this? I could also use a class like Rect but that would be like an array.
Java does not have a way to pass a reference to a primitive. However, in your situation it would probably be better to avoid it anyway: it appears that the four variables are related to each other.
When several variables are related, they should be instance variables of a single object. Your object probably looks like a rectangular box that has the origin of (x, y), height h, and width w. Make a class for it, and let the method change that class, or return a new instance:
class Rect {
private final float x, y, w, h;
public float getX() { return x; }
public float getY() { return y; }
public float getW() { return w; }
public float getH() { return h; }
public Rect(float x, float y, float w, float h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
Then you can write a method returning a new Rect
public Rect influence(Rect inputRect) {
...
}
or make Rect mutable, and let influence modify its values.
You can't change primitives in Java like that because everything in Jave is passed by value - but you can store the value in an array and pass it:
public void influence(float[] arr){
for (int i=0; i<arr.length; i++){
arr[i] += 5;
}
}
public class Vector {
private int x, y, z;
public Vector(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public void add(Vector v) {
x += v.x;
y += v.y;
z += v.z;
}
public void silly(int x, int y, int z) {
this.x = ++x;
this.y = y + 1;
this.z += z;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
#Override
public String toString() {
return "Vector, <x = " + x + ", y = " + y + ", z = " + z + ">";
}
public static void main(String[] args) {
Vector a = new Vector(1, 0, 0);
Vector b = new Vector(0, 1, 0);
Vector c = a;
int x = 1;
int y = 2;
int z = 3;
a.add(b);
b.add(b);
c.add(c);
c.silly(x, y, z);
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("c: " + c);
System.out.println("x: " + x + "\ty: " + y + "\tz: " + z);
}
}
I have obviously been unclear in my question, sorry about that. I got this as practice from my teacher and I am supposed to explain the output of the last 4 lines in the code. I have no idea why the output looks as it does. I'm not very good at alias and so on. Someone might be able to give me an explanation? Thanks.
Vector c = a;
means that you create reference which is linked to reference a and its object. You don't call a constructor there. You don't create any object there. Just new reference
The only question I can see is 'What is the relation between Vectors a and c?' So I'll answer that.
When you use the 'new' keyword you are creating a new object which is stored in the heap. So 'a' and 'b' are two separate objects when they have been instantiated. When you say:
Vector c = a;
You are not creating a new object in the heap, merely making a new reference to the same object. So now both 'a' and 'c' are referencing the same thing. If you change a, c will change, and vice versa.
When:
c.add(c);
Is called then the ints in c are simply being added to themselves.