Call method on multidimensional array - java

Let's say I have a method like so:
public class ColoredPoint {
private final Color color;
private final int x;
private final int y;
public ColoredPoint(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public ColoredPoint(int x, int y, int color) {
this(x,y, new Color(color));
}
public int getX() {
return x;
}
}
Then I populate a single dimension array with some data like so for example:
public class DemoInput {
final static ColoredPoint[] test2 = new ColoredPoint[]
{ new ColoredPoint( 208, 324, -1 )
, new ColoredPoint( 154, 313, -1 )
, new ColoredPoint( 288, 316, -1 )
, new ColoredPoint( 312, 296, -1 )
}
How can I figure out the biggest x in the array? I have a method to get x from the ColoredPoint so this should be easy, right?
I know I can use a for-loop for this. I just don't now to to get the x from the ColoredPoint inside the array.
I want the x value of a ColoredPoint in the array called test2 in the class DemoInput so I thought:
DemoInput.test2.ColoredPoint.getX[i]
would do the trick but that doesn't work.
Can anyone help me out? Also, how would it work for a multidimensional array, like such:
allTests = new ColoredPoint[][]
{ test1
, test2
};

You need to first get a ColoredPoint element from the array (using the [] operator), and then call the getX() method on it:
x = DemoInput.test2[i].getX()
// Here -----------^
The same logic applies for a 2D array - using the [] operator will return a 1D array, on which you'll need to use the [] operator in order to get a ColoredPoint element:
x = DemoInput.allTests[i][j].getX()
// Here --------------^

Java streams are pretty useful for finding things like largest and smallest:
Arrays.stream(test2).mapToInt(ColoredPoint::getX).max();
Multi-dimensional is slightly less elegant:
Arrays.stream(allTests).map(Arrays::stream)
.flatMapToInt(test -> test.mapToInt(ColoredPoint::getX)).max();

This is a possible implementation
public class ColoredPoint implements Comparable<ColoredPoint> {
private final Color color;
private final int x;
private final int y;
public ColoredPoint(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public ColoredPoint(int x, int y, int color) {
this(x, y, new Color(color));
}
public int getX() {
return x;
}
#Override
public int compareTo(ColoredPoint o) {
return Integer.compare(this.x, o.x);
}
public static void main(String[] args) {
ColoredPoint[] test2 = new ColoredPoint[]{new ColoredPoint(208, 324, -1)
, new ColoredPoint(154, 313, -1)
, new ColoredPoint(288, 316, -1)
, new ColoredPoint(312, 296, -1)
};
Optional<ColoredPoint> maxColor = Arrays.stream(test2).max(ColoredPoint::compareTo);
maxColor.ifPresent(coloredPoint -> System.out.println("Max X = " + coloredPoint.getX()));
}
}
This is a Java 8 compatible solution.
Hope this helps!

Related

pass array to a class as an argument

I am trying to pass an array to another class as an argument but keep getting the error
"error: incompatible types: Point cannot be converted to int[]"
the first portion of my code is:
public Circle(int n, int x, int y)
{
radius = n;
counter++;
center[0] = x;
center[1] = y;
Point center = new Point(center);
}
Point is the class that needs to have the array passed to it.
the second portion of code:
public class Point
{
private int xCord;
private int yCord;
public Point (int [] center)
{
xCord = center[0];
yCord = center[1];
This is unclear to me, however it should clearly cause an error in the circle class constructor.
center[0] = x; // center is an int array
center[1] = y;
Point center = new Point(center); // ?????
// ^^^ ^^^^ Duplicate variable names
Fix this by changing the name of the new Point variable.
Point center = new Point(center);
Duplicate variable
Change to
Point point = new Point(center);
You have to consider Object here. The variable name here is duplicate. As the center objects hold the array reference you cannot keep the same variable to hold the point object.
You can modify your code accordingly. Attached you sample code
public class Test {
public static void main(String[] args) {
Circle(1,2,3);
}
static void Circle(int n, int x, int y)
{ int center[] = new int[2];
//Do your operation and initialize the array
center[0] = 25;
center[1] = 26;
Point pointObject = new Point(center);
}
}
class Point
{
private int xCord;
private int yCord;
public Point (int [] center)
{
xCord = center[0];
yCord = center[1];
}
}

Overloaded method resolution at runtime and how type promotion works?

package arunjava;
public class sample3 {
public static void main(String[] args) {
Box25 b1 = new Box25();
Box25 b2 = new Box25();
b1.Dimension(25, 32, 65);
b2.Dimension(25, 45, 62);
System.out.println("volume is" + b1.volume());
System.out.println("volume is" + b2.volume());
b1.Dimension(4, 6, 8);
b2.Dimension(6, 8, 4);
System.out.println("volume is" + b1.vol());
System.out.println("volume is" + b2.vol());
}
}
class Box25 {
double height, width, depth;
int height1, width1, depth1;
public void Dimension(double height, double width, double depth) {
this.height = height;
this.width = width;
this.depth = depth;
}
public void Dimension(int height1, int width1, int depth1) {
this.height1 = height1;
this.width1 = width1;
this.depth1 = depth1;
}
double volume() {
return height * depth * width;
}
int vol() {
return height1 * depth1 * width1;
}
}
I had created the above program in my Java tutorial. The problem is that I am not able to compute the volume of the box which has the double datatype.
The programme result shows the following:
volume is0.0
volume is0.0
volume is192
volume is192
Secondly, I am confused about the Java concept of method overloading, as I know that in method overloading we can use the same method name with different parameters but as I created the volume method, I had to modify the name of the methods(volume,vol), so as to overload the volume method and get the answer. Why is it like that?
Following lines invokes
b1.Dimension(25, 32, 65);
b1.Dimension(4, 6, 8);
invokes method public void Dimension(int height1, int width1, int depth1) because the literal's 25, 32 and 65 are treated of type int
So, the fields height, width, depth of class Box25 have default values 0.0 hence the output you get is 0.
There are various ways you can fix the problem, by invoking appropriate method
Approach 1:
b1.Dimension((double)25, (double)32, (double)65);
b1.Dimension((double)4, (double)6, (double)8);
Approach 2:
double h = 25, w = 32, d = 65;
b1.Dimension(25, 32, 65);
Approach 3:
b1.Dimension(25.0, 32.0, 65.0);
b1.Dimension(4.0, 6.0, 8.0);
Why are the int arguments passed, not promoted to double?
At runtime, the resolution first happens by exact match of argument types
If the matching types are found, then the method with exact matched arguments is invoked
If there no exact match of arguments, then the types are promoted to next higher type and if there is a match, then that method is invoked.
Example 1:
public class OverloadingDemo {
public static void main(String args[]) {
OverloadingDemo obj = new OverloadingDemo();
obj.sayHello(10);
}
public void sayHello(double x) {
System.out.println("Hello double " + x);
}
}
Output: Hello double 10.0
Reason: Since there is no matching method for value 10 (which is of type int), it is promoted to long. As there is no matching method which accepts long argument, it is promoted to double. Now that there is a method with accepts double argument, it is invoked.
Example 2:
public class OverloadingDemo {
public static void main(String args[]) {
OverloadingDemo obj = new OverloadingDemo();
obj.sayHello(10);
}
public void sayHello(int x) {
System.out.println("Hello int " + x);
}
public void sayHello(double x) {
System.out.println("Hello double " + x);
}
}
Output: Hello int 10
Reason: Since there is a matching method for value 10 (which is of type int), it is invoked.
Example 3:
public class OverloadingDemo {
public static void main(String args[]) {
OverloadingDemo obj = new OverloadingDemo();
obj.sayHello(10);
}
public void sayHello(long x) {
System.out.println("Hello long " + x);
}
public void sayHello(double x) {
System.out.println("Hello double " + x);
}
}
Output: Hello long 10
Reason: Since there is no matching method for value 10 (which is of type int), it is promoted to long. Now that there is a method with accepts long argument, it is invoked.
I think having two sets of attributes is wrong. Here's how I'd write it.
public class Box {
private final double l, h, w;
public Box(double length, double height, double width) {
this.l = length;
this.h = height;
this.w = width;
}
public double getVolume() { return this.l*this.h*this.w; }
}
As written, there's nothing to stop you from entering negative or zero dimensions. Does that make sense? What should you do to guarantee sensible values?
If you insist on keeping your class, here's how you can fix the problem:
class Box25
{
double height,width,depth;
int height1,width1,depth1;
public void Dimension(double height, double width, double depth)
{
this.height=height;
this.width=width;
this.depth=depth;
this.height1 = (int) height;
this.width1 = (int) width;
this.depth1= (int) depth;
}
public void Dimension(int height1, int width1, int depth1)
{
this.height1=height1;
this.width1=width1;
this.depth1=depth1;
this.height = height1;
this.width = width1;
this.depth = depth1;
}
double volume()
{
return height*depth*width;
}
int vol()
{
return height1*depth1*width1;
}
}
You needed to set all variables.
Now both methods will return what you want. I'd still argue that your way is unnecessary.
specify that it is double value like this:
public static void main(String[] args)
{
Box25 b1=new Box25();
Box25 b2=new Box25();
b1.Dimension(25d, 32d, 65d);
b2.Dimension(25d, 45d, 62d);
...
...
}
Output
volume is52000.0
volume is69750.0
volume is192
volume is192

declare 2d variable Java

I am wondering whether it is possible to assign a value to a variable that would point to some exact position in the 2d Array in Java.
I am accessing array element through
imageMatrix[width][hight].getColor1()
and since I am considering different scenarios, it would be easier to declare [width][high] by eg. n1=[2][1] and then call
imageMatrix(n1).getColor1()
Is it somehow possible? Thanks!
You can define a class Coordinate that contains the width and height of a cell of your 2d array. Then use an instance of this class to your imageMatrix() method.
Something like:
public clas Coordinate{
private int height;
private int width;
/*Accessors and constructors...*/
}
You can define ImageMatrix and Point as class.
For setting and getting color of each point you can create method inside Point class.
Here we are storing each point in a list so that we can access them in future.
import java.util.ArrayList;
public class ImageMatrix {
Point point;
public ImageMatrix(Point point){
this.point = point;
}
public static void main(String[] args) {
//to set color and store each point into a list
ArrayList<Point> pointList = new ArrayList<>();
//creating 9 points with different color
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
Point point = new Point(i,j);
point.setColor("color"+i+j);
pointList.add(point);
}
}
//to get color from each point
for(Point point : pointList){
System.out.println("color of point " + point.height +" and " + point.width +" is : " + point.getColor());
}
}
}
class Point{
public int height;
public int width;
public String color;
public Point(int height, int width){
this.height = height;
this.width = width;
}
public void setColor(String color){
this.color = color;
}
public String getColor(){
return this.color;
}
}

Why is Color.colorToHSV and HSVToColor inaccurate?

I am writing an Android game. In the game, different colored blocks will fall to the ground. When two blocks with the same color are on top of each other, they will merge into one block that is in a darker color. However, I observed that the blocks with the same color do not merge sometimes. After some debugging, I found that they are actually in slightly different colors: -16757700 and -16757444. I used Color.colorToHSV and Color.HSVToColor to make the color darker as you can see in my code below (The checkLanded method). So I think there must be something wrong with those two hsv methods. Here is my code (Actually I don't think there is anything else wrong with the code, you can just look at the checkLanded method. But I pasted the other code because the problem might not be where I think it is. Just almost scroll to the bottom and you will see the checkLanded method):
package com.shades;
import android.graphics.Color;
import android.support.annotation.IntDef;
import com.shades.util.BlockView;
import com.shades.util.Timer;
import java.util.HashMap;
import java.util.Random;
public class Block {
private static Random r = new Random ();
private static HashMap<Integer, Float> colorValuesMap;
#IntDef ({LEFT, RIGHT})
public #interface Direction {}
public static final int LEFT = -1;
public static final int RIGHT = 1;
static {
colorValuesMap = new HashMap<> ();
colorValuesMap.put (4, 0.1F);
colorValuesMap.put (3, 0.3F);
colorValuesMap.put (2, 0.5F);
colorValuesMap.put (1, 0.7F);
colorValuesMap.put (0, 0.9F);
}
private int x;
private int y;
private int color;
protected Timer timer;
public int getX() {
return x;
}
public int getY() {
return y;
}
private void setY(int y) {
Block[][] matrix = Game.getInstance ().getBlockMatrix ();
matrix[this.x][this.y] = null;
this.y = y;
matrix[this.x][this.y] = this;
BlockView.updateViews ();
}
private void setX(int x) {
Block[][] matrix = Game.getInstance ().getBlockMatrix ();
matrix[this.x][this.y] = null;
this.x = x;
matrix[this.x][this.y] = this;
BlockView.updateViews ();
}
private void setXY (int x, int y) {
Block[][] matrix = Game.getInstance ().getBlockMatrix ();
matrix[this.x][this.y] = null;
this.y = y;
this.x = x;
matrix[x][y] = this;
BlockView.updateViews ();
}
public int getColor () {
return color;
}
public Block(int x, int y) {
setXY (x, y);
this.y = y;
float[] hsv = new float[3];
hsv[0] = Game.getInstance ().getHueNumber ();
hsv[1] = 1F;
hsv[2] = colorValuesMap.get (r.nextInt (4));
color = Color.HSVToColor (hsv);
BlockView.updateViews ();
timer = new Timer (new Runnable () {
#Override
public void run() {
moveDown ();
}
}, 1000, true);
}
private void moveDown () {
//if reached bottom
if (getY () == Game.MATRIX_HEIGHT - 1) {
timer.stopTimer ();
Game.getInstance ().nextBlock (r);
return;
}
color = Game.getInstance ().getBlockViewMatrix ()[x][y].getColor ();
Block[][] matrix = Game.getInstance ().getBlockMatrix ();
if (checkLanded (matrix[x][y + 1])) {
Game.getInstance ().nextBlock(r);
return;
}
setY (getY () + 1);
}
private boolean checkLanded(Block blockBelow) {
//if it can merge into another block
float[] currentHSV = new float[3];
Color.colorToHSV (color, currentHSV);//here is the possible inaccurate method
if (blockBelow != null &&
blockBelow.getColor () == color &&
currentHSV[2] != colorValuesMap.get (4)) {
Color.colorToHSV (blockBelow.getColor (), currentHSV);
currentHSV[2] -= 0.2F;
blockBelow.color = Color.HSVToColor (currentHSV); //here is the possible inaccurate method
selfDestroy ();
timer.stopTimer ();
//if the block below is not the block at the bottom
if (blockBelow.getY () != Game.MATRIX_HEIGHT - 1) {
blockBelow.checkLanded (Game.getInstance ().
getBlockMatrix ()[blockBelow.getX ()][blockBelow.getY () + 1]);
}
return true;
}
//if a block is touched
if (blockBelow != null &&
blockBelow.getColor () != color) {
timer.stopTimer ();
return true;
}
return false;
}
private void selfDestroy () {
Game.getInstance ().getBlockMatrix ()[x][y] = null;
BlockView.updateViews ();
}
private boolean checkPositionValid (int x, int y) {
return !(x < 0 || x >= Game.MATRIX_WIDTH ||
y < 0 || y >= Game.MATRIX_HEIGHT)
&& Game.getInstance ().getBlockMatrix ()[x][y] == null;
}
public void moveHorizontally (#Direction int direction) {
if (checkPositionValid (x + direction, y)) {
setX (x + direction);
}
}
}
Can anyone tell me whether Color.colorToHSV and Color.HSVToColor are inaccurate or where else did I do wrong?
Just to let you know, Game.getInstance().getHueNumber() returns 167 if that helps
I would probably create a custom color class for this, where I would keep the accurate color information and only converted to another format if needed for the output. The conversion woudn't matter in this case because the converted values wouldn't be used for comparisons.
Something similar to this should solve your problem:
class CustomColor {
private static final Random RANDOM = new Random();
private static final int DARKNESS_LEVEL_COUNT = 5;
private static final float[] DARKNESS_LEVELS = new float[] {0.9f, 0.7f, 0.5f, 0.3f, 0.1f};
private static final float SATURATION = 1f;
private float hue;
private int darknessLevel;
public CustomColor(float hue) {
this.hue = hue;
darknessLevel = RANDOM.nextInt(DARKNESS_LEVEL_COUNT - 1); // I'm guessing you don't create the darkest blocks
}
public int getColor() {
float[] hsv = new float[] {hue, SATURATION, DARKNESS_LEVELS[darknessLevel]};
return Color.HSVToColor(hsv);
}
public boolean equals(CustomColor other) {
return (hue == other.hue) && (darknessLevel == other.darknessLevel);
}
public boolean darken() {
darknessLevel++;
return darknessLevel == DARKNESS_LEVEL_COUNT - 1; // are we at max darkness?
}
}
I don't know how you pick hues, but you could probably use a similar array approach as with darkness here.
After some time, I found a solution for this. From #Cinnam 's comments, I know that HSV colors use floats and they are inaccurate. RGB is is not a good idea for me because I cannot easily know the hue.
According to Code Complete 2nd Edition by Steve McConnell, Section 12.3:
... One Effective approach is to determine whether the values are close enough. Typically, you'd write a equals() function that returns true if the values are close enough and false otherwise.
And I think that the two slightly different colors are "approximately equal" so I wrote a method like this:
private boolean intColorEquals(int color1, int color2) {
final int MAXIMUM_ERROR = 1000;
return Math.abs (color1 - color2) < MAXIMUM_ERROR;
}
private boolean floatEquals (float a, float b) {
final float MAXIMUM_ERROR = 0.05F;
return Math.abs (a - b) < MAXIMUM_ERROR;
}
And I replaced all the comparisons between colors and that between floats.
I really don't know whether an answer to my own question should be in a style like this. So if I did anything wrong, please tell me.

Array of random numbers as Object in java

I am new at java and want to ask you one question. So first what I have to do: My goal is to create different points in one area. I decided to create a class Koord for saving the coordinates of the points. I have used an array of 2 elements for this - for the x and y value. After that I added a random generator for x and y (they have to be random).
Here is my class:
import java.util.Random;
public class Koord {
private int number;
private static int numberOfNodes = 0;
public static int[] koord;
public Koord(int x, int y){
koord = new int[2];
koord[0] = x;
koord[1] = y;
number = ++numberOfNodes;
}
public int getNumber() {
return number;
}
public static int getNumberOfNodes() {
return numberOfNodes;
}
private static int randomFill(){
Random rand = new Random();
int randomNum = rand.nextInt(99);
return randomNum;
}
public int getX(){
return koord[0] = randomFill();
}
public int getY(){
return koord[1] = randomFill();
}
}
So, until now everything is OK. But now at my main class, I want to create some points and add them to a list. This is also not a problem. The problem starts when I want to print the coordinates of the points. As I am calling the methods getX() when I am printing the coordinates of the points in the list, I am getting different coordinates every time.
import java.util.LinkedList;
import java.util.ListIterator;
public class Display {
public static void main(String args[]) {
LinkedList<Koord> ownArea = new LinkedList<Koord>();
Koord point1 = new Koord(0, 0);
Koord point2 = new Koord(0, 0);
Koord point3 = new Koord(0, 0);
Koord point4 = new Koord(0, 0);
Koord point5 = new Koord(0, 0);
Koord point6 = new Koord(0, 0);
Koord point7 = new Koord(0, 0);
ownArea.add(point1);
ownArea.add(point2);
ownArea.add(point3);
ownArea.add(point4);
ownArea.add(point5);
ownArea.add(point6);
ownArea.add(point7);
System.out.println("ListIterator Approach: ");
ListIterator<Koord> listIterator = ownArea.listIterator();
while (listIterator.hasNext()) {
System.out.println(listIterator.next().getX());
}
System.out.println("ListIterator Approach: ");
ListIterator<Koord> listIterator2 = ownArea.listIterator();
while (listIterator2.hasNext()) {
System.out.println(listIterator2.next().getX());
}
}
}
So I know where the problem is, I know that this is wrong, but I don't know how to assign static coordinates to every point and how to print them. And I need this, because I want to operate with the coordinates (comparing them, printing them and so on). I know I have to learn a lot, but for now it will be very helpful, if you can give me some advice.
Since you are calling randomFill() every time you try to getX() or getY() It will be better to initialize every Koord object with the X and Y value already randomized.
Example:
Random rand = new Random();
LinkedList<Koord> ownArea = new LinkedList<Koord>();
Koord point1 = new Koord(rand.nextInt(99), rand.nextInt(99));
Koord point2 = new Koord(rand.nextInt(99), rand.nextInt(99));
ownArea.add(point1);
ownArea.add(point2);
for(Koord c : ownArea) {
System.out.println("x: " + c.getX() + " y: " + c.getY());
}
Also in your Koord class
The variable int[] koord should not be static and change
getX() and getY() to simply return the value.
In fact this would be a better approach
public class Koord {
private int number;
private static int numberOfNodes = 0;
private int x;
private int y;
public Koord(int x, int y) {
this.x = x;
this.y = y;
this.number = ++numberOfNodes;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getNumber() {
return number;
}
}
I think this is the problem
public int getX(){
return koord[0] = randomFill();
}
This makes the x random every time you call it!
Move all assignemts to the constructor, and make getX() work like an actual getter, ie. return x
I avoid posting code. You should figure it out yourself :)
You need to look at your getX() function. I have no idea why you're using randomFill() there, since it will continously return a random x value. If you want a random set of coordinates per point, but you only want them to be set once, I suggest calling randomFill() in the constructor.
public Koord() { // you don't need the x - y parameters if you're calling the random function anyways.
koord = new int[2];
koord[0] = randomFill();
koord[1] = randomFill();
number = ++numberOfNodes;
}
// you can now create points like so
Koord point1 = new Koord();
Koord point2 = new Koord();
Koord point3 = new Koord();
You'll also need to update your getX() (and getY()) :
public int getX() {
return koord[0];
}

Categories

Resources