I am attempting to use the slopeTo method inside my slopeCompare subclass in my comparator definition. However I get an error in eclipse telling me to change slopeTo to a static method. It also does not work when I use this.slopeTo(). I thought that the whole point of subclasses was that they can use all the methods of the superclass. Can someone help me clarify what I am not understanding here? I apologize if I am misusing terminology but comparators are a new topic and I am not entirely comfortable with them.
(this is from the princeton algorithms course on udacity)
import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;
public class Point implements Comparable<Point> {
private final int x; // x-coordinate of this point
private final int y; // y-coordinate of this point
/**
* Initializes a new point.
*
* #param x the <em>x</em>-coordinate of the point
* #param y the <em>y</em>-coordinate of the point
*/
public Point(int x, int y) {
/* DO NOT MODIFY */
this.x = x;
this.y = y;
}
/**
* Draws this point to standard draw.
*/
public void draw() {
/* DO NOT MODIFY */
StdDraw.point(x, y);
}
/**
* Draws the line segment between this point and the specified point
* to standard draw.
*
* #param that the other point
*/
public void drawTo(Point that) {
/* DO NOT MODIFY */
StdDraw.line(this.x, this.y, that.x, that.y);
}
/**
* Returns the slope between this point and the specified point.
* Formally, if the two points are (x0, y0) and (x1, y1), then the slope
* is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
* +0.0 if the line segment connecting the two points is horizontal;
* Double.POSITIVE_INFINITY if the line segment is vertical;
* and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
*
* #param that the other point
* #return the slope between this point and the specified point
*/
public double slopeTo(Point that) {
/* YOUR CODE HERE */
if (this.compareTo(that) == 0){
return Double.NEGATIVE_INFINITY;
}
double slope = (double)(that.y-this.y)/(that.x-this.x);
return slope;
}
/**
* Compares two points by y-coordinate, breaking ties by x-coordinate.
* Formally, the invoking point (x0, y0) is less than the argument point
* (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
*
* #param that the other point
* #return the value <tt>0</tt> if this point is equal to the argument
* point (x0 = x1 and y0 = y1);
* a negative integer if this point is less than the argument
* point; and a positive integer if this point is greater than the
* argument point
*/
public int compareTo(Point that) {
if (this.y > that.y){
return 1;
}
if (this.y < that.y){
return -1;
}
if ((this.y == that.y) && (this.x < that.x)){
return -1;
}
if ((this.y == that.y) && (this.x > that.x)){
return 1;
}
else {
return 0;
}
}
/**
* Compares two points by the slope they make with this point.
* The slope is defined as in the slopeTo() method.
*
* #return the Comparator that defines this ordering on points
*/
public Comparator<Point> slopeOrder() {
/* YOUR CODE HERE */
return new SlopeCompare();
}
private static class SlopeCompare implements Comparator<Point> {
public int compare(Point a, Point b){
if (slopeTo(a) < slopeTo(b)){
return -1;
}
return 0;
}
}
/**
* Returns a string representation of this point.
* This method is provide for debugging;
* your program should not rely on the format of the string representation.
*
* #return a string representation of this point
*/
public String toString() {
/* DO NOT MODIFY */
return "(" + x + ", " + y + ")";
}
/**
* Unit tests the Point data type.
*/
public static void main(String[] args) {
/* YOUR CODE HERE */
}
}
Sorry I can't comment yet.
But yes, you cannot call non static method inside static method.
Static belongs to class and non-static belongs to the instance you can look more into that in google.
If SlopeCompare should be static you need to have an instance of Point to call slopeTo.
this in this.slopeTo() represents SlopeCompare instance, inner class can indeed access fields and methods of outer class, but it's not inherit, so you can not access slopeTo() with this keywords, you can ues outer.this to get an instance of the outer class.
Two solutions for references:
1.define slopeTo() method with static:
public static double slopeTo(Point that) {
2.remove the static keywords from the member class:
private class SlopeCompare implements Comparator<Point> {
Related
I have a set of 3d points S.
I need to find the set X of all sets of points in S which are within manhattan distance d of each other.
i.e. for each set Y in X there exists atleast one point in 3d space that is within distance d of all points in Y
The length of set S will never be >20 but I will have to run this analysis on a stream of sets which are being produced at ~10 new sets per second, so whatever solution I use will have to be fairly efficient.
an example to help visualize the problem, given the following:
the output would be ((A,B), (B,C,E), (B,D,E))
we only care about the largest possible sets so the sets (B,C), (B,D), (B,E), (C,E) and (D,E), while within the given parameters, are not in the output given they are subsets of other sets in X
also this I'm doing this in java but any pointers in terms of algorithms or pseudo code would be greatly appreciated, thanks in advance.
A solution in pseudocode would be:
calculate_intersections(areas):
intersections = calculate every two intersecting areas
combinations = combine_intersections(intersections)
reduced = remove all sets in combinations that are included in bigger sets
combine_intersections(intersections):
do:
combinations = new HashSet
for s1 in intersections:
for s2 in intersections:
diff_1_2 = s1 \ s2
diff_2_1 = s2 \ s1
if diff_1_2.len == 1 && diff_2_1.len == 1:
union = diff_1_2 + diff_2_1
if union in intersections:
union2 = s1 + s2
if !union2 in intersections:
combinations.add(union)
while (combinations not empty)
An implementation in Java could look like this:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.collections4.SetUtils;
public class IntersectionSetCalculation {
private static class ManhattanDistanceArea {
private String id;
private Vector3D center;
private double distance;
public ManhattanDistanceArea(Vector3D center, double distance, String id) {
this.center = center;
this.distance = distance;
this.id = id;
}
#Override
public String toString() {
return id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((center == null) ? 0 : center.hashCode());
long temp;
temp = Double.doubleToLongBits(distance);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManhattanDistanceArea other = (ManhattanDistanceArea) obj;
if (center == null) {
if (other.center != null)
return false;
}
else if (!center.equals(other.center))
return false;
if (Double.doubleToLongBits(distance) != Double.doubleToLongBits(other.distance))
return false;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public boolean intersects(ManhattanDistanceArea other) {
double maxDist = distance + other.distance;
return center.distance(other.center, 1) < maxDist;
}
}
/**
* Calculate the intersection of all areas (maximum of 2 areas in an intersection)
*/
public static Set<Set<ManhattanDistanceArea>> getIntersectingAreas(Set<ManhattanDistanceArea> areas) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>();
for (ManhattanDistanceArea area : areas) {
for (ManhattanDistanceArea area2 : areas) {
if (!area.equals(area2) && area.intersects(area2)) {
HashSet<ManhattanDistanceArea> intersection = new HashSet<ManhattanDistanceArea>();
intersection.add(area);
intersection.add(area2);
intersections.add(intersection);
}
}
}
Set<Set<ManhattanDistanceArea>> combined = combineIntersections(intersections);
Set<Set<ManhattanDistanceArea>> reduced = reduceIntersections(combined);
return reduced;
}
/**
* Combine the small intersections (with a maximum of 2 areas in an intersection) to bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> combineIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Set<Set<ManhattanDistanceArea>> combinations;
do {
combinations = new HashSet<Set<ManhattanDistanceArea>>();
for (Set<ManhattanDistanceArea> intersecting1 : intersections) {
for (Set<ManhattanDistanceArea> intersecting2 : intersections) {
Set<ManhattanDistanceArea> diff_1_2 = SetUtils.difference(intersecting1, intersecting2);
Set<ManhattanDistanceArea> diff_2_1 = SetUtils.difference(intersecting2, intersecting1);
if (diff_1_2.size() == 1 && diff_2_1.size() == 1) {
Set<ManhattanDistanceArea> union_1_2 = SetUtils.union(diff_1_2, diff_2_1);
if (intersections.contains(union_1_2)) {
Set<ManhattanDistanceArea> union = SetUtils.union(intersecting1, intersecting2);
if (!intersections.contains(union)) {
combinations.add(union);
}
}
}
}
}
intersections.addAll(combinations);
} while (!combinations.isEmpty());
return intersections;
}
/**
* Remove the small intersections that are completely covered by bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> reduceIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Iterator<Set<ManhattanDistanceArea>> iter = intersections.iterator();
while (iter.hasNext()) {
Set<ManhattanDistanceArea> intersection = iter.next();
for (Set<ManhattanDistanceArea> intersection2 : inters) {
if (intersection2.size() > intersection.size() && intersection2.containsAll(intersection)) {
iter.remove();
break;
}
}
}
return intersections;
}
public static void main(String[] args) {
final double dist = 2d;//the manhattan distance d
ManhattanDistanceArea A = new ManhattanDistanceArea(new Vector3D(0, -3, 0), dist, "A");
ManhattanDistanceArea B = new ManhattanDistanceArea(new Vector3D(0, 0, 0), dist, "B");
ManhattanDistanceArea C = new ManhattanDistanceArea(new Vector3D(3.5, 0, 0), dist, "C");
ManhattanDistanceArea D = new ManhattanDistanceArea(new Vector3D(0, 3.5, 0), dist, "D");
ManhattanDistanceArea E = new ManhattanDistanceArea(new Vector3D(1, 1, 0), dist, "E");
ManhattanDistanceArea F = new ManhattanDistanceArea(new Vector3D(-1, 1, 0), dist, "F");
//test the example you provided
Set<ManhattanDistanceArea> abcde = new HashSet<ManhattanDistanceArea>();
abcde.addAll(Arrays.asList(new ManhattanDistanceArea[] {A, B, C, D, E}));
//test another example
Set<ManhattanDistanceArea> abcdef = new HashSet<ManhattanDistanceArea>();
abcdef.addAll(abcde);
abcdef.add(F);
Set<Set<ManhattanDistanceArea>> intersectionsABCDE = getIntersectingAreas(abcde);
Set<Set<ManhattanDistanceArea>> intersectionsABCDEF = getIntersectingAreas(abcdef);
System.out.println(intersectionsABCDE);
System.out.println(intersectionsABCDEF);
//test the runntime for 1000 calculation
double startTime = System.currentTimeMillis();
final int calculations = 1000;
for (int i = 0; i < calculations; i++) {
Set<ManhattanDistanceArea> areas = new HashSet<ManhattanDistanceArea>();
for (int j = 0; j < 20; j++) {
areas.add(new ManhattanDistanceArea(new Vector3D(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5), dist,
"A" + j));
}
getIntersectingAreas(areas);
}
System.out.println("\nTime used for " + calculations + " intersection calculations (with sets of size 20): "
+ (System.currentTimeMillis() - startTime) + "ms");
}
}
For the implementation I used this class Vector3D:
public class Vector3D {
public double x;
public double y;
public double z;
public static final Vector3D NAN_VEC = new Vector3D(Double.NaN, Double.NaN, Double.NaN);
public static final Vector3D NULL_VEC = new Vector3D(0, 0, 0);
public enum Axis {
X, Y, Z;
}
public Vector3D() {
}
/**
* Crate a new Vector2D with x and y components.
*/
public Vector3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3D(double... val) {
x = val[0];
y = val[1];
z = val[2];
}
/**
* Create a Vector3D by two angles (in degree).
*
* The first angle is in XY direction. The second angle is the Z direction.
*
* An angle (XY) of 0° results in (x, y) = (1, 0); 90° in (x, y) = (0, 1); ... An angle (Z) of 0° results in (x, y, z) = (x, y, 0); 90° in (x, y,
* z) = (x, y, 1); -90° in (x, y, z) = (x, y, -1)
*
* The resulting vector has a length of 1.
*
* #param angleXY
* The angle of the new vector (in degree) for the XY direction (from 0 to 360).
*
* #param angleZ
* The angle of the new vector (in degree) for the Z direction (from -90 to 90).
*/
public Vector3D(double angleXY, double angleZ) {
x = Math.cos(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
y = Math.sin(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
z = Math.sin(angleZ * Math.PI / 180);
double len = length();
x /= len;
y /= len;
z /= len;
}
private Vector3D(Vector3D clone) {
this.x = clone.x;
this.y = clone.y;
}
#Override
public Vector3D clone() {
return new Vector3D(this);
}
#Override
public String toString() {
return "Vector3D[x: " + x + " y: " + y + " z:" + z + "]";
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Vector3D) {
Vector3D v = (Vector3D) obj;
return Math.abs(x - v.x) < 1e-8 && Math.abs(y - v.y) < 1e-8 && Math.abs(z - v.z) < 1e-8;
}
return false;
}
/**
* Get this vector as 3D-Array.
*/
public double[] asArray() {
return new double[] {x, y, z};
}
/**
* The (euclidean) length of the Vector.
*/
public double length() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
}
/**
* The length of this vector in a given norm.
*
* #param norm
* The norm of the vector length.
*
* #return The length of this vector in the given norm.
*/
public double length(int norm) {
if (norm == Integer.MAX_VALUE) {
return Math.max(Math.max(x, y), z);
}
return Math.pow(Math.pow(x, norm) + Math.pow(y, norm) + Math.pow(z, norm), 1.0 / norm);
}
/**
* Rotate this vector an angle (in degrees) around an axis resulting in a new Vector that is returned.
*
* #param degrees
* The angle to return the vector.
*
* #param axis
* The axis around which the vector is rotated.
*
* #return The new created vector.
*/
public Vector3D rotate(double degrees, Axis axis) {
double cos = Math.cos(degrees * Math.PI / 180);
double sin = Math.sin(degrees * Math.PI / 180);
switch (axis) {
case X:
return new Vector3D(x, cos * y - sin * z, sin * y + cos * z);
case Y:
return new Vector3D(cos * x + sin * z, y, -sin * x + cos * z);
case Z:
return new Vector3D(cos * x - sin * y, sin * x + cos * y, z);
default:
return null;
}
}
/**
* Project the vector given as parameter on this vector.
*
* #param vec
* The vector that is to be projected on this vector.
*
* #return The projected vector.
*/
public Vector3D project(Vector3D vec) {
return mult(scalar(vec) / Math.pow(length(), 2));
}
/**
* Add another Vector3D to this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector added to this vector.
*
* #return The new created vector.
*/
public Vector3D add(Vector3D vec) {
return new Vector3D(x + vec.x, y + vec.y, z + vec.z);
}
/**
* Subtract another Vector3D from this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector subtracted from this vector.
*
* #return The new created vector.
*/
public Vector3D sub(Vector3D vec) {
return new Vector3D(x - vec.x, y - vec.y, z - vec.z);
}
/**
* Multiply this vector with a scalar resulting in a new Vector that is returned.
*
* #param scalar
* The scalar to multiply this vector with.
*
* #return The new created vector.
*/
public Vector3D mult(double scalar) {
return new Vector3D(x * scalar, y * scalar, z * scalar);
}
/**
* Check whether this vector is linearly dependent to the parameter vector.
*
* #param vec
* The checked vector.
*
* #return True if the vectors are linearly dependent. False otherwise.
*/
public boolean isLinearlyDependent(Vector3D vec) {
double t1 = (x == 0 ? 0 : vec.x / x);
double t2 = (y == 0 ? 0 : vec.y / y);
double t3 = (z == 0 ? 0 : vec.z / z);
return Math.abs(t1 - t2) < 1e-5 && Math.abs(t1 - t3) < 1e-5 && t1 != 0;//all parameters t are equal and != 0
}
/**
* Calculate the scalar product of this vector and the parameter vector.
*
* #param vec
* The vector to calculate the scalar with this vector.
*
* #return The scalar of the vectors.
*/
public double scalar(Vector3D vec) {
return this.x * vec.x + this.y * vec.y + this.z * vec.z;
}
/**
* Calculate the cross product of this vector with another vector (resulting vector = this X parameter vector)
*
* #param vec
* The second vector for the cross product calculation.
*
* #return The cross product vector of the two vectors.
*/
public Vector3D cross(Vector3D vec) {
return new Vector3D(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
}
/**
* Create a new vector with the same direction but a different length as this vector.
*
* #param length
* The length of the new vector.
*
* #return The new vector with a new length.
*/
public Vector3D setLength(double length) {
double len = length();
return new Vector3D(x * length / len, y * length / len, z * length / len);
}
/**
* Get the distance of this point's position vector to another point's position vector.
*
* #param p
* The second point's position vector.
*
* #return The distance between the points.
*/
public double distance(Vector3D p) {
return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y) + (this.z - p.z) * (this.z - p.z));
}
/**
* Get the distance of this point's position vector to another point's position vector in a given norm.
*
* #param p
* The second point's position vector.
*
* #param norm
* The norm in which the distance is calculated (1 -> manhattan, 2 -> euclide, ...)
*
* #return The distance between the points in the given norm.
*/
public double distance(Vector3D p, int norm) {
return Math.pow((Math.pow(Math.abs(this.x - p.x), norm) + Math.pow(Math.abs(this.y - p.y), norm) + Math.pow(Math.abs(this.z - p.z), norm)),
1d / norm);
}
/**
* Change this vector to the new coordinates.
*/
public void move(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Move a point's position vector in a direction (by a vector) and a distance.
*
* #param p
* The direction vector.
*
* #param distance
* The distance to move the new vector
*
* #return The new created vector.
*/
public Vector3D moveTo(Vector3D p, double distance) {
double d = distance(p);
double dx = p.x - x;
double dy = p.y - y;
double dz = p.z - z;
double coef = distance / d;
return new Vector3D(x + dx * coef, y + dy * coef, z + dz * coef);
}
/**
* Get the angle difference of this vector to another vector.
*
* #param vec
* The other vector.
*
* #return The angle difference of the two vectors (from 0° to 180°).
*/
public double getAngleTo(Vector3D vec) {
double angle = Math.acos(scalar(vec) / (length() * vec.length())) * 180 / Math.PI;
if (angle > 180) {
angle = 360 - angle;
}
return angle;
}
/**
* Get the vector from this point to another.
*
* #param vec
* The point to which the vector is calculated.
*
* #return The vector from this points position vector to the other point.
*/
public Vector3D vectorTo(Vector3D vec) {
return new Vector3D(vec.x - x, vec.y - y, vec.z - z);
}
/**
* Checks whether a point (by its position vector) is in a given range of this point.
*
* #param p
* The point that is checked.
*
* #param range
* The range used for the check.
*
* #return True if the point is in the range of this point (distance <= range).
*/
public boolean isInRange(Vector3D p, double range) {
return p != this && distance(p) <= range;
}
}
and the class SetUtils from the apache commons lib.
I also added some tests:
the test from your question
another test with a bigger intersection set
a test for the runtime
The results are:
[[A, B], [B, E, C], [B, E, D]]
[[A, B], [B, E, C], [D, E, F, B]]
Time used for 1000 intersection calculations (with sets of size 20):
791.0ms
So the results seem to be correct and you can calculate more than 1000 intersections in a second.
Exhaustive distance computation between 20 points, i.e. 190 distances is nothing for a PC. Time will measure in microseconds. You can draw the desired information from the "close to" relation encoded in a matrix.
I am working on a Java Lab for school. The purpose is to calculate the perimeter, area, and radius of circle r given a polygon with x # of sides and n length.
My Code:
public class RegularPolygon {
private int myNumSides; // # of sides
private double mySideLength; // length of side
private double myR; // radius of circumscribed circle
private double myr; //radius of inscribed circle
/**
* This is a default constructor creating a 3 sided polygon (triangle)
* This means that myNumSides should be initialized to 3
*/
public RegularPolygon() {
this.myNumSides = 3;
}
/**
* This is a parameter constructor with one int parameter and one double parameter
* #param numSides This is a parameter that sets the # of sides for object RegularPolygon
* #param sideLength This is a parameter for the length of each side in object RegularPolygon
*/
public RegularPolygon(int numSides, double sideLength) {
this.myNumSides = numSides;
this.mySideLength = sideLength;
}
/**
* Private Method to calculate the radius of the inscribed circle
* #return Nothing
*/
private void calcr() {
this.myr = 0.5 * this.getSideLength() * (1/(Math.tan(Math.PI / this.getNumside())));
}
/**
* Private Method to calculate the radius of the circumscribed circle
* #return Nothing
*/
private void calcR() {
this.myR = 1 / 2 * this.getSideLength() * (1 / (Math.sin(Math.PI / this.getNumside())));
}
/**
* This is a method that calculates the Vertex Angle. The Vertex Angle is assigned to to the variable q
* #return double Returns the double value of q, the vertex angle
*/
public double vertexAngle() {
double q = ((this.getNumside() - 2) / this.getNumside()) * Math.toRadians(180);
return q;
}
/**
* Method that calculates the perimeter of the polygon. The perimeter is assigned to the double variable perimeter
* #return double Returns the double value of the perimeter
*/
public double Perimeter() {
double perimeter = this.getSideLength() * this.getNumside();
return perimeter;
}
/**
* Method that calculates the area of the polygon RegularPolygon
* #return double Returns the double value of the area
*/
public double Area() {
double area = 1 / 2 * this.getNumside() * Math.pow(this.getR(), 2) * Math.sin(2 * Math.PI / this.getNumside());
return area;
}
/**
* Getter method that returns the value of myNumSides
* #return int Value of myNumSides
*/
public int getNumside() {
return myNumSides;
}
/**
* Getter Method that returns the value of mySideLength
* #return double Value of mySideLength
*/
public double getSideLength() {
return mySideLength;
}
/**
* Getter Method that returns the value myR
* #return double Value of circumscribed circle myR
*/
public double getR() {
return myR;
}
/**
* Getter Method that returns the value of inscribed circle myr
* #return double Value of inscribed circle myr
*/
public double getr() {
return myr;
}
}
Everything is correct except for the calcR and calcr methods. For some reason the value returned is always 0.0. Not sure if I am using the Math methods incorrectly or something.
Here is my testing code:
public class PolygonDriver {
public static void main(String[] args) {
RegularPolygon poly = new RegularPolygon(4, 10);
System.out.println(poly.Area());
System.out.println(poly.getR());
System.out.println(poly.Perimeter());
}
}
After running it, I get:
0.0
0.0
40.0
What is wrong with my methods calcR() and calcr()?
calcr() and calcR are not being called anywhere in your code so myr and myR are never being set so you are getting the initialized value of 0.0
Besides not calling calcr() and calcR(), you should change the 1/2 in Area() and the calcR() to 0.5 so that you are working with the correct data type.
My flood fill algorithm works, however, I cannot print the 6 main colors of my game. The Java function that allows me to print the 2-d array is in the class GameModel.java called toString():
import java.util.Random;
public class GameModel {
/**
* predefined values to capture the color of a DotInfo
*/
public static final int COLOR_0 = 0;
public static final int COLOR_1 = 1;
public static final int COLOR_2 = 2;
public static final int COLOR_3 = 3;
public static final int COLOR_4 = 4;
public static final int COLOR_5 = 5;
public static final int NUMBER_OF_COLORS = 6;
private static DotInfo[][] dots;
private int size;
private int currentColor;
private Random generator;
private int steps;
/**
* Constructor to initialize the model to a given size of board.
*
* #param size
* the size of the board
*/
public GameModel(int size) {
this.size = size;
dots = new DotInfo[size][size];
generator = new Random();
}
/**
* Resets the model to (re)start a game. The previous game (if there is one)
* is cleared up .
*/
public void reset(){
generator = new Random();
int color = 0;
for (int j=0;j<size;j++) {
for (int i=0;i<size;i++) {
dots[j][i] = new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
}
}
}
/**
* Getter method for the size of the game
*
* #return the value of the attribute sizeOfGame
*/
public int getSize(){
return size;
}
/**
* returns the current color of a given dot in the game
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public int getColor(int i, int j){
return dots[j][i].getColor();
}
/**
* returns true is the dot is captured, false otherwise
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public boolean isCaptured(int i, int j){
return dots[j][i].isCaptured();
}
/**
* Sets the status of the dot at coordinate (i,j) to captured
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*/
public void capture(int i, int j){
dots[j][i] = new DotInfo(i, j, currentColor);
dots[j][i].setCaptured(true);
}
/**
* Getter method for the current number of steps
*
* #return the current number of steps
*/
public int getNumberOfSteps(){
return steps;
}
/**
* Setter method for currentSelectedColor
*
* #param val
* the new value for currentSelectedColor
*/
public void setCurrentSelectedColor(int val) {
currentColor = val;
}
/**
* Getter method for currentSelectedColor
*
* #return currentSelectedColor
*/
public int getCurrentSelectedColor() {
return currentColor;
}
/**
* Getter method for the model's dotInfo reference
* at location (i,j)
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*
* #return model[i][j]
*/
public DotInfo get(int i, int j) {
return dots[j][i];
}
/**
* The metod <b>step</b> updates the number of steps. It must be called
* once the model has been updated after the payer selected a new color.
*/
public void step(){
steps++;
}
/**
* The metod <b>isFinished</b> returns true iff the game is finished, that
* is, all the dats are captured.
*
* #return true if the game is finished, false otherwise
*/
public boolean isFinished(){
boolean flag=true;
for (int y=0;y<size;y++) {
for (int x=0;x<size;x++) {
if (dots[y][x].isCaptured()==false) {
flag=false;
}
}
}
return flag;
}
/**
* Builds a String representation of the model
*
* #return String representation of the model
*/
public String toString(){
String rep = "";
for (int y=0;y<size;y++) {
for (int x=0;x<size;x++) {
rep += dots[y][x].getColor()+" ";
}
rep+="\n";
}
return rep;
}
}
The function where I am printing the array is in my GameController.java class with the call:
System.out.println(model)
.
import java.awt.*;
public class GameController /*implements ActionListener*/ {
private GameModel model;
private MyStack dots;
private int size;
/**
* Constructor used for initializing the controller. It creates the game's view
* and the game's model instances
*
* #param size
* the size of the board on which the game will be played
*/
public GameController(int size) {
this.size = size;
model = new GameModel(size);
dots = new MyStack(size*size);
}
/**
* resets the game
*/
public void reset(){
model.reset();
System.out.println(model);
}
/**
* Callback used when the user clicks a button (reset or quit)
*
* #param e
* the ActionEvent
*/
/*public void actionPerformed(ActionEvent e) {
}*/
/**
* <b>selectColor</b> is the method called when the user selects a new color.
* If that color is not the currently selected one, then it applies the logic
* of the game to capture possible locations. It then checks if the game
* is finished, and if so, congratulates the player, showing the number of
* moves, and gives two options: start a new game, or exit
* #param color
* the newly selected color
*/
public void selectColor(int color){
model.setCurrentSelectedColor(color);
capturePointAtZero();
sendCapturedToStack();
equalityCheck(color);
System.out.println(model);
}
private void capturePointAtZero() {
int x = 0, y = 0;
if (!model.isCaptured(x, y)) {
model.capture(x, y);
}
}
private void sendCapturedToStack() {
for (int j=0;j<size;j++) {
for (int i=0;i<size;i++) {
if (model.isCaptured(i, j)) {
model.capture(i,j);
dots.push(model.get(i,j));
}
}
}
}
private void equalityCheck(int newColor) {
while (!dots.isEmpty()) {
DotInfo dot = dots.pop();
int x = dot.getX();
int y = dot.getY();
if (model.getColor(x,y+1)==newColor && !model.isCaptured(x,y+1)) {
model.capture(x, y+1);
dots.push(model.get(x,y+1));
} if (model.getColor(x+1,y)==newColor && !model.isCaptured(x+1,y)) {
model.capture(x+1, y);
dots.push(model.get(x+1,y));
} if (model.getColor(x,y-1)==newColor && !model.isCaptured(x,y-1)) {
model.capture(x, y-1);
dots.push(model.get(x,y-1));
} if (model.getColor(x-1,y)==newColor && !model.isCaptured(x-1,y)) {
model.capture(x-1, y);
dots.push(model.get(x-1,y));
}
}
}
}
I am getting a IndexOutOfBoundsError when it approaches the end of the matrix.
If anyone could help that would be much appreciated.
There are too many issues with the code to fix all of them. Still here a few the I noticed after a quick look:
Yes, the reason why the matrix is filled with 0 is that currentColor is 0 becuase you don't call setCurrentSelectedColor
A deeper issue is with logic. Let's look at equalityCheck
if (model.getColor(x, y + 1) == newColor && !model.isCaptured(x, y + 1))
{
model.capture(x, y + 1);
dots.push(model.get(x, y + 1));
}
This code means that dot at (x, y+1) will be updated only if it already has the newColor. Obviously you want it to be updated if it matches the "old color" i.e. color of the (0,0) but you don't even try to save that color in your capturePointAtZero!
Code such as
public void capture(int i, int j){
for (int y=0;y<size;y++) {
for (int x=0;x<size;x++) {
if (x==i && y==j) {
dots[y][x] = new DotInfo(x, y, currentColor);
dots[y][x].setCaptured(true);
}
}
}
}
is rather inefficient. Why do you need loops if you still update only single DotInfo? It can be simplified
public void capture(int i, int j){
dots[j][i] = new DotInfo(i, j, currentColor);
dots[j][i].setCaptured(true);
}
Hope this helps.
Update
I understand your comments but now I am getting an arrayIndexOutOfBounds whenever i call a number that is at the end of my Matrix.
Exception most probably happens because you don't validate your indices in the equalityCheck. You can add a method isValidPosition such as:
public class GameModel
{
....
public boolean isValidPosition(int x, int y)
{
return (x >= 0) && (x < size) && (y >= 0) && (y < size);
}
}
and then
private void equalityCheck(int newColor)
{
...
if (model.isValidPosition(x, y+1) && model.getColor(x, y + 1) == newColor && !model.isCaptured(x, y + 1))
{
model.capture(x, y + 1);
dots.push(model.get(x, y + 1));
}
Note that it is important that isValidPosition is the first call in the compound if. This works because Java uses short-circuit evaluation for boolean statements.
You can hide isValidPosition inside your other methods in the GameModel and sometimes similar approach is the right thing to do. But I don't think this is the time because 1) it requires you to return some fake value from getColor (you now use 0 and I don't really like it) and 2) it hides from the reader the business-logic that the field is not unlimited.
I wrote a Rectangle class that has length and width for the fields. setLength, setWidth, getLength, getWidth, getPerimeter, and getArea for the methods. In my main program, RectangleTest; when I run it; I am able to enter in the length and width. The program then displays the value that I entered in for length (which is correct), but when it displays the value that I entered in for width; it always displays 0.0. Please help. Here is the source code:
package com.delgado;
import javax.swing.JOptionPane;
import java.text.DecimalFormat;
public class RectangleTest {
public static void main(String[] args) {
double length;
double width;
String input;
DecimalFormat formatter = new DecimalFormat("#0.0");
input = JOptionPane
.showInputDialog("Please enter the length of the basketball court: ");
length = Double.parseDouble(input);
input = JOptionPane
.showInputDialog("Please enter the width of the basketball court: ");
width = Double.parseDouble(input);
Rectangle basketBall = new Rectangle(length, width);
JOptionPane.showMessageDialog(
null,
"You entered " + formatter.format(basketBall.getLength())
+ " for the length, and "
+ formatter.format(basketBall.getWidth())
+ " for the width.");
}
}
If you need the source code for the Rectangle class, please let me know. Thank you guys.
Here is the source code for the Rectangle class:
package com.delgado;
/* This Class creates an object that takes the length and width as arguments,
* and returns the perimeter and area of a rectangle.
*/
public class Rectangle {
private double length; // Holds the length.
private double width; // Holds the width.
/**
* This is a default constructor
*/
public Rectangle() {
}
/**
* This is a constructor that takes two arguments; len and w.
*
* #param len
* The length of the rectangle.
* #param w
* The width of the rectangle.
*/
public Rectangle(double len, double w) {
length = len;
w = width;
}
/**
* The method setLength sets the length of a rectangle.
*
* #param len
* The length of a rectangle.
*/
public void setLength(double len) {
length = len;
}
/**
* The method setWidth sets the width of a rectangle.
*
* #param w
* The width of a rectangle.
*/
public void setWidth(double w) {
width = w;
}
/**
* The method getLength returns the length of a rectangle.
*
* #return Returns the length of a rectangle.
*/
public double getLength() {
return length;
}
/**
* The method getWidth returns the width of a rectangle.
*
* #return Returns the width of a rectangle.
*/
public double getWidth() {
return width;
}
/**
* The method getArea returns the area of a rectangle.
*
* #return Returns the area of a rectangle.
*/
public double getArea() {
return length * width;
}
/**
* The method getPerimeter returns the perimeter of a rectangle.
*
* #return Returns the perimeter of a rectangle.
*/
public double getPerimeter() {
return (length * 2) + (width * 2);
}
}
I have to wonder if your JOptionPane is messing with your Scanner... can't tell til I test it, but regardless, I would simplify things even further. As long as you're showing JOptionPanes, who not show one that displays a message and gets input at the same time?
JOptionPane.showInputDialog(....)
Edit: Yikes
public Rectangle(double len, double w) {
length = len;
w = width;
}
You're setting the w parameter here, not the width field!!! Instead it should be:
width = w; //*********
Do you understand why?
I been trying to figure out how to set up this equation to add two complex numbers for Java.
There's two methods, but I don't understand exactly what the first one is asking me to do. Is it saying I need to do (real1 + imag1) instead of (real1 + real2)? If that is the case then how would I get that result to go into c1? I also am having trouble with the second method result to hold the sum and return it.
/*Method for adding the real and imaginary parts of two complex numbers,
*which returns the result in a new complex number
*/
public static ComplexNumber addComplexNumbers(double real1, double imag1, double real2, double imag2){
ComplexNumber result = ComplexNumber.addComplexNumbers(real1, imag1, real2, imag2);
result.setReal(real1 + real2);
result.setImag(imag1 + imag2);
return result;
}
//Method for adding two complex numbers
public static ComplexNumber addComplexNumbers(ComplexNumber c1, ComplexNumber c2){
ComplexNumber result = new ComplexNumber();
result = (c1.real + c2.real) + (c1.imag + c2.imag);
}
final public class Complex {
private final double real;
private final double imag;
public Complex() {
this(0.0, 0.0);
}
public Complex(double r) {
this(r, 0.0);
}
public Complex(double r, double i) {
this.real = r;
this.imag = i;
}
public Complex add(Complex addend) {
return new Complex((this.real + addend.real), (this.imag + addend.imag));
}
}
Though this already been answered I thought people may benefit by the following class which does a lot of functions related to Complex Numbers.
This has been released under MIT License and the GitHub project is here.
/**
* <code>ComplexNumber</code> is a class which implements complex numbers in Java.
* It includes basic operations that can be performed on complex numbers such as,
* addition, subtraction, multiplication, conjugate, modulus and squaring.
* The data type for Complex Numbers.
* <br /><br />
* The features of this library include:<br />
* <ul>
* <li>Arithmetic Operations (addition, subtraction, multiplication, division)</li>
* <li>Complex Specific Operations - Conjugate, Inverse, Absolute/Magnitude, Argument/Phase</li>
* <li>Trigonometric Operations - sin, cos, tan, cot, sec, cosec</li>
* <li>Mathematical Functions - exp</li>
* <li>Complex Parsing of type x+yi</li>
* </ul>
*
* #author Abdul Fatir
* #version 1.1
*
*/
public class ComplexNumber
{
/**
* Used in <code>format(int)</code> to format the complex number as x+yi
*/
public static final int XY = 0;
/**
* Used in <code>format(int)</code> to format the complex number as R.cis(theta), where theta is arg(z)
*/
public static final int RCIS = 1;
/**
* The real, Re(z), part of the <code>ComplexNumber</code>.
*/
private double real;
/**
* The imaginary, Im(z), part of the <code>ComplexNumber</code>.
*/
private double imaginary;
/**
* Constructs a new <code>ComplexNumber</code> object with both real and imaginary parts 0 (z = 0 + 0i).
*/
public ComplexNumber()
{
real = 0.0;
imaginary = 0.0;
}
/**
* Constructs a new <code>ComplexNumber</code> object.
* #param real the real part, Re(z), of the complex number
* #param imaginary the imaginary part, Im(z), of the complex number
*/
public ComplexNumber(double real, double imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
/**
* Adds another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be added to the current complex number
*/
public void add(ComplexNumber z)
{
set(add(this,z));
}
/**
* Subtracts another <code>ComplexNumber</code> from the current complex number.
* #param z the complex number to be subtracted from the current complex number
*/
public void subtract(ComplexNumber z)
{
set(subtract(this,z));
}
/**
* Multiplies another <code>ComplexNumber</code> to the current complex number.
* #param z the complex number to be multiplied to the current complex number
*/
public void multiply(ComplexNumber z)
{
set(multiply(this,z));
}
/**
* Divides the current <code>ComplexNumber</code> by another <code>ComplexNumber</code>.
* #param z the divisor
*/
public void divide(ComplexNumber z)
{
set(divide(this,z));
}
/**
* Sets the value of current complex number to the passed complex number.
* #param z the complex number
*/
public void set(ComplexNumber z)
{
this.real = z.real;
this.imaginary = z.imaginary;
}
/**
* Adds two <code>ComplexNumber</code>.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 + z2).
*/
public static ComplexNumber add(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real + z2.real, z1.imaginary + z2.imaginary);
}
/**
* Subtracts one <code>ComplexNumber</code> from another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 - z2).
*/
public static ComplexNumber subtract(ComplexNumber z1, ComplexNumber z2)
{
return new ComplexNumber(z1.real - z2.real, z1.imaginary - z2.imaginary);
}
/**
* Multiplies one <code>ComplexNumber</code> to another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 * z2).
*/
public static ComplexNumber multiply(ComplexNumber z1, ComplexNumber z2)
{
double _real = z1.real*z2.real - z1.imaginary*z2.imaginary;
double _imaginary = z1.real*z2.imaginary + z1.imaginary*z2.real;
return new ComplexNumber(_real,_imaginary);
}
/**
* Divides one <code>ComplexNumber</code> by another.
* #param z1 the first <code>ComplexNumber</code>.
* #param z2 the second <code>ComplexNumber</code>.
* #return the resultant <code>ComplexNumber</code> (z1 / z2).
*/
public static ComplexNumber divide(ComplexNumber z1, ComplexNumber z2)
{
ComplexNumber output = multiply(z1,z2.conjugate());
double div = Math.pow(z2.mod(),2);
return new ComplexNumber(output.real/div,output.imaginary/div);
}
/**
* The complex conjugate of the current complex number.
* #return a <code>ComplexNumber</code> object which is the conjugate of the current complex number
*/
public ComplexNumber conjugate()
{
return new ComplexNumber(this.real,-this.imaginary);
}
/**
* The modulus, magnitude or the absolute value of current complex number.
* #return the magnitude or modulus of current complex number
*/
public double mod()
{
return Math.sqrt(Math.pow(this.real,2) + Math.pow(this.imaginary,2));
}
/**
* The square of the current complex number.
* #return a <code>ComplexNumber</code> which is the square of the current complex number.
*/
public ComplexNumber square()
{
double _real = this.real*this.real - this.imaginary*this.imaginary;
double _imaginary = 2*this.real*this.imaginary;
return new ComplexNumber(_real,_imaginary);
}
/**
* #return the complex number in x + yi format
*/
#Override
public String toString()
{
String re = this.real+"";
String im = "";
if(this.imaginary < 0)
im = this.imaginary+"i";
else
im = "+"+this.imaginary+"i";
return re+im;
}
/**
* Calculates the exponential of the <code>ComplexNumber</code>
* #param z The input complex number
* #return a <code>ComplexNumber</code> which is e^(input z)
*/
public static ComplexNumber exp(ComplexNumber z)
{
double a = z.real;
double b = z.imaginary;
double r = Math.exp(a);
a = r*Math.cos(b);
b = r*Math.sin(b);
return new ComplexNumber(a,b);
}
/**
* Calculates the <code>ComplexNumber</code> to the passed integer power.
* #param z The input complex number
* #param power The power.
* #return a <code>ComplexNumber</code> which is (z)^power
*/
public static ComplexNumber pow(ComplexNumber z, int power)
{
ComplexNumber output = new ComplexNumber(z.getRe(),z.getIm());
for(int i = 1; i < power; i++)
{
double _real = output.real*z.real - output.imaginary*z.imaginary;
double _imaginary = output.real*z.imaginary + output.imaginary*z.real;
output = new ComplexNumber(_real,_imaginary);
}
return output;
}
/**
* Calculates the sine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the sine of z.
*/
public static ComplexNumber sin(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.sin(z.real) * (x + x_inv)/2;
double i = Math.cos(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the cosine of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the cosine of z.
*/
public static ComplexNumber cos(ComplexNumber z)
{
double x = Math.exp(z.imaginary);
double x_inv = 1/x;
double r = Math.cos(z.real) * (x + x_inv)/2;
double i = -Math.sin(z.real) * (x - x_inv)/2;
return new ComplexNumber(r,i);
}
/**
* Calculates the tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the tangent of z.
*/
public static ComplexNumber tan(ComplexNumber z)
{
return divide(sin(z),cos(z));
}
/**
* Calculates the co-tangent of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-tangent of z.
*/
public static ComplexNumber cot(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),tan(z));
}
/**
* Calculates the secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the secant of z.
*/
public static ComplexNumber sec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),cos(z));
}
/**
* Calculates the co-secant of the <code>ComplexNumber</code>
* #param z the input complex number
* #return a <code>ComplexNumber</code> which is the co-secant of z.
*/
public static ComplexNumber cosec(ComplexNumber z)
{
return divide(new ComplexNumber(1,0),sin(z));
}
/**
* The real part of <code>ComplexNumber</code>
* #return the real part of the complex number
*/
public double getRe()
{
return this.real;
}
/**
* The imaginary part of <code>ComplexNumber</code>
* #return the imaginary part of the complex number
*/
public double getIm()
{
return this.imaginary;
}
/**
* The argument/phase of the current complex number.
* #return arg(z) - the argument of current complex number
*/
public double getArg()
{
return Math.atan2(imaginary,real);
}
/**
* Parses the <code>String</code> as a <code>ComplexNumber</code> of type x+yi.
* #param s the input complex number as string
* #return a <code>ComplexNumber</code> which is represented by the string.
*/
public static ComplexNumber parseComplex(String s)
{
s = s.replaceAll(" ","");
ComplexNumber parsed = null;
if(s.contains(String.valueOf("+")) || (s.contains(String.valueOf("-")) && s.lastIndexOf('-') > 0))
{
String re = "";
String im = "";
s = s.replaceAll("i","");
s = s.replaceAll("I","");
if(s.indexOf('+') > 0)
{
re = s.substring(0,s.indexOf('+'));
im = s.substring(s.indexOf('+')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),Double.parseDouble(im));
}
else if(s.lastIndexOf('-') > 0)
{
re = s.substring(0,s.lastIndexOf('-'));
im = s.substring(s.lastIndexOf('-')+1,s.length());
parsed = new ComplexNumber(Double.parseDouble(re),-Double.parseDouble(im));
}
}
else
{
// Pure imaginary number
if(s.endsWith("i") || s.endsWith("I"))
{
s = s.replaceAll("i","");
s = s.replaceAll("I","");
parsed = new ComplexNumber(0, Double.parseDouble(s));
}
// Pure real number
else
{
parsed = new ComplexNumber(Double.parseDouble(s),0);
}
}
return parsed;
}
/**
* Checks if the passed <code>ComplexNumber</code> is equal to the current.
* #param z the complex number to be checked
* #return true if they are equal, false otherwise
*/
#Override
public final boolean equals(Object z)
{
if (!(z instanceof ComplexNumber))
return false;
ComplexNumber a = (ComplexNumber) z;
return (real == a.real) && (imaginary == a.imaginary);
}
/**
* The inverse/reciprocal of the complex number.
* #return the reciprocal of current complex number.
*/
public ComplexNumber inverse()
{
return divide(new ComplexNumber(1,0),this);
}
/**
* Formats the Complex number as x+yi or r.cis(theta)
* #param format_id the format ID <code>ComplexNumber.XY</code> or <code>ComplexNumber.RCIS</code>.
* #return a string representation of the complex number
* #throws IllegalArgumentException if the format_id does not match.
*/
public String format(int format_id) throws IllegalArgumentException
{
String out = "";
if(format_id == XY)
out = toString();
else if(format_id == RCIS)
{
out = mod()+" cis("+getArg()+")";
}
else
{
throw new IllegalArgumentException("Unknown Complex Number format.");
}
return out;
}
}
Check out this simple program .
class Com{
int real,img;
Com (int r, int i){
real = r;
img = i;
}
void add(Com c){
real = real + c.real;
img = img + c.img;
}
void print(){
System.out.println(real+" +i"+img);
}
}
public class complex {
public static void main(String [] args){
Com c1 = new Com(10,20);
c1.print();
Com c2 = new Com(20,10);
c1.add(c2);
c1.print();
}
}