Problem Statement:
A fish has to move in a 2D Aquarium.
At no point two fishes can be at the same Location.
Challenges:
To generate a random direction in which every fish will move.
Fish should not go beyond the Aquarium specifications.
Maintaining a collection which contains the locations of all fishes in the aquarium.
Approach:
I used multi threading via Java so that all the fishes can move at the same time.
Used Enum's to extract direction for X & Y co-ordinates randomly.
Created a Fish Class which extends Location Class.
Please suggest if there could have been a different approach used for this question since I am an Intermediate Level Java Programmer.
Location Class
public class Location {
public int x;
public int y;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
Location other = (Location) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
public Location(int Size) {
setRandomLocation(Size);
synchronized (Aquarium.location_list) {
Aquarium.location_list.add(this);
}
}
public Location() {
}
public void setRandomLocation(int Size){
int location_exist_ind=0 ;
while(location_exist_ind==0){
this.x = (int)(Math.random() * Size);
this.y = (int)(Math.random() * Size);
location_exist_ind=checkLocation(this);
}
}
public int checkLocation(Location obj){
int temp_ind=0;
synchronized (Aquarium.location_list) {
if(Aquarium.location_list.size()!=0)
for(Location loc1 : Aquarium.location_list )
{
if(obj.equals(loc1)){
System.out.println("This location" + obj.x
+ " , "
+obj.y+ " is already taken by another fish , so generating the random location again.");
temp_ind=0;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
else temp_ind=1;
}
else temp_ind=1;
}
return temp_ind;
}
public void setNextLocation(int x,int y){
int X_location = 0;
int Y_location = 0;
int location_exist_ind=0 ;
while(location_exist_ind==0){
X_location= Direction_X.getRandom_direction_X(x);
Y_location= Direction_Y.getRandom_direction_Y(y);
Location temp_loc= new Location();
temp_loc.setX(X_location);
temp_loc.setY(Y_location);
location_exist_ind=checkLocation(temp_loc);
}
this.setX(X_location);
this.setY(Y_location);
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
Aquarium class
import java.util.LinkedList;
import java.util.Scanner;
public class Aquarium {
static int size= 0;
static int number_of_fishes = 1000;
static int number_of_moves = 0;
static LinkedList<Location> location_list = new LinkedList<Location>();
public static void main(String[] args) {
Scanner scn= new Scanner(System.in);
System.out.println("Please enter the size of the aquarium :");
size=scn.nextInt();
while(number_of_fishes >= Math.pow(size,2)){
System.out.println("Please enter the correct number of fishes in the aquarium , MAx allowed fishes are 2 to the power size of Aquarium: ");
number_of_fishes=scn.nextInt();
}
System.out.println("Please enter the Number of Minimum Moves for each of the fishes :");
number_of_moves=scn.nextInt();
Fish[] fishes = new Fish[number_of_fishes];
Thread[] thr = new Thread[number_of_fishes];
for (int i=0;i<number_of_fishes;i++){
fishes[i]= new Fish(size, number_of_moves ,i);
thr[i]= new Thread(fishes[i]);
thr[i].start();
}
try {
for (int i=0;i<number_of_fishes;i++)
thr[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Final Location list goes like : ");
for(Location loc : location_list){
System.out.println(loc.x + " , " + loc.y);
}
}
}
Fish class
public class Fish extends Location implements Runnable{
int moves=0;
int fishnum=0;
public Fish(int AquariumSize, int moves , int fishnum) {
super(AquariumSize);
this.moves=moves;
this.fishnum=fishnum;
}
#Override
public void run() {
for(int i=0;i< moves;i++){
if(i==0)
System.out.println(" Initial location of Fish " + fishnum + " Location is "+this.x + " , "+ this.y);
this.setNextLocation(x, y);
System.out.println(" Location of Fish " + fishnum + " Move number is "+ i + " , new location is "+this.x + " , " + this.y);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Direction enumeration
public enum Direction_X {
RIGHT(1),
NONE(0),
LEFT(-1);
public int direction_X_ind;
Direction_X(int X)
{
direction_X_ind = X;
}
public static int getRandom_direction_X(int x)
{
int X=x;
if(X!=0 && X!=Aquarium.size-1)
{
X = X + values()[(int) (Math.random() * (values().length))].direction_X_ind;
}
else if(x>=Aquarium.size-1)
{
X = X + values()[ (int) (Math.random() * (values().length-1)) + 1 ].direction_X_ind;
}
else
{
X = X + values()[(int) (Math.random() * (values().length-1))].direction_X_ind;
}
return (X);
}
}
public enum Direction_Y {
UP(1),
NONE(0),
DOWN(-1);
public int direction_Y_ind;
Direction_Y(int Y)
{
direction_Y_ind = Y;
}
public static int getRandom_direction_Y(int Y)
{
if(Y!=0 && Y != Aquarium.size-1)
{
Y = Y + values()[ (int) (Math.random() * (values().length))].direction_Y_ind;
}
else if(Y >= Aquarium.size-1)
{
Y = Y + values()[ (int) (Math.random() * (values().length-1)) + 1 ].direction_Y_ind;
}
else
{
Y = Y + values()[ (int) (Math.random() * (values().length-1))].direction_Y_ind;
}
return (Y);
}
}
Multi threading will only make your logic harder. The fishes' direction of movement is dependent on other fishes so this makes no sense letting each and every one of them move on its own with synchronization. Perhaps a better approach will be something involving a game loop. You can read more about it here. Basically its a more sophisticated implementation of an event loop.
Related
I'm trying to add a method an an array like this.
Position[] positions = new Position[10];
Position pos = positions.getPosAt(x, y);
I know this can be accomplished like:
Position pos = getPosAt(positions, x, y)
But I would like to know if there is a way to accomplish the first method.
you can make a class handler for this, like this PositionArray class (name it as you would like):
public class Test {
public static void main(String... args) {
Position[] positions = new Position[10];
positions[0] = new Position(5, 10);
positions[1] = new Position(11, 18);
positions[2] = new Position(20, 7);
PositionArray pa = new PositionArray(positions);
System.out.println(pa.getPosAt(5, 10)); // Position{x=5, y=10}
}
}
class PositionArray {
private Position[] positions;
public PositionArray(Position[] positions) {
this.positions = positions;
}
public Position getPosAt(int x, int y) {
for (Position p : positions) {
if (!Objects.isNull(p)) {
System.out.println(p.getX() + " " + p.getY());
if (p.getX() == x && p.getY() == y) {
return p;
}
}
}
return null;
}
}
class Position {
private final int x;
private final int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public String toString() {
return "Position{" + "x=" + x + ", y=" + y + '}';
}
}
There is no way to do this in Java. You could possibly create your own class that contained an array of Position objects and provides e.g. get methods, but there is no way whatsoever to add methods to classes you do not control, including all array types.
I am making a game in which i have randomly spawned objects. I also have a table that has the data of which objects are close to one another, say within a range of 200px - lets call them neighbors. What i want is to generate and assign coordinates to all the available objects so that this relationship is reflected. I want to view the structure of how they are.
I have made a greedy algorithm. Which works very slowly. and gets stuck sometimes. Does anyone have a better approach to this? - the coordinates can be assigned dynamically through trial and error no problem.
Below is the current code classes.
/**
* biggest problem
* */
public void assignInitialCoords( MyObject[] objects )
{
objects[0].setxCoor(rand.nextInt(1000));
objects[0].setyCoor(rand.nextInt(1000));
for(int i=0; i<objects.length; i++ )
{
ArrayList<MyObject> neighs = objects[i].getNeighbours();
System.out.println("Assigning " + objects[i].getId() + "'s coors");
setNonNeighborCoords(objects, i);
setNeighborCoordinates(objects, i, neighs);
System.out.println(objects[i].getId() + "(" + objects[i].getxCoor() + ", " + objects[i].getyCoor() + ")\n");
}
}
The classes
import java.util.ArrayList;
import java.util.HashMap;
public class MyObject
{
public ArrayList<MyObject> neighbours;
public ArrayList<MyObject> nonNeighbours;
public double fov = 360;
public double sRange = 100, xCoor, yCoor;
boolean isClustered = false;
public String id;
//Cluster[] clusters;
public MyObject()
{
neighbours = new ArrayList<MyObject>();
nonNeighbours = new ArrayList<MyObject>();
}
/**
* Find neighbours for this Object given a relations table
* example: if a MyObject has id A, and neighbor is B, then the key can be either: A_B or B_A
* Both represent the same relation, so we only need to check it once
* */
public void findNeighbours(HashMap<String, Integer> table, MyObject[] objects)
{
for (int i = 0; i < objects.length; i++)
{
String key1 = getId() + "_" + objects[i].getId(), key2 = objects[i].getId() +"_" + getId(), key="";
if(table.get(key1) != null)
{
key = key1;
if(table.get(key) <= getsRange())
getNeighbours().add(objects[i]);
}
if(table.get(key2) != null)
{
key = key2;
if(table.get(key) <= getsRange())
getNeighbours().add(objects[i]);
}
}
}
/**
* Check whether a given Object is the neighbour ArrayList of this object
* */
public boolean isInNeighbours( MyObject n )
{
if(neighbours.equals(null)) { return false; }
for(int i=0; i<getNeighbours().size(); i++)
if(getNeighbours().get(i).getId().equals(n.getId())) { return true; }
return false;
}
/**
* Check whether a given Object is the noneighbour ArrayList of this object
* */
public boolean isInNonNeighbours( MyObject n )
{
if(nonNeighbours.equals(null)) { return false; }
for(int i=0; i<getNonNeighbours().size(); i++)
if(getNonNeighbours().get(i).getId().equals(n.getId())) { return true; }
return false;
}
/**
* Check if given MyObject Can be a neighbour to this Object - for rand coord generation
* */
public boolean canBeANeighbour(MyObject n)
{
return distanceTo(n) <= sRange;
}
// return Euclidean distance between this and p
public double distanceTo(MyObject p) {
double dx = this.xCoor - p.xCoor;
double dy = this.yCoor - p.yCoor;
return Math.sqrt(dx*dx + dy*dy);
}
//Setters And Getters
public ArrayList<MyObject> getNeighbours(){ return neighbours; }
public void setNeighbours(ArrayList<MyObject> neighbours)
{
this.neighbours = neighbours;
}
public double getFov()
{
return fov;
}
public void setFov(double fov)
{
this.fov = fov;
}
public double getsRange()
{
return sRange;
}
public void setsRange(double sRange)
{
this.sRange = sRange;
}
public double getxCoor()
{
return xCoor;
}
public void setxCoor(double xCoor)
{
this.xCoor = xCoor;
}
public double getyCoor()
{
return yCoor;
}
public void setyCoor(double yCoor)
{
this.yCoor = yCoor;
}
public boolean isClustered()
{
return isClustered;
}
public void setClustered(boolean isClustered)
{
this.isClustered = isClustered;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public ArrayList<MyObject> getNonNeighbours()
{
return nonNeighbours;
}
public void setNonNeighbours(ArrayList<MyObject> nonNeighbours)
{
this.nonNeighbours = nonNeighbours;
}
}
//The sample test:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
public class SampleField
{
Random rand = new Random();
public int range = 100;
HashMap<String, Integer> table = new HashMap<String, Integer>();
String[] nodeIds = {"A", "B", "C", "D", "E", "F"};
public MyObject[] objects = new MyObject[nodeIds.length];
public static void main(String[] args)
{
SampleField test = new SampleField();
for(MyObject n: test.objects)
{
n.findNeighbours(test.table, test.objects);
}
test.populateNonNeighbours(test.objects);
System.out.println(test.table);
test.printRelationsTable( test.objects );
test.assignInitialCoords(test.objects);
System.out.println(test.table);
test.printRelationsTable( test.objects );
}
public SampleField()
{
initialiseNodes();
generateTestTable(objects);
}
/**
* biggest problem
* */
public void assignInitialCoords( MyObject[] objects )
{
objects[0].setxCoor(rand.nextInt(1000));
objects[0].setyCoor(rand.nextInt(1000));
for(int i=0; i<objects.length; i++ )
{
ArrayList<MyObject> neighs = objects[i].getNeighbours();
System.out.println("Assigning " + objects[i].getId() + "'s coors");
setNonNeighborCoords(objects, i);
setNeighborCoordinates(objects, i, neighs);
System.out.println(objects[i].getId() + "(" + objects[i].getxCoor() + ", " + objects[i].getyCoor() + ")\n");
}
}
/**
* if this object has neighbours, try to set their coordinates so that they do not conflict
*
* #param objects
* #param i
* #param neighs
*/
private void setNeighborCoordinates(MyObject[] objects, int i, ArrayList<MyObject> neighs)
{
//it should have at least one neighbour
if(neighs != null )
for( int j=0; j<neighs.size(); j++ )
{
//Initial assignment to the first neighbor
neighs.get(j).setxCoor(rand.nextInt() + objects[i].getsRange() );
neighs.get(j).setyCoor(rand.nextInt() + objects[i].getsRange() );
//If not a neighbor keep generating coordinates until it keeps being a neighbor.
while( !objects[i].canBeANeighbour(neighs.get(j)) )
{
//go deeper? - later
neighs.get(j).setxCoor(rand.nextInt(1000) - shootRange() - 5 );
neighs.get(j).setyCoor(rand.nextInt(1000) - shootRange() - 5 );
}
}
}
/**
* try to set the coordinates of each object here
* #param objects
* #param i
*/
private void setNonNeighborCoords(MyObject[] objects, int i)
{
for(MyObject n : objects[i].getNonNeighbours())
{
n.setxCoor(rand.nextInt() + shootRange() - 5);
n.setyCoor(rand.nextInt() + shootRange() - 5);
//Make sure non neighbors remain non neighbors
while(objects[i].canBeANeighbour(n))
{
n.setxCoor(rand.nextInt() + shootRange() - 5 );
n.setyCoor(rand.nextInt() + shootRange() - 5 );
}
}
}
/* populate nonNeighbours */
public void populateNonNeighbours(MyObject[] objects)
{
for(int i=0; i<objects.length; i++)
{
for(int j=0; j<objects.length; j++ )
{
if( (objects[i].getId() != objects[j].getId()) && !objects[i].isInNeighbours(objects[j]) )
{
objects[i].getNonNeighbours().add(objects[j]);
}
}
}
}
/* Show each object and its neighbors/nonneighbors - just for output */
public void printRelationsTable( MyObject[] objects )
{
for(int i=0; i<objects.length; i++ )
{
System.out.print("MyObject " + objects[i].getId() + "'s neighbours: ");
for(int j=0; j<objects[i].getNeighbours().size(); j++)
{
System.out.print(objects[i].getNeighbours().get(j).getId() + " ");
}
System.out.println();
System.out.print("\t\t" +objects[i].getId()+ "' : ");
for(int j=0; j<objects[i].getNonNeighbours().size(); j++)
{
System.out.print(objects[i].getNonNeighbours().get(j).getId() + " ");
}
System.out.println();
}
}
/* Initialise Objects here - give basic information */
public void initialiseNodes()
{
for(int i=0; i<nodeIds.length; i++)
{
MyObject n = new MyObject();
n.setId(nodeIds[i]);
n.setsRange(shootRange());
objects[i] = n;
}
}
/* Generate a list of neighbors for testing */
public void generateTestTable(MyObject[] objects)
{
for(int i=0; i<objects.length; i++)
{
/* Get two objects' ids and make them neighbors - ids must be unique */
String firstId = objects[rand.nextInt(objects.length)].getId();
String secondId = objects[rand.nextInt(objects.length)].getId();
while( firstId.equals(secondId) || table.containsKey(firstId + "_" + secondId) || table.containsKey(secondId + "_" + firstId) )
{
firstId = objects[rand.nextInt(objects.length)].getId();
secondId = objects[rand.nextInt(objects.length)].getId();
}
table.put(firstId + "_" + secondId, shootRange());
}
}
/* Range within which they are neighbors */
public int shootRange()
{
return range;
}
public void setRange(int range)
{
this.range = range;
}
}
If you only compare distances (and if you are talking about neighbours, it seems so), then you don't need to count them at all. Instead of
range = sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
if (range >d)...
use
sqrange(a,b) = sqr(a.x-b.x)+sqr(a.y-b.y)
if (range> d_sqr) ...
That means, you don't use ranges, but their squares. That quickens the comparisons about 50 times (for double). So, you can use much more easy structures.
This question already has answers here:
java.util.NoSuchElementException - Scanner reading user input
(5 answers)
Closed 6 years ago.
Alright so this is my first time posting.
I'm trying to create a box using another class that creates a rectangle. But when I try to run, I get to input the values for height and width but right after I try to input depth this error pops up.
Thanks in advance for any help.
Console:
Ange rektangelns bredd:
10
Ange rektangelns höjd:
10
En rektangelns med bredden 10 och höjden 10 ger arean 100
Ange rektangelns djup:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at cj222qu.Box.<init>(Box.java:18)
at cj222qu.Steg4_lab02.main(Steg4_lab02.java:7)
Box class:
import java.util.Scanner;
public class Box extends Rectangle {
private int depth;
public Box() {
Scanner hej = new Scanner(System.in);
String dep = null;
boolean go3 = true;
while (go3) {
try {
System.out.println("Ange rektangelns djup: ");
dep = hej.next();
Integer.parseInt(dep);
go3 = false;
} catch (NumberFormatException e) {
System.out.println("Ett fel har inträffat! Ange värdet som ett tal");
go3 = true;
}
}
//new Box(getWidth(), getHeight(), Integer.parseInt(dep));
hej.close();
}
public Box(int width, int height, int depth) {
setDepth(depth);
System.out.println(toString());
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("En låda med bredden " + getWidth() + ", höjden " + getHeight() + " och djupet " + ".");
result.append("Lådans volym är " + computeVolume() + ".");
result.append("Lådans mantelarea är " + computeArea() + ".");
return result.toString();
}
public int computeVolume() {
int volume = 0;
volume = getWidth() * getHeight() * getDepth();
return volume;
}
public int computeArea() {
int mantelarea = 0;
mantelarea = getDepth() * getWidth() * 2 + getDepth() * getHeight() * 2 + getWidth() * getHeight() * 2;
return mantelarea;
}
public int getDepth()
{
return depth;
}
public void setDepth(int d)
{
depth = d;
}
}
Rectangle class:
import java.util.Scanner;
public class Rectangle {
private int height;
private int width;
public Rectangle(int width, int height)
{
setHeight(height);
setWidth(width);
System.out.println(toString());
}
#Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("En rektangelns med bredden " + width + " och höjden " + height + " ger arean " + computeArea());
return result.toString();
}
public Rectangle()
{
Scanner keyboard = new Scanner(System.in);
String w = null;
String h = null;
boolean go1 = true;
boolean go2 = true;
while (go1) {
try {
System.out.println("Ange rektangelns bredd: ");
w = keyboard.next();
Integer.parseInt(w);
go1 = false;
} catch (NumberFormatException e) {
System.out.println("Ett fel har inträffat! Ange värdet som ett tal");
go1 = true;
}
}
while (go2) {
try {
System.out.println("Ange rektangelns höjd: ");
h = keyboard.next();
Integer.parseInt(h);
go2 = false;
} catch (NumberFormatException e) {
System.out.println("Ett fel har inträffat! Ange värdet som ett tal");
go2 = true;
}
}
new Rectangle(Integer.parseInt(w), Integer.parseInt(h));
keyboard.close();
}
public int computeArea()
{
int area = 0;
area = getHeight() * getWidth();
return area;
}
public int getHeight()
{
return height;
}
public int getWidth()
{
return width;
}
public void setHeight(int h)
{
height = h;
}
public void setWidth(int w)
{
width = w;
}
}
Main:
public class Steg4_lab02 {
public static void main(String[] args) {
new Box();
}
}
You shouldn't instantiate multiple Scanners with System.in, and it's a big no-no to close a Scanner instantiated with System.in (basically closing the STDIN stream) and then creating a new Scanner with System.in.
Rectangle should have a constructor that either takes a Scanner or a constructor that takes a width and height. Then either use the passed in Scanner to collect user input or collect user input in main() and create a Rectangle with the width and height collected from the user.
As Fildor stated in the comments, the Box and Rectangle classes should not be responsible for gathering user input.
everyone so I'm writting a program that solves quadratics (one doubled root and two doubled roots this seems to work but somehow I can't get it to solve complex roots? any help.
import javax.swing.JOptionPane;
public class QuadMethods {
static double a=0;
static double b=0;
static double c=0;
public static void main(String[] args) {
getUserInput(); // gets values into a, b, and c
double disc = getTheDiscriminant(a,b,c);
if (disc ==0) {
displayDoubledRealRoot(a,b,c);
//} else if (disc < 0) {
//displayComplexConjugates();
} else if (disc > 0) {
displayUnequalRealRoots(a,b,c);
//} else {
//System.out.println("Help! Arithmetic has failed!");
//
}
}
public static void displayUnequalRealRoots(double a, double b, double c) {
double disc = getTheDiscriminant(a,b,c);
double r1 = (-b+Math.sqrt(disc)/ (2*a));
double r2 = (-b-Math.sqrt(disc)/ (2*a));
String s = "two roots " + r1 + " and " + r2;
JOptionPane.showMessageDialog(null, s);
}
public static void displayDoubledRealRoot(double a, double b, double c) {
String s = "One doubled root = " + (-b/(2*a));
JOptionPane.showMessageDialog(null, s);
}
public static double getTheDiscriminant(double a, double b, double c) {
return b*b - 4*a*c;
}
public static void getUserInput() {
JOptionPane.showMessageDialog(null, "Getting coeffecients for ax^2+bx+c=0");
a = getANumber("a");
b = getANumber("b");
c = getANumber("c");
}
public static double getANumber(String p) {
boolean iDontHaveANumberYet = true;
double r = 0;
do {
try {
String aStr = JOptionPane.showInputDialog("Enter \"" + p + "\"");
r = Double.parseDouble(aStr);
iDontHaveANumberYet = false;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Hey, I can't deal with that. Must enter legal number.");
}
} while (iDontHaveANumberYet);
return r;
}
}
The solution:
import javax.swing.JOptionPane;
public class QuadMethods {
static double a=0;
static double b=0;
static double c=0;
public static void main(String[] args) {
getUserInput(); // gets values into a, b, and c
double disc = getTheDiscriminant(a,b,c);
if (disc ==0) {
displayDoubledRealRoot(a,b,c);
} else if (disc > 0) {
displayUnequalRealRoots(a,b,c);
} else {
// New method
displayComplexRoots(a,b,c);
}
}
public static void displayUnequalRealRoots(double a, double b, double c) {
double disc = getTheDiscriminant(a,b,c);
double r1 = (-b+Math.sqrt(disc)/ (2*a));
double r2 = (-b-Math.sqrt(disc)/ (2*a));
String s = "two roots " + r1 + " and " + r2;
JOptionPane.showMessageDialog(null, s);
}
public static void displayDoubledRealRoot(double a, double b, double c) {
String s = "One doubled root = " + (-b/(2*a));
JOptionPane.showMessageDialog(null, s);
}
public static double getTheDiscriminant(double a, double b, double c) {
return b*b - 4*a*c;
}
// New method
public static void displayComplexRoots(double a, double b, double c) {
double disc = 4 * a * c - b * b;
double dobleA = 2 * a;
String s = "two roots (" + (-b/dobleA) + "+" + (Math.sqrt(disc)/dobleA) + "i) and ("+ (-b/dobleA) + "" + (-Math.sqrt(disc)/dobleA) + "i)";
JOptionPane.showMessageDialog(null, s);
}
public static void getUserInput() {
JOptionPane.showMessageDialog(null, "Getting coeffecients for ax^2+bx+c=0");
a = getANumber("a");
b = getANumber("b");
c = getANumber("c");
}
public static double getANumber(String p) {
boolean iDontHaveANumberYet = true;
double r = 0;
do {
try {
String aStr = JOptionPane.showInputDialog("Enter \"" + p + "\"");
r = Double.parseDouble(aStr);
iDontHaveANumberYet = false;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Hey, I can't deal with that. Must enter legal number.");
}
} while (iDontHaveANumberYet);
return r;
}
}
General solution with complex numbers:
public class Complex {
double r;
double i = 0;
public Complex(double real, double imaginary) {
this.r = real;
this.i = imaginary;
}
public Complex(double real) {
this.r = real;
}
public Complex add(Complex c){
return new Complex(r+c.r, i+c.i);
}
public Complex cross(Complex c){
return new Complex(r*c.r - i*c.i, i*c.r + r*c.i);
}
public double getR() {
return r;
}
public double getI() {
return i;
}
#Override
public String toString() {
String result = Double.toString(r);
if (i < 0) {
result += " - " + ((i != -1)?Double.toString(-i):"") + "i";
} else if (i > 0) {
result += " + " + ((i != 1)?Double.toString(i):"") + "i";
}
return result;
}
public Complex[] squareRoot(){
double r2 = r * r;
double i2 = i * i;
double rR = Math.sqrt((r+Math.sqrt(r2+i2))/2);
double rI = Math.sqrt((-r+Math.sqrt(r2+i2))/2);
return new Complex[]{new Complex(rR, rI),new Complex(-rR, rI)};
}
public static Complex[] quadraticsRoot(double a, double b, double c) {
Complex[] result = new Complex(b*b - 4*a*c).squareRoot();
Complex bNegative = new Complex(-b);
Complex divisor = new Complex(1.0d / (2 * a));
for (int j = 0; j < result.length; j++) {
result[j] = bNegative.add(result[j]).cross(divisor);
}
return result;
}
public static void main(String[] args) {
Complex[] sol = quadraticsRoot(1,-10,34);
System.out.println(sol[0]);
System.out.println(sol[1]);
}
}
I'm using the Point Class to manage a list of (x,y) coordinates and I need to sort them in order of X.
I read online to make a new class PointCompare that implements Comparator, however I'm not sure how this works and therefore I have a compiler error in the sortByXCoordinates method.
Help would be appreciated a lot, and any comments are welcome, thanks in advance.
Here is some of my code:
import javax.swing.JOptionPane;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
//import java.util.Iterator;
public class ConvexHullMain {
private Point coordinates = new Point(0, 0);
private final int MAX_POINTS = 3;
private ArrayList<Point> coordinateList = new ArrayList<Point>();
public void inputCoordinates() {
String tempString; // temp string for JOptionPane
int tempx = 0;
int tempy = 0;
for (int i = 0; i < MAX_POINTS; i++) {
try {
// input x coordinates
tempString = JOptionPane.showInputDialog(null,
"Enter X coordinate:");
tempx = Integer.parseInt(tempString);
// input y coordinates
tempString = JOptionPane.showInputDialog(null,
"Enter Y coordinate:");
tempy = Integer.parseInt(tempString);
coordinates.setLocation(tempx, tempy);// set input data into
// coordinates object
coordinateList.add(coordinates.getLocation()); // put in
// arrayList
} // end Try
catch (NumberFormatException e) {
System.err.println("ERROR!");
main(null);
} // end catch
}// end for loop
}
public void displayPoints() {
for (int i = 0; i < MAX_POINTS; i++) {
JOptionPane.showMessageDialog(null, "Point number " + (i + 1)
+ " is: " + coordinateList.get(i));
}
// alt method
// Iterator i = coordinateList.iterator();
// String outputTemp;
// while (i.hasNext()) {
// outputTemp = i.next().toString();
// JOptionPane.showMessageDialog(null, "Point number " + " is: "
// + outputTemp);
// }
}
/**
* This sorts the points by the X coordinates
*/
public void sortByXCoordinates(){
coordinateList.sort(coordinates, new PointCompare());
}
public class PointCompare implements Comparator<Point> {
public int compare(Point a, Point b) {
if (a.x < b.x) {
return -1;
} else if (a.x > b.x) {
return 1;
} else {
return 0;
}
}
}
public static void main(String[] args) {
ConvexHullMain main = new ConvexHullMain();
main.inputCoordinates();
main.displayPoints();
}
}
private ArrayList<Point> coordinateList = new ArrayList<Point>();
...
Collections.sort(coordinateList, new PointCompare());
...
public class PointCompare implements Comparator<Point> {
public int compare(Point a, Point b) {
if (a.x < b.x) {
return -1;
}
else if (a.x > b.x) {
return 1;
}
else {
return 0;
}
}
}
You were close. The problem you had was simply that you invoked
public void sortByXCoordinates(){
coordinateList.sort(coordinates, new PointCompare());
}
What you want is this:
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import javax.swing.JOptionPane;
public class MainClass {
private final Point coordinates = new Point(0, 0);
private final int MAX_POINTS = 3;
private final ArrayList<Point> coordinateList = new ArrayList<Point>();
public void inputCoordinates() {
String tempString;
int tempx = 0;
int tempy = 0;
for (int i = 0; i < this.MAX_POINTS; i++) {
try {
tempString = JOptionPane.showInputDialog(null, "Enter X coordinate:");
tempx = Integer.parseInt(tempString);
tempString = JOptionPane.showInputDialog(null, "Enter Y coordinate:");
tempy = Integer.parseInt(tempString);
this.coordinates.setLocation(tempx, tempy);// set input data into
this.coordinateList.add(this.coordinates.getLocation()); // put in
}
catch (final NumberFormatException e) {
System.err.println("ERROR!");
main(null);
}
}
}
public void displayPoints() {
for (int i = 0; i < this.MAX_POINTS; i++) {
JOptionPane.showMessageDialog(null, "Point number " + (i + 1) + " is: " + this.coordinateList.get(i));
}
}
/**
* This sorts the points by the X coordinates
*/
public void sortByXCoordinates() {
Collections.sort(this.coordinateList, new PointCompare());
}
public class PointCompare
implements Comparator<Point> {
public int compare(final Point a, final Point b) {
if (a.x < b.x) {
return -1;
}
else if (a.x > b.x) {
return 1;
}
else {
return 0;
}
}
}
public static void main(final String[] args) {
final MainClass main = new MainClass();
main.inputCoordinates();
main.displayPoints();
}
}
i'm going to ignore all of the code you posted because you've just dumped everything without taking the time to identify the relevant areas.
now, from your question: you have an ArrayList containing Points. You want to sort it by the X axis/value.
List<Point> list = new ArrayList<Point>();
Firstly you need a Comparator which will compare one Point to another.
Comparator<Point> comp = new Comparator<Point>()
{
#Override
public int compare(Point o1, Point o2)
{
return new Integer(o1.x).compareTo(o2.x);
}
};
I choose to "box" the int to an Integer and use Integer's compareTo method. You could come up with a tidier method of comparison, up to you.
Then you can use the utility method Collections.sort
Collections.sort(list, comp);
and your list is sorted.
I'm using the Point Class to manage a list of (x,y) coordinates and I need to sort them in order of X
You can use a Bean Comparator or a custom Comparator as described in the blog.
The ArrayList class (see API documentation: http://download.oracle.com/javase/1.5.0/docs/api/java/util/ArrayList.html) that you use for your 'coordinateList' does not have a sort() method. You will have to implement this yourself, or use Collections.sort().