import java.util.Scanner;
class Shape
{
// Declaration of the instance variables for the class
double height, base, area, radius, perimeter;
String shape;
// Constructor that will initialize only the 'shape' variable
public Shape(String shape)
{
this.shape = shape;
}
// The method used to calculate the area of the shape
double area(){
Scanner s = new Scanner(System.in); // new scanner object
// Calculates area if shape is a circle
if (this.shape.equalsIgnoreCase("circle")){
System.out.print("What is the radius of the circle? ");
radius = s.nextDouble();
area = Math.PI * (radius * radius);
}
// Calculates area if shape is a rectangle
else if (this.shape.equalsIgnoreCase("rectangle"))
{
System.out.print("What is the base of the shape? ");
base = s.nextDouble();
System.out.print("What is the height of the shape? ");
height = s.nextDouble();
area = base * height;
}
// Calculates area if shape is a square
else if (this.shape.equalsIgnoreCase("square"))
{
System.out.print("What is the side length? ");
base = s.nextDouble();
area = base * base;
}
// Calculates area if shape is a triangle
else if (this.shape.equalsIgnoreCase("triangle"))
{
System.out.print("What is the base of the triangle? ");
base = s.nextDouble();
System.out.print("What is the height of the triangle? ");
height = s.nextDouble();
area = base * height * .5;
}
// After all the calculations are made, the method returns the area
return area;
}
// Method that calculates the perimeter of the shape
double perimeter()
{
Scanner s = new Scanner(System.in); // new scanner object
// calculates perimeter if the shape is a circle
if (this.shape.equalsIgnoreCase("circle"))
perimeter = Math.PI * (radius * 2);
// calculates perimeter if the shape is a rectangle
else if (this.shape.equalsIgnoreCase("rectangle"))
perimeter = (2 * base) + (2 * height);
// calculates perimeter if the shape is a square
else if (this.shape.equalsIgnoreCase("square"))
perimeter = base * 4;
// calculates smallest possible perimeter if shape is a triangle
else if (this.shape.equalsIgnoreCase("triangle")){
perimeter=(2*(Math.sqrt((height*height)+((base/2)*(base/2))))+base);
}
// After all the calculations are made, the method returns the perimeter
return perimeter;
}
}
public class Main
{
// The main method begins here
public static void main(String[] args)
{
Scanner x = new Scanner(System.in); // new scanner object
// This variable is local to the main method
String units;
System.out.println("\t*******Area and Perimeter Calculator!*******");
// Get input from the user
System.out.print("What shape? ");
// Create new object using the input
Shape shape1 = new Shape(x.next());
// If the shape is a triangle, there are an infinite amount of possible areas
// so it will only display the perimeter
if (shape1.shape.equalsIgnoreCase("triangle"))
{
System.out.print("What units of measurment? ");
units = x.next();
System.out.println("The area is: " + shape1.area() + ' ' + units +
" squared.\nThe smallest possible perimeter is: " +
shape1.perimeter() + ' ' + units);
}
// If it is any of the other shapes, it displays both the area and perimeter.
else
{
System.out.print("What units of measurment? ");
units = x.next();
System.out.println("The area is: " + shape1.area() + ' ' + units +
" squared.\nThe perimeter is: " + shape1.perimeter() +
' ' + units);
}
}
}
Refactorings
No refactoring yet !
Brian
February 22, 2009, February 22, 2009 22:39, permalink
Your program is very procedurally-oriented. With Java, programmers usually try to keep classes very modular/encapsulated. In your code, the area() method both takes in values and calculates area. Try to break down that method a bit. Break the Shape class into smaller classes and create a hierarchy.
In my version, the Main method needs some refactoring.
import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;
// Abstract class for any Shape
public abstract class Shape {
protected double area;
protected double perimeter;
public Shape() {} // Empty constructor
public double area() {
return area;
}
public double perimeter() {
return perimeter;
}
// Derived classes will call this to fill
// in the area and perimeter values;
protected abstract void calculateValues();
}
public class Rectangle extends Shape {
private double length;
private double width;
public Rectangle(double l, double w) {
this.length = l;
this.width = w;
calculateValues();
}
protected void calculateValues() {
this.area = length * width;
this.perimeter = 2 * (length + width);
}
}
public class Square extends Rectangle {
public Square(double s) {
super(s, s); // Calls Rectangle's constructor
}
}
public class Triangle extends Shape {
private double base;
private double height;
private double offset; // Altitude offset from center of base
public Triangle(double b, double h, double o) {
this.base = b;
this.height = h;
this.offset = o;
calculateValues();
}
public Triangle(double b, double h) {
this(b, h, 0.0); // Call other constructor
}
protected void calculateValues() {
this.area = (base * height) / 2;
this.perimeter = base +
Math.sqrt(
Math.pow((base/2) + offset, 2) +
Math.pow(height, 2)) +
Math.sqrt(
Math.pow((base/2) - offset, 2) +
Math.pow(height, 2));
}
}
public class Circle extends Shape {
private double radius;
public Circle(double r) {
this.radius = r;
calculateValues();
}
protected void calculateValues() {
this.area = Math.PI * Math.pow(radius, 2);
this.perimeter = Math.PI * 2 * radius;
}
}
public class Main {
private Scanner s = new Scanner(System.in);
private Set<String> validShapes = new HashSet<String>();
public static void main(String[] args) {
Main m = new Main(); // Sorry, I know this part is
m.run(); // sloppy programming.
}
public void run() {
// Adds shape names into the validShape set
addValidShapes();
// Get shape name from user
String shapeInput = getShapeInput();
// Declare shape object
Shape shape = null;
try {
shape = getShapeData(shapeInput);
} catch (Exception e) {
System.out.println(e.getMessage());
System.exit(-1);
}
String unit = getUnit();
showShapeInfo(shape, unit);
}
protected void addValidShapes() {
validShapes.add("rectangle");
validShapes.add("square");
validShapes.add("triangle");
validShapes.add("circle");
}
public String getShapeInput() {
System.out.print("Which shape? ");
String shape = s.next().toLowerCase();
if (validShapes.contains(shape)) {
return shape;
}
return getShapeInput();
}
// Gets shape-specific data
public Shape getShapeData(String shapeInput) throws Exception {
if (shapeInput.equals("rectangle")) {
return getRectangleData();
} else if (shapeInput.equals("square")) {
return getSquareData();
} else if (shapeInput.equals("triangle")) {
return getTriangleData();
} else if (shapeInput.equals("circle")) {
return getCircleData();
}
throw new Exception("NoSuchShapeExcpetion");
}
public Rectangle getRectangleData() {
System.out.print("Length? ");
double length = s.nextDouble();
System.out.print("Width? ");
double width = s.nextDouble();
return new Rectangle(length, width);
}
public Square getSquareData() {
System.out.print("Length? ");
double length = s.nextDouble();
return new Square(length);
}
public Triangle getTriangleData() {
System.out.print("Base? ");
double base = s.nextDouble();
System.out.print("Height? ");
double height = s.nextDouble();
System.out.print("Altitude Offset? ");
double offset = s.nextDouble();
return new Triangle(base, height, offset);
}
public Circle getCircleData() {
System.out.print("Radius? ");
double radius = s.nextDouble();
return new Circle(radius);
}
public String getUnit() {
System.out.print("Unit? ");
return s.next();
}
// Outputs shape's area and perimeter info
public void showShapeInfo(Shape s, String u) {
System.out.println("Area: " + s.area() + " " + u + " squared");
System.out.println("Perimeter: " + s.perimeter() + " " + u);
}
}
Justin
November 3, 2010, November 03, 2010 03:02, permalink
How do you change the coding where it will ask you the sizes of the shape instead of the "which shape"? Also, if user enters 1 2 3, it detects as a triangle and spits out values (perimeter & area)...?
woo