Rectangle custom object shows zero width, should be non-zero - java

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?

Related

Doing a school project, can't get Area calculation right

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.

can not access superclass method from within subclass that implements comparator

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> {

Having trouble showing colours in flood fill game

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.

while loop loops just once - java

Why my while loop is looping just once ? It should loops 99 times. Could Thread.sleep method break this loop or repaint ? Can you help me resolve this ? It doesn't show any errors. And i am using netbeans.
Licznik.java:
import javax.swing.JApplet;
public class Licznik extends JApplet {
#Override
public void init() {
setSize(900,900);
PanelLicznik pl=new PanelLicznik();
add(pl);
}
}
PanelLicznik.java:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.*;
import java.awt.geom.Line2D;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class PanelLicznik extends JPanel implements Runnable
{
int srodek = 450;
Image bg;
int a = 400, t = 0, v = 0, i = 0;
double x = 152, y = 756;
public PanelLicznik() {
Thread watek1 = new Thread(this);
watek1.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(900, 900);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
bg = new ImageIcon(this.getClass().getResource("s.gif")).getImage();
g2.drawImage(bg,0,0,null);
Line2D wsk = new Line2D.Double(srodek,srodek,x,y);
g2.setColor(new Color(255,255,255));
g2.setStroke(new BasicStroke(15.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER));
g2.draw(wsk);
}
#Override
public void run() {
t = 3;
v = 100;
i = 0
while(i < v){
try{
Thread.sleep(100);
}
catch(Exception ek) {}
double stopien = 231.4 - ((360*v)/280);
double radSek = Math.toRadians(stopien);
x = srodek + (a * Math.cos(radSek));
y = srodek - (a * Math.sin(radSek));
repaint();
i++;
}
}
}
repaint
public void repaint() {
repaint(0, 0, 0, width, height);
}
/**
* Repaints the component. If this component is a lightweight
* component, this results in a call to <code>paint</code>
* within <code>tm</code> milliseconds.
* <p>
* <b>Note</b>: For more information on the paint mechanisms utilitized
* by AWT and Swing, including information on how to write the most
* efficient painting code, see
* Painting in AWT and Swing.
*
* #param tm maximum time in milliseconds before update
* #see #paint
* #see #update(Graphics)
* #since JDK1.0
*/
public void repaint(long tm) {
repaint(tm, 0, 0, width, height);
}
/**
* Repaints the specified rectangle of this component.
* <p>
* If this component is a lightweight component, this method
* causes a call to this component's <code>paint</code> method
* as soon as possible. Otherwise, this method causes a call to
* this component's <code>update</code> method as soon as possible.
* <p>
* <b>Note</b>: For more information on the paint mechanisms utilitized
* by AWT and Swing, including information on how to write the most
* efficient painting code, see
* Painting in AWT and Swing.
*
* #param x the <i>x</i> coordinate
* #param y the <i>y</i> coordinate
* #param width the width
* #param height the height
* #see #update(Graphics)
* #since JDK1.0
*/
public void repaint(int x, int y, int width, int height) {
repaint(0, x, y, width, height);
}
/**
* Repaints the specified rectangle of this component within
* <code>tm</code> milliseconds.
* <p>
* If this component is a lightweight component, this method causes
* a call to this component's <code>paint</code> method.
* Otherwise, this method causes a call to this component's
* <code>update</code> method.
* <p>
* <b>Note</b>: For more information on the paint mechanisms utilitized
* by AWT and Swing, including information on how to write the most
* efficient painting code, see
* Painting in AWT and Swing.
*
* #param tm maximum time in milliseconds before update
* #param x the <i>x</i> coordinate
* #param y the <i>y</i> coordinate
* #param width the width
* #param height the height
* #see #update(Graphics)
* #since JDK1.0
*/
public void repaint(long tm, int x, int y, int width, int height) {
if (this.peer instanceof LightweightPeer) {
// Needs to be translated to parent coordinates since
// a parent native container provides the actual repaint
// services. Additionally, the request is restricted to
// the bounds of the component.
if (parent != null) {
if (x < 0) {
width += x;
x = 0;
}
if (y < 0) {
height += y;
y = 0;
}
int pwidth = (width > this.width) ? this.width : width;
int pheight = (height > this.height) ? this.height : height;
if (pwidth <= 0 || pheight <= 0) {
return;
}
int px = this.x + x;
int py = this.y + y;
parent.repaint(tm, px, py, pwidth, pheight);
}
} else {
if (isVisible() && (this.peer != null) &&
(width > 0) && (height > 0)) {
PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
new Rectangle(x, y, width, height));
SunToolkit.postEvent(SunToolkit.targetToAppContext(this), e);
}
}
}
Reset i before the while
v = 100;
i = 1; // if you want 99 times
while (i<v) { ...
Note: try to stay away from using global values like this because you have to keep track of the value of the variable all the time. Use local variables if possible.
Local variables:
int ax = 100;
int bx = 1;
while(bx < ax){
try{
Thread.sleep(100);
}
catch(Exception ek) {}
double stopien = 231.4 - ((360*v)/280);
double radSek = Math.toRadians(stopien);
x = srodek + (a * Math.cos(radSek));
y = srodek - (a * Math.sin(radSek));
repaint();
bx++;
}

Filling a square neatly with smaller squares

I am developing a game in which the world is divided up into units called sectors, which the player passes through. Each of these sectors is a different size, and each is divided up into units called SubSectors, which can be different sizes and fill the sector completely. I made a quick drawing of how I would like the generation to work:
tiles http://jsydie.com/artlib/misc/tiles.gif
EDIT: I am not trying to draw random pictures like this. The SubSector object (represented by the squares above) knows where it's upper-left corner is, and how big it is. I am trying to fit these "squares" onto a grid the size of the parent Sector object.
I am trying to work on the generation for the sectors, but I don't know how to take the next step from here:
package world;
import java.util.ArrayList;
import java.util.Random;
public class Sector {
private static int size;
private static ArrayList<SubSector> sub;
public Sector(int par0) {
size = par0;
sub = this.generateSubs();
}
private ArrayList<SubSector> generateSubs() {
ArrayList<SubSector> out = new ArrayList<SubSector>();
int side = this.size;
int spaces = side * side;
boolean[][] available = new boolean[side][side];
Random r = new Random();
int subSide;
int loc;
SubSector a;
boolean anyAvailable = true;
while(anyAvailable) {
subSide = r.nextInt(1+side)-1;
System.out.println(subSide);
a = new SubSector(subSide);
loc = r.nextInt(4);
System.out.println(loc);
out.add(a);
if(loc == 0) {
for(int i=0; i<subSide; i++) {
for(int j=0; j<subSide; j++) {
available[i][j] = false;
}
}
}
if(loc == 1) {
for(int i=subSide; i>0; i--) {
for(int j=0; j<subSide; j++) {
available[i][j] = false;
}
}
}
if(loc == 2) {
for(int i=subSide; i>0; i--) {
for(int j=subSide; j>0; j--) {
available[i][j] = false;
}
}
}
if(loc == 3) {
for(int i=0; i<subSide; i++) {
for(int j=subSide; j>0; j--) {
available[i][j] = false;
}
}
}
breakloop:
for(int i=0; i<side; i++) {
for(int j=0; j<side; j++) {
if(available[i][j] == true) {
anyAvailable = true;
break breakloop;
}
else
anyAvailable = false;
}
}
}
return out;
}
}
I have no idea how to make it check what size SubSectors are now available to it in the remaining space, then create one and place it in a random location.
This is something I created for my own use, but it's modified for your square sub-sectors. It contains a class Sector which provides operations on its space and manages its sub-sectors, which are a SubSector class. I left the Javadoc in for you. You might want to add checks that the coordinate arguments are inside the sector's space.
public class Sector {
private final int SIZE;
private int[][] allocationTable;
private Set<SubSector> subSectors = new HashSet<>();
/**
* Creates a new <code>Sector</code> of the specified size.
* #param size the size of the sector
*/
public Sector (int size) {
SIZE = size;
allocationTable = new int[SIZE][SIZE];
}
/**
* Checks if a position in the grid is occupied by a {#link SubSector}.
* #param x the x coordinate
* #param y the y coordinate
* #return <code>true</code> if the position is occupied, <code>false</code> otherwise
*/
public boolean isAllocated(int x, int y) {
return (allocationTable[x][y] != 0);
}
/**
* Calculates the free space originating at the given coordinates. A {#link SubSector} of this
* maximum size or less can be allocated in this space.
* #param x the x coordinate origin of the space
* #param y the y coordinate origin of the space
* #return the length of contiguous non-allocated space
*/
public int getNonAllocatedSpaceAt(int x, int y) {
int space = Math.min(SIZE-x, SIZE-y);
for (int i = x; i < space +x ; i++) {
for (int j = y; j < space + y; j++) {
if (isAllocated(i, j))
return Math.max(i - x, j - y);
}
}
return space;
}
/**
* Gets the {#link SubSector} containing the specified coordinate.
* #param x the x coordinate
* #param y the y coordinate
* #return the <code>SubSecotr</code> to which this space is allocated. <code>null</code> if
* the space is not allocated.
*/
public SubSector getSubSectorAt(int x, int y) {
for (SubSector s : subSectors)
if (s.number == allocationTable[x][y])
return s;
return null;
}
/**
* Gets the {#link SubSector} specified by its number designation.
* #param subSector the number designation of the <code>SubSector</code>
* #return the designated <code>SubSector</code>. <code>null</code> if the <code>SubSector</code>
* does not exist.
*/
public SubSector getSubSector(int subSector) {
for (SubSector s : subSectors)
if (s.number == subSector)
return s;
return null;
}
/**
* Allocates the specified coordinate space to the specified {#link SubSector} and creates a new
* <code>SubSector</code>. The <code>SubSector</code> must not already exist.
* #param x the x coordinate origin of the space
* #param y the y coordinate origin of the space
* #param size the length of contiguous space to be allocated
* #param subSector the number designation of the <code>SubSector</code>
* #return <code>true</code> if the space was allocated, <code>false</code> otherwise
*/
public boolean allocate(int x, int y, int size, int subSector) {
if (getNonAllocatedSpaceAt(x, y) < size || !subSectors.add(new SubSector(x, y, size, subSector)))
return false;
for (int i = x; i < size + x; i++) {
for (int j = y; j < size + y; j++) {
allocationTable[i][j] = subSector;
}
}
return true;
}
/**
* Frees the space occupied by the specified {#link SubSector} and removes it.
* #param subSector the <code>SubSector</code> to be removed
* #return <code>true</code> if the space was deallocated, <code>false</code> otherwise
*/
public boolean deallocate(int subSector) {
return remove(getSubSector(subSector));
}
/**
* Frees the space occupied by the {#link SubSector} occupying the specified coordinates.
* #param x the x coordinate
* #param y the y coordinate
* #return <code>true</code> if the space was deallocated, <code>false</code> otherwise
*/
public boolean deallocate(int x, int y) {
return remove(getSubSectorAt(x, y));
}
private boolean remove(SubSector sub) {
if (!subSectors.remove(sub))
return false;
for (int i = sub.x; i < sub.size + sub.x; i++) {
for (int j = sub.y; j < sub.size + sub.y; j++) {
allocationTable[i][j] = 0;
}
}
return true;
}
/**
* Gets the allocation table for this <code>Sector</code>.
* #return the allocation table for this <code>Sector</code>
*/
public int[][] getAllocationTable() {
return allocationTable;
}
/**
* Gets the size of this <code>Sector</code>.
* #return the size of this <code>Sector</code>
*/
public int getSize() {
return SIZE;
}
/**
* Gets the (unsorted) {#link Set} of {#link SubSector}s in this <code>Sector</code>.
* #return the <code>Set</code> of <code>SubSector</code>s in this <code>Sector</code>.
*/
public Set<SubSector> getSubSectors() {
return subSectors;
}
/**
* A <code>SubSector</code> represents a square-shaped area in its parent {#link Sector}'s space.
* A <code>SubSector</code> is designated (named) by a number and each parent <code>Sector</code>
* can only contain one such <code>SubSector</code>.
* A <code>SubSector</code> can only be created (and removed) by its parent <code>Sector</code>
* and can never be modified (this prevents synchronizations issues with the allocation table),
* however, its fields can be accessed directly.
*/
public class SubSector {
/** The x coordinate origin of this <code>SubSector</code>. */
public final int x;
/** The y coordinate origin of this <code>SubSector</code>. */
public final int y;
/** The length of this <code>SubSector</code>. */
public final int size;
/** The designation of this <code>SubSector</code>. */
public final int number;
private SubSector(int x, int y, int size, int number) {
this.x = x;
this.y = y;
this.size = size;
this.number = number;
}
}
}

Categories

Resources