All right, my new lab is almost done and I'm feeling very close. However, I'm getting one last confusing error and while I sort of think I get it I don't know how to fix it.
import java.util.Scanner;
import java.util.ArrayList;
import java.util.StringTokenizer;
/**
* Lab3.
*
* @author joe.auerbach
* @version 3.18.6
*/
publicclass Lab4
{
private Scanner sc;
privatestaticfinalint CHOICE_NONE = 0;
privatestaticfinalint CHOICE_BLOCK = 1;
privatestaticfinalint CHOICE_CUBE = 2;
privatestaticfinalint CHOICE_PYRAMID = 3;
privatestaticfinalint CHOICE_SPHERE = 4;
privatestaticfinalint CHOICE_TORUS = 5;
privatestaticfinalint CHOICE_TEXT = 6;
privatestaticfinalint CHOICE_QUIT = 7;
/**
* Constructor for objects of class Lab4.
*/
public Lab4()
{
sc = new Scanner(System.in);
}
/**
* Makes Lab3 use the given Scanner.
* @param testScanner Scanner to use
*/
publicvoid setScanner(Scanner testScanner)
{
sc = testScanner;
}
/**
* Displays the menu to the user.
*
* @return The option that the user picked
*/
publicint displayMenu()
{
int ret = -1;
boolean validResponse = true;
do
{
System.out.println("*********************");
System.out.println("1. Build a Block");
System.out.println("2. Build a Cube");
System.out.println("3. Build a Pyramid");
System.out.println("4. Build a Sphere");
System.out.println("5. Build a Torus");
System.out.println("6. Build a shape via a description");
System.out.println("7. Exit program");
System.out.println("*********************");
ret = sc.nextInt();
validResponse = (ret >= 1) && (ret <= 7);
if ( !validResponse )
{
System.out.println("I'm sorry, that is not a valid " +
"response. Please try again.");
}
}
while( !validResponse );
return ret;
}
/**
* Calculates the volume of a torus.
*
* @return The volume of the torus
*/
publicdouble calcTorusVolume()
{
System.out.print("Please enter the inner radius:");
double innerRadius = sc.nextDouble();
System.out.print("Please enter the outer radius:");
double outerRadius = sc.nextDouble();
double ret = 0.0;
Torus t = new Torus(innerRadius, outerRadius);
ret = t.getVolume();
return ret;
}
/**
* Calculates the volume of a pyramid.
*
* @return The volume of the pyamid
*/
publicdouble calcPyramidVolume()
{
System.out.print("Please enter the side length:");
double l = sc.nextDouble();
System.out.print("Please enter the width:");
double w = sc.nextDouble();
System.out.print("Please enter the height:");
double h = sc.nextDouble();
double ret = 0.0;
Pyramid t = new Pyramid(l, w, h);
ret = t.getVolume();
return ret;
}
/**
* Calculates the volume of a sphere.
*
* @return The volume of the sphere
*/
publicdouble calcSphereVolume()
{
System.out.print("Please enter the radius:");
double innerRadius = sc.nextDouble();
double ret = 0.0;
Sphere t = new Sphere(innerRadius);
ret = t.getVolume();
return ret;
}
/**
* Calculates the volume of a cube.
*
* @return The volume of the cube
*/
publicdouble calcCubeVolume()
{
System.out.print("Please enter the side length:");
double length = sc.nextDouble();
double ret = 0.0;
Cube t = new Cube(length);
ret = t.getVolume();
return ret;
}
/**
* Calculates the volume of a block.
*
* @return The volume of the block
*/
publicdouble calcBlockVolume()
{
System.out.print("Please enter the side length:");
double l = sc.nextDouble();
System.out.print("Please enter the width:");
double w = sc.nextDouble();
System.out.print("Please enter the height:");
double h = sc.nextDouble();
double ret = 0.0;
Block t = new Block(l, w, h);
ret = t.getVolume();
return ret;
}
/**
* Asks the user for a descriptive sentence.
* Then calculates the volume from that.
* The shape's name can be anywhere within
* the user's response and is not case sensitive.
* The shape's dimensions do not need any
* descriptive text around them and are
* taken in a particular order.
*/
publicdouble calcVolumeFromDescription()
{
String sentence;
int shape;
int i = 0;
double[] numbers = newdouble[3];
System.out.print("Please enter your description: ");
sc.nextLine();
sentence = sc.nextLine();
StringTokenizer st = new StringTokenizer(sentence);
while(st.hasMoreTokens())
{
String token = st.nextToken();
if(token.equalsIgnoreCase("block"))
{
shape = CHOICE_BLOCK;
}
elseif(token.equalsIgnoreCase("cube"))
{
shape = CHOICE_CUBE;
}
elseif(token.equalsIgnoreCase("pyramid"))
{
shape = CHOICE_PYRAMID;
}
elseif(token.equalsIgnoreCase("sphere"))
{
shape = CHOICE_SPHERE;
}
elseif(token.equalsIgnoreCase("torus"))
{
shape = CHOICE_TORUS;
}
elseif (Character.isDigit(token.charAt(0)))
{
numbers[i] = Double.valueOf(token);
i = i + 1;
}
}
if (shape == CHOICE_BLOCK)
{
double ret = 0.0;
Block t = new Block(numbers[0], numbers[1], numbers[2]);
ret = t.getVolume();
System.out.println("The calculated volume is " + ret);
return ret;
}
elseif (shape == CHOICE_CUBE)
{
double ret = 0.0;
Cube t = new Cube(numbers[0]);
ret = t.getVolume();
System.out.println("The calculated volume is " + ret);
return ret;
}
elseif (shape == CHOICE_PYRAMID)
{
double ret = 0.0;
Pyramid t = new Pyramid(numbers[0], numbers[1], numbers[2]);
ret = t.getVolume();
System.out.println("The calculated volume is " + ret);
return ret;
}
elseif (shape == CHOICE_SPHERE)
{
double ret = 0.0;
Sphere t = new Sphere(numbers[0]);
ret = t.getVolume();
System.out.println("The calculated volume is " + ret);
return ret;
}
elseif (shape == CHOICE_TORUS)
{
double ret = 0.0;
Torus t = new Torus(numbers[0], numbers[1]);
ret = t.getVolume();
System.out.println("The calculated volume is " + ret);
return ret;
}
double ret = 0.0;
return ret;
}
/**
* The run method for the class.
*/
publicvoid run()
{
int choice = CHOICE_NONE;
while (choice != CHOICE_QUIT)
{
double volume = 0.0;
choice = displayMenu();
if (choice == CHOICE_BLOCK)
{
volume = calcBlockVolume();
}
elseif (choice == CHOICE_CUBE)
{
volume = calcCubeVolume();
}
elseif (choice == CHOICE_PYRAMID)
{
volume = calcPyramidVolume();
}
elseif (choice == CHOICE_SPHERE)
{
volume = calcSphereVolume();
}
elseif (choice == CHOICE_TORUS)
{
volume = calcTorusVolume();
}
elseif (choice == CHOICE_TEXT)
{
volume = calcVolumeFromDescription();
}
if (choice != CHOICE_QUIT)
{
System.out.println("The calculated volume is " + volume);
}
}
}
/**
* The main method for the program.
*/
publicstaticvoid main(String [] args)
{
Lab4 c = new Lab4();
c.run();
}
}
At "if (shape == CHOICE_BLOCK)" I get "variable shape might not have been initialized.
It seems ot me that this is because it's in hte wrong brackets. Shape is assigned like this within the while loop before this, but I don't want the loop to continue past where it is because I only want to run the rest once.
I'm very sure that t his is close to right, but I must be missing some small point or other. Help would be nice.
Here is the block where you initialize shape. I put in some comments
if(token.equalsIgnoreCase("block")) {
shape = CHOICE_BLOCK;
} elseif(token.equalsIgnoreCase("cube")) {
shape = CHOICE_CUBE;
} elseif(token.equalsIgnoreCase("pyramid")) {
shape = CHOICE_PYRAMID;
} elseif(token.equalsIgnoreCase("sphere")) {
shape = CHOICE_SPHERE;
} elseif(token.equalsIgnoreCase("torus")) {
shape = CHOICE_TORUS;
} elseif (Character.isDigit(token.charAt(0))) {
numbers[i] = Double.valueOf(token);
i = i + 1;
//shape is NOT initialized
} else { //I know you didn't write this, but I put it in for better documentation
//shape is NOT initialized
}
You see, there are 2 cases where shape is not initialized. The compiler notices that.
Best way would simply be to declare and initialize shape at the same moment.
int shape = 0;
Note: This should make absolutely no difference, because the standard value of an int is 0, at least that's what we suspect to be in the system memory. This is just for the compiler.
shape = Choice.BLOCK;
if (shape == Choice.BLOCK) { ...
}
You ask what's the advantage?
It's all about passing parameters to a method.
Using ints someone could pass -1 or 10, that would be a problem.
Using the enum option he HAS to pass Choice.* or a null value. The program wouldn't compile if you'd try anything else.
Just make sure that the enum is publicif the method should be accessed from outside the class.
Also, there is no guarantee that st.hasMoreTokens() will not return false the first time, preventing the loop body from being run even once. So this is a third case where shape will not be initialised.
You should also think about replacing all of those if statements with polymorphism.
Create an abstract base class Volume then make subclasses Sphere, Pyramid, etc that extend Volume and implement the specific calculations in their own implementations of the virtual methods.
Then choose which class is instantiated in another function (this is called a Factory) so the main loop should be much cleaner, something like:
int choice = CHOICE_NONE;
while (choice != CHOICE_QUIT) {
double volume = 0.0;
choice = displayMenu();
if (choice != CHOICE_QUIT) {
Volume v = VolumeFactory(choice);
System.out.println("The calculated volume is " + v.getVolume());
}
}