I'm trying to recursively call a method until I obtain the desired output. However, I want to call a method from another class and get information from that method in order to use it in my recursive method. For example, suppose I have a parent class called Cake that contains information about a cake such as its batter(i.e. amount the batter), an extended class with a specific type of cake containing a unique instance of the batter, and I have another class called Bakery where I want to actually make cakes that are being ordered. I have a method in Bakery called createCake, and I want to recursively call this method until enough batter is in the pan to create a cake. If the amount of batter is randomly generated in the extended class, how do I call the getBatter method from that class and capture the information about the batter amount in order to use it in my recursive method for creating the cakes? Can anyone help me out with this? I'm doing something similar to this, but I don't quite understand how I would go about actually getting the information in order to get the recursion to work. I have an example of the code below, so that you can have an idea of what I'm trying to do (I know it's not very accurate). Any help would be greatly appreciated.
import java.util.Random;
public abstract class Cake
{
static Random gen = new Random(System.currentTimeMillis());
public int type; //type of cake
public static int batter = gen.nextInt() * 3; //random amount of batter
public int getType()
{
return type;
}
public int getBatter()
{
return batter;
}
}
public class RedVelvet extends Cake
{
public int type;
public int batter = gen.nextInt(3)+6; //generates between 6-8 cups of batter inclusive
public int getType()
{
return 1;
}
public int getBatter()
{
return batter;
}
}
public class Chocolate extends Cake
{
public int type;
public int batter = gen.nextInt(3)+6; //generates between 6-8 cups of batter inclusive
public int getType()
{
return 2;
}
public int getBatter()
{
return batter;
}
}
public class Pound extends Cake
{
public int type;
public int batter = gen.nextInt(3)+6;
public int getType()
{
return 3;
}
public int getBatter()
{
return batter;
}
}
public class Bakery
{
import java.util.Scanner;
System.out.print("Enter desired size of cake to be baked (Must be at least 12):");
desiredSize=scan.nextInt();
public static void createCake(int desiredSize, int currentSize) //currentSize is the current amount of batter in the pan
{
if (currentSize == desiredSize)
return;
else if (currentSize < desiredSize)
{
//Recursively call createCake method so that batter continues to be added to the pan until there is enough to make the desired cake size. I want to get the batter information from one of the extended classes in order to add it to the cake.
}
}
Is this for school or a course of sorts because I personally wouldn't go this route but then again that's my opinion. It's like, what the heck do I know about baking and I can safely tell you....absolutely nothing. Some may even say that about my programming/coding skills but then again, I'm not a programmer and I am self taught in almost all programming environments including good old Assembly most of which I have now forgotten. :/
I should think that when it comes to baking cakes (or most things for that matter) some sort of accuracy must be established so as to avoid waste and we all know that waste costs money. I'm not overly convinced that generating random amounts of cake batter is accurate enough for what you're most likely are trying to accomplish but then again, you already know this. I noticed that in your different cake classes they all basically generate a random number from 6 to 8. If they all do the same thing then why have them?
I don't believe you need recursion at all but instead a simple method called from within a loop, for example:
while (currentSize < desiredSize) {
currentSize+= getBatter(cake, desiredSize);
}
Here is how I would do this and I apologize now if you find this is all totally meaningless:
import java.util.Random;
import java.util.Scanner;
public class Bakery {
public static void main(String[] args) {
getBaking(); // :)
}
private static void getBaking(){
Scanner scan = new Scanner(System.in);
String cakeType = "";
while (cakeType.equals("")) {
System.out.print("Enter desired cake to be baked (Pound, Chocolate, "
+ "RedVelvet) or\nenter 'exit' to quit: -> ");
cakeType = scan.nextLine();
if (cakeType.isEmpty()) {
System.out.println("\nYou must supply the name of cake to bake or "
+ "enter 'exit' to quit!\n");
}
else if (cakeType.toLowerCase().equals("exit")) { System.exit(0); }
else if (!cakeType.toLowerCase().matches("(pound|chocolate|redvelvet)")) {
System.out.println("\nYou must supply the name of cake as shown above!\n");
cakeType = "";
}
}
int desiredSize = 0;
String size = "";
while (size.equals("")) {
System.out.print("\nEnter desired size of cake to be baked (must be at "
+ "least 12\"): -> ");
size = scan.nextLine();
if (size.isEmpty()) {
System.out.println("\nYou must supply the size of cake to bake or "
+ "enter 'exit' to quit!\n");
}
else if (size.toLowerCase().equals("exit")) { System.exit(0); }
else if (Integer.valueOf(size.replace("\"","")) < 12 ) {
System.out.println("\nYou must supply a cake size of 12\" or greater!\n");
size = "";
}
}
desiredSize = Integer.valueOf(size.replace("\"",""));
createCake(cakeType, desiredSize, 0);
}
public static void createCake(String cake, int desiredSize, int currentSize) {
//currentSize is the current amount of batter in the pan
while (currentSize < desiredSize) {
currentSize+= getBatter(cake, desiredSize);
System.out.println(currentSize);
}
System.exit(0); // Done! - Quit!
}
public static int getBatter(String cake, int desiredSize) {
Random gen = new Random(System.currentTimeMillis());
// Since the random generation for the batter amount is the
// same for all cake types according to your code we just
// need this:
int batterAmount = gen.nextInt(3)+6;
// But if we want to be more specific for each Cake Type
// then we can do it this way but first create the required
// batter equations for each cake type and remove the /* and
// */ from the code but first comment out (//) the batterAmount
// variable declaration above.
// NOTE: Both cake diameter AND 'Height' should play into the factor
// of how much batter is required unless of course all cakes made are
// of the same height.
/*
int batterAmount = 0;
switch (cake.toLowerCase()) {
case "pound":
batterAmount = //batter amount to make 12 inch cake + (this much batter for a 1 inch cake * (desiredSize - 12));
break;
case "chocolate":
batterAmount = //batter amount to make 12 inch cake + (this much batter for a 1 inch cake * (desiredSize - 12));
break;
case "redvelvet":
batterAmount = //batter amount to make 12 inch cake + (this much batter for a 1 inch cake * (desiredSize - 12));
break;
} */
return batterAmount;
}
}
Well, I do hope this has helped you somewhat or at least thrown a little thought into the oven :P
Related
Right now I'm doing some tasks from a java e-book that I've acquired, and unfortunately, I'm stuck. The main thought of this program is to create a Vehicle class, which along with a test program can increase, decrease and break the current speed.
The starting speed should be 0. I want the user to specify what speed the car should drive to (for an example 90 km/h). After hitting the speed(90 in this case) I want the program to ask the user if he wants to decrease the speed to a given value, stay at the same speed, or break to 0. Should all of this be done in the testprogram, or should it be implemented into the Vehicle class?
I'm supposed to create a program from the following UML: https://i.stack.imgur.com/01fgM.png
This is my code so far:
public class Vehicle {
int speed;
//Constructor
public Vehicle () {
this.speed = 0;
}
public void increaseSpeed (int differenceInc) {
this.speed += differenceInc;
}
public void decreaseSpeed (int differenceDec) {
this.speed -= differenceDec;
}
public void brake() {
}
public int getSpeed () {
return this.speed;
}
}
And this is my empty test class.
public class VehicleTest {
public static void main(String[] args) {
Vehicle golf = new Vehicle();
//Speed which should be accelerated to:
Vehicle myHybrid = new Vehicle();
System.out.println("You've hit the given speed. Do you want to stay at this speed, break, or decrease to another given speed?");
}
}
Well , first of all, welcome to Stack Overflow.
If you want a method to accept arguments (parameters) then you must declare said arguments and the arguments' types in the mehtod declaration:
public void increaseSpeed (int augmentValue) {
this.speed += augmentValue;
}
You're also asking about software design: "should the component (Vehicle) user or client be able to set the augment value of the increaseSpeed mehtod?" . The answer relies on the design of said component. If your method will accept an argument then perhaps the method should also validate the input value and establish pre and post conditions.
Hope this helps.
Probably the idea is to take an int for increaseSpeed(), so that you can increase the speed by that given integer. Also add the logic for hitting the speed limit in your increaseSpeed method.
So...
public void increaseSpeed (int amount) {
if (speed + amount < MAX_SPEED) { // Where MAX_SPEED is a static final int of value 90
this.speed += amount;
} else {
System.out.println("Max speed reached. Want to exceed (y/n)?");
Scanner scanner = new Scanner(System.in);
char c = scanner.next().charAt(0);
if (c == 'y') {
this.speed += amount;
}
}
}
You can do the same for decreaseSpeed(), of course. Don't forget to check if decreasing the speed doesn't result in a negative speed (unless, you consider a negative value of speed to be driving in reverse.
By the way, here I have hard-coded MAX_SPEED for simplicity. This is, of course, dependent on the road you are driving, so it is probably better to do this differently (e.g., a Road class that includes the particular attributes of a given road, or by passing both an integer for the amount you want to speedup with and an integer for the maximum speed).
I've been working ahead in my intro class and I've almost finished my last project, Keno. its a betting game that rewards money according to how many numbers you matched with the dealer. I'm having issues on where to put the betting aspect, they start with 100$ and are asked to wage a certain amount of money. I don't know which method that would go under for it to still work because my methods aren't voids, so i wont be able to return more than one data value.
My second issue, maybe the more important one, is that they need to be unique numbers. To do that i would need to search the array of numbers every time to see if they match, or use an array of booleans to keep track of the numbers. I don't know how i would do the second but i have a good idea of what i would do with the first. The issue is that im using a do while already, im not sure how i could add the for loop with a nested for loop in. Here is my code, sorry if its messy, i know my teacher hates my curly braces:
package Keno;
import cs1.Keyboard;
public class Keno {
public static void main(String[]args){
int userArr[]=user();
int compArr[]=computer();
int howMany=matchNums(compArr,userArr);
int moneyGained=betting(howMany);
System.out.println("You matched "+howMany+" numbers");
System.out.println("You have gained "+moneyGained+" dollars!");
}
public static int[] computer(){
int []compChoice=new int[20];
for(int x=0;x<compChoice.length;x++){
compChoice[x]=(int)(Math.random()*81);
}
return compChoice;
}
public static int[] user(){
int choice[]=new int[7];
System.out.println("Welcome to Keno!");
System.out.println("Choose 7 unique numbers ranging from 1-80");
System.out.println("*************************************************");
//assigns numbers to choice array
for(int x=0;x<choice.length;x++){
do{
int temp=x+1;
System.out.println("number "+temp+": ");
choice[x]=Keyboard.readInt();
}while(choice[x]<0||choice[x]>80);
}
System.out.println("Thanks!");
System.out.println("*************************************************");
return choice;
}
public static int matchNums(int arr1[], int arr2[]){
int count=0;
//checks each array slot individually to see if they match
for(int x=0;x<arr1.length;x++){
for(int y=0;y<arr2.length;y++){
if(arr1[x]==arr2[y]){
count++;
}
}
}
return count;
}
public static int betting(int matches){
int moneyGained=0;
if(matches==7){
moneyGained=12000;
}else if(matches==6){
moneyGained=200;
}else if(matches==5){
moneyGained=20;
}else if(moneyGained==4){
moneyGained=1;
}
return moneyGained;
}
}
The simplest way to add the betting/money concept would be to add an integer which represents how much money the player has (starting at 100). You will have to ask the player how much they want to wager, and then adjust their money accordingly.
public static void main(String[] args) {
int playerMoney = 100;
int wagered = getWager(); // dont forget it has to be 0 < wagered <= 100
// adjust players money according to the wager, and how much they won
For ensuring uniqueness, either one of your ideas would work. I like just checking for the numbers existence already in the array, but the boolean array of size 80 would work too. It just seems like a lot for only 7 numbers though.
I am creating a small game of Final Fantasy characters, in which I input the name of who I would like to "fight" I have each character (only 5 of them) as a subclass to a superclass called Stats in which the variables (non static) and getters/setters are defined.
The code all works as I would like, but I don't like it all being in One huge class.
The Main method is here;
package com.George.revision;
import java.util.Random;
import com.George.characters.Cloud;
import com.George.characters.Squall;
import com.George.characters.Stats;
import com.George.characters.TheEnemy;
import com.George.characters.ThePlayer;
import com.George.characters.Tidus;
import com.George.characters.Yuna;
import com.George.characters.Zidane;
import com.George.input.GetInput;
import com.George.input.ListNames;
public class Main {
public static void main(String[] args) {
ListNames.listNames();
Stats clo = new Cloud();
Stats squ = new Squall();
Stats zid = new Zidane();
Stats tid = new Tidus();
Stats yun = new Yuna();
String versus = GetInput.getInput("\nWhich of these Characters would you like to go up against?");
Stats ene1 = new TheEnemy();
switch (versus) {
case "Cloud":
ene1.setName(Names.CLOUD);
ene1.setHairColor(Stats.BLONDE);
ene1.setWep(Weapons.BUSTER_SWORD);
ene1.setSkill(clo.skill);
ene1.setAp(clo.ap);
ene1.setStr(clo.str);
ene1.setMag(clo.mag);
break;
case "Squall":
ene1.setName(Names.SQUALL);
ene1.setHairColor(Stats.BLACK);
ene1.setWep(Weapons.LIONHEART);
ene1.setSkill(squ.skill);
ene1.setAp(squ.ap);
ene1.setStr(squ.str);
ene1.setMag(squ.mag);
break;
case "Zidane":
ene1.setName(Names.ZIDANE);
ene1.setHairColor(Stats.LIGHTBROWN);
ene1.setWep(Weapons.THIEF_DAGGER);
ene1.setSkill(zid.skill);
ene1.setAp(zid.ap);
ene1.setStr(zid.str);
ene1.setMag(zid.mag);
break;
case "Tidus":
ene1.setName(Names.TIDUS);
ene1.setHairColor(Stats.BLONDE);
ene1.setWep(Weapons.CALADBOLG);
ene1.setSkill(tid.skill);
ene1.setAp(tid.ap);
ene1.setStr(tid.str);
ene1.setMag(tid.mag);
break;
case "Yuna":
ene1.setName(Names.YUNA);
ene1.setHairColor(Stats.DARKBROWN);
ene1.setWep(Weapons.NIRVANA);
ene1.setSkill(yun.skill);
ene1.setAp(yun.ap);
ene1.setStr(yun.str);
ene1.setMag(yun.mag);
break;
default:
System.out.println("You did not enter a valid character name");
break;
}
System.out.println("You have chosen to face " + ene1.name);
System.out.println("Enemy Skill = " + ene1.skill + " Enemy Weapon = " + ene1.wep);
System.out.println("Enemy Skill = " + ene1.skill + " Enemy Weapon = " + ene1.wep);
int eneTotal = ene1.skill + ene1.ap + ene1.str + ene1.mag;
Stats player = new ThePlayer();
String plN = GetInput.getInput("What is your name?");
player.playerName = plN;
System.out.println("So Your name is " + player.playerName);
String plWep = GetInput.getInput("What is your Weapon's name?");
player.playerWep = plWep;
System.out.println("So your Weapon is " + player.playerWep);
Random generator = new Random();
int plSkill = generator.nextInt(10);
player.skill = plSkill;
System.out.println("Your skill level is " + player.skill);
Random gn = new Random();
int plAp = gn.nextInt(10 - 5) + 5;
System.out.println("So your Attack Power is " + plAp);
player.ap = plAp;
Random gns = new Random();
int plStr = gns.nextInt(10);
System.out.println("So your Strength is " + plStr);
plStr = player.str;
Random gnm = new Random();
int plMag = gnm.nextInt(10 - 5) + 5;
player.mag = plMag;
System.out.println("So your Magic is " + player.mag);
int plHax = 15;
double doubleResult = plHax;
double ene1Hax = 3.99;
int intResult = (int)ene1Hax;
double doubleValue = 6.99;
Double doubleObj = new Double(doubleValue);
int intR = doubleObj.intValue();
System.out.println(intR);
int plyrTotal = player.skill + player.ap + player.str + player.mag;
if (plyrTotal > eneTotal) {
System.out.println("Congratulations you beat " + ene1.name + " Please Play Again!" );
} else if (plyrTotal == eneTotal) {
System.out.println("You drew with " + ene1.name + " Play again and Win!");
}
else
{
System.out.println("You were not succesful this time " + ene1.name + " Defeated you by " + (eneTotal - plyrTotal) + " Please Try Again");
}
}
}
Now after this I have a whole lot more code generating random numbers for the players "stats", and the character, and then matching the total values of their stats to determine "a winner" which I would like to put in a separate class. My issue is,
how do I get ene1 in a separate class with the values that are input in the switch statement in the Main class.
Updated to full main method just for clarity
One of the issues you have is that you are assigning Enemy as a subclass of Stats, but with no relation to your characters. So while the enemy has the same attributes of a character, it has no relationship in which to speak to the character. Instead of copying all of these values like name and color, instead make Enemy it's own entity that holds a Stats value, that shares an interface with stats. The enemy can then use that interface to call various methods in the Stats class.
public class Static implements Actions{
// ...
}
public class Enemy implements Actions{
private Static characterType;
}
Also for future reference, could you please design your questions to be more generic? It not only helps those who don't understand the references, but also makes it easier for people who have similar problems to find this.
You can just pass it into a method (or constructor) of that class as you would any other variable or text. I.e.
clo.setOpponent(ene1);
Then have the implementation of setOpponent be like this
class Stats
{
private Stats opponent;
//ALL OF YOUR OTHER CODE AND METHODS GO HERE
public void setOpponent(Stats enemy)
{
opponent = enemy;
}
}
This doesn't take into account the poor OO design of your application, it only answers your question. Better design comes with more practice and some studying (look up IS-A and HAS-A relationships to help with basic OO design)
In your particular example I would suggest to have Enumerations for the enemies, instead of using class hierarchy, as you have got the same fields for all enemy entities and you're not using any external storage here (like DB, file or whatever).
Class hierarchies are more suitable for situations, when you have several entities which have got both similarities and distinguishes. For example, you can have one class for regular enemies, and one class for 'enforced' enemies with some superskills, so the second class will inherit the first one and will have 1 additional field. This allows you to reduce the code duplicates and provides enough flexibility. Also, class hierarchy gives you some more benefits when you want to save this entities in some storage, for example, DB.
But in you case, it is more logical to use a single Enum to have some set of enemies, which is 'hardcoded' to the application. I would suggest the next solution:
public enum Enemy {
CLOUD("Cloud", "Red", "Sword", 10),
SQUALL("Cloud", "Black", "Minigun", 999)
// and so on
;
public String name;
public String hairColor;
public String wep;
public int skill;
Enemy(String name, String hairColor, String wep, int skill /* and so on */) {
this.name = name;
this.hairColor = hairColor;
this.wep = wep;
this.skill = skill;
}
public static Enemy getByName(String name) {
for (Enemy enemy : Enemy.values()) {
if (enemy.name.equalsIgnoreCase(name)) {
return enemy;
}
}
throw new IllegalArgumentException("Enemy with the name `" + name + "` doesn't exist.");
}
}
And then it is possible to initialize an enemy in the main class by its key name:
String versus = GetInput.getInput("\nWhich of these Characters would you like to go up against?");
try {
Enemy enemy = Enemy.getByName(versus);
} catch (IllegalArgumentException e) { // processing incorrect input
System.out.println(e.getMessage());
}
Then you can pass this constant to any other class to process it and calculate whatever you want:
public class FightCalculator {
public int calculateScore(Enemy enemy) {
// Some calculations here...
}
}
It might help to create separate Hero and Enemy classes. Or if your characters aren't "good" or "bad" guys, perhaps just a Character class. For the following discussion, I will simply use Character, but you can replace this with Hero or Enemy and it should still make sense.
First of all, what is the relationship between a Character and a Stats. I think a Characater has a Stats. This means that Character should have a member variable of type Stats:
class Character {
private Stats stats = new Stats();
}
Now you can add a constructor that a new Stats object for a Character. This means that the Character needs to take several parameters for each of the values stored in a Stats. One advantage of this approach is that you write the code to set up a Stats object just once and then each case statement has just 1 line:
ene1 = new Character(/* all the stats values go here */);
The moral of the story here is that when you find yourself repeating code, you should consider writing a method which encapsulates that repetition.
Okay to make this clearer this is what i need done to my entire program. I need main to restore any calculators that are in the file "calc.bak" before presenting the user with a menu and main should save all calculators that exist in that same file (overwrite as appropriate) just before exiting. I also need to give the user the option to create a brand new calculator, name it, and add a function to it from an already existing collection (which are my Add, multiply, and divide). I also need the user to create their own function by designing and naming a combination of any pair of functions. The ouput of the first function would necessarily be input to the second function. For example, the user can create a new function called "addmult" that calls the add function (which prompts for two numbers and adds them) and establishes the sum as one of the operands for the multiply function (which would have to prompt for its second operand).
The sample out put should look like this:
Welcome to the Calculator Configurator
restore a calculator from a file
create a calculator from scratch
let me create a calculator you can use
2
OK. so you want to create one yourself.
What is the name of your calculator? Fred
Indicate which functions from our stock you'd like to add to your calculator (enter 0 to quit this menu):
Add(1)
Multiply(2)
Divide(3)
Pair of functions(4)
input (2)
Indicate which functions from our stock you'd like to add to your calculator (enter 0 to quit this menu):
Add
Multiply
Divide
Pair of functions
1
Indicate which functions from our stock you'd like to add to your calculator (enter 0 to quit this menu):
Add
Multiply
Divide
Pair of functions
4
Provide a name for this pair:
BothAddAndMult
Provide a description for this pair:
multiplies and then adds
Which function should be first?
Multiply(0)
Add(1)
0
Which function should be first?
Multiply
Add
1
Indicate which functions from our stock you'd like to add to your calculator (enter 0 to quit this menu):
Add
Multiply
Divide
Pair of functions
4
Provide a name for this pair:
MultAfter
Provide a description for this pair: multiplies last after a multiply and add
Which function should be first?
Multiply
Add
BothAddAndMult
2
Which function should be first?
Multiply
Add
BothAddAndMult
Indicate which functions from our stock you'd like to add to your calculator (enter 0 to quit this menu):
Add
Multiply
Divide
Pair of functions
0
I am a calculator named Fred
quit
clear memory
multiply two numbers
add two numbers
multiplies and then adds
multiplies last after a multiply and add
Can someone help me reach this output?
Here is my code so far
CalcConfig.java
import java.util.Scanner;
// program to model a configurable calculator
public class CalcConfig {
public static void main(String [] args)
{
System.out.println("Welcome to the Calculator Configurator");
Scanner kbd = new Scanner(System.in);
CalcFunction [] funs = {
new Add(kbd, "add two numbers"),
new Multiply(kbd, "Multiply two numbers"),
new Divide(kbd, "divide two numbers")};
Calculator calc = new Calculator(funs);
calc.go(kbd);
}
}
Calculator.java
//my Calculator class
import java.util.Scanner;
// models a configurable calcuator
public class Calculator {
private CalcFunction [] functions;
private double memory = 0;
private boolean clear = true;
public Calculator(CalcFunction [] functions)
{
this.functions = functions;
}
public void go(Scanner kbd)
{
int choice = 0;
do
{
System.out.println(this);
choice = kbd.nextInt();
if (choice == 0) return; // choice is to quit
if (choice == 1)
{
clear = true;
continue;
}
if (choice < 0 || choice >= 5)
{
System.out.println("error");
continue;
}
if (!clear)
{
System.out.print("use memory [" + memory + "] (y or n)? ");
String ans = kbd.next();
if (ans.equals("n")) clear = true;
}
if (clear)
memory = functions[choice-2].doit();
else
memory = functions[choice-2].doit(memory);
clear = false;
System.out.println(memory);
} while(choice != 0);
}
public String toString()
{
String out = "0. quit\n1. clear memory\n";
for (int i=0; i<functions.length; i++)
out += (i+2) + ". " + functions[i] + "\n";
return out;
}
}
CalcFunction.java
//my CalcFunction class
import java.util.Scanner;
// generic class to model a function in a calculator
public abstract class CalcFunction {
private Scanner kbd;
private String description;
public CalcFunction(Scanner kbd, String description)
{
this.kbd = kbd;
this.description = description;
}
public abstract double doit();
public abstract double doit(double memory);
// get a string from the user
protected String getString(String prompt)
{
System.out.print(prompt);
return kbd.next();
}
// get a number from the user
protected double getNum(String prompt)
{
System.out.print(prompt);
while(!kbd.hasNextDouble())
{
System.out.print("Invalid: need a number: ");
kbd.next(); // discard invalid input
}
return kbd.nextDouble();
}
public String toString()
{
return description;
}
}
Add.java
//just one of my functions(Add)
import java.util.Scanner;
// class to encapsulate adding two numbers
public class Add extends CalcFunction {
public Add(Scanner kbd, String description)
{
super(kbd, description);
}
public double doit()
{
double n1 = this.getNum("Enter a number: ");
return this.doit(n1);
}
public double doit(double first)
{
double n2 = this.getNum("Enter a second number: ");
double answer = first + n2;
return answer;
}
}
Please help if you can. Thanks!
Pseudo-code:
// 1 maps to add, 2 to subtract, etc
while(cur_func = scanner.read != sentinal value) {
switch(cur_func) {
1:
//toss add into the functions set
break
.
.
.
}
}
toArray your set and build the calc
If you want the user to be able to dynamically add calculator functions to a calculator, then you will need something like this:
public void addCalcFunction(CalcFunction newCalcFunction) {
this.functions.add(newCalcFunction);
}
...but that will require this.functions to be modified to a Collection<CalcFunction>
If you want the user to refer to these functions by name, then you'll need to map them:
private Map<String, CalcFunction> functions;
...
public void addCalcFunction(String functionName, CalcFunction newCalcFunction) {
this.functions.put(functionName, newCalcFunction);
}
Using a Map will require you to make further changes, but I'm sure you can figure those out.
I'm trying some Java recently and look for some review of my style. If You like to look at this exercise placed in the image, and tell me if my style is good enought? Or maybe it is not good enought, so You can tell me on what aspect I should work more, so You can help me to improve it?
exercise for my question
/*
* File: MathQuiz.java
*
* This program produces Math Quiz.
*/
import acm.program.*;
import acm.util.*;
public class MathQuiz extends ConsoleProgram {
/* Class constants for Quiz settings. */
private static final int CHANCES = 3;
private static final int QUESTIONS = 5;
private static final int MIN = 0;
private static final int MAX = 20;
/* Start program. Number of questions to ask is assigned here. */
public void run() {
println("Welcome to Math Quiz");
while(answered != QUESTIONS) {
produceNumbers();
askForAnswer();
}
println("End of program.");
}
/* Ask for answer, and check them. Number of chances includes
* first one, where user is asked for reply. */
private void askForAnswer() {
int answer = -1;
if(type)
answer = readInt("What is " + x + "+" + y + "?");
else
answer = readInt("What is " + x + "-" + y + "?");
for(int i = 1; i < CHANCES+1; i++) {
if(answer != solution) {
if(i == CHANCES) {
println("No. The answer is " + solution + ".");
break;
}
answer = readInt("That's incorrect - try a different answer: ");
} else {
println("That's the answer!");
break;
}
}
answered++;
}
/* Produces type and two numbers until they qualify. */
private void produceNumbers() {
produceType();
produceFirst();
produceSecond();
if(type)
while(x+y >= MAX) {
produceFirst();
produceSecond();
}
else
while(x-y <= MIN) {
produceFirst();
produceSecond();
}
calculateSolution();
}
/* Calculates equation solution. */
private void calculateSolution() {
if(type) solution = x + y;
else solution = x - y;
}
/* Type of the equation. True is from plus, false is for minus. */
private void produceType() {
type = rgen.nextBoolean();
}
/* Produces first number. */
private void produceFirst() {
x = rgen.nextInt(0, 20);
}
/* Produces second number. */
private void produceSecond() {
y = rgen.nextInt(0, 20);
}
/* Class variables for numbers and type of the equation. */
private static boolean type;
private static int x;
private static int y;
/* Class variables for equation solution. */
private static int solution;
/* Class variable counting number of answered equations,
* so if it reaches number of provided questions, it ends */
private static int answered = 0;
/* Random generator constructor. */
RandomGenerator rgen = new RandomGenerator();
}
One thing I noticed was that all of your methods take no parameters and return void.
I think it would be clearer if you use method parameters and return values to show the flow of data through your program instead of using the object's state to store everything.
There are a few things you should do differently, and a couple you could do differently.
The things you should do differently:
Keep all fields together.
static fields should always be in THIS_FORM
you've used the static modifier for what clearly look like instance fields. (type,x,y,solution, answered). This means you can only ever run one MathsQuiz at a time per JVM. Not a big deal in this case, but will cause problems for more complex programs.
produceFirst and produceSecond use hardcoded parameters to nextInt rather than using MAX and MIN as provided by the class
There is no apparent need for answered to be a field. It could easily be a local variable in run.
Things you should do differently:
There is a small possibility (however tiny), that produceNumbers might not end. Instead of producing two random numbers and hoping they work. Produce one random number and then constrain the second so that a solution will always be formed. eg. say we are doing and addition and x is 6 and max is 20. We know that y cannot be larger than 14. So instead of trying nextInt(0,20), you could do nextInt(0,14) and be assured that you would get a feasible question.
For loop isn't really the right construct for askForAnswer as the desired behaviour is to ask for an answer CHANCES number of times or until a correct answer is received, whichever comes first. A for loop is usually used when you wish to do something a set number of times. Indeed the while loop in run is a good candidate for a for loop. A sample while loop might look like:
int i = 1;
boolean correct = (solution == readInt("What is " + x + "+" + y + "?"));
while (i < CHANCES && !correct) {
correct = (solution == readInt("Wrong, try again."));
i++;
}
if (correct) {
println("Well done!");
} else {
println("Nope, the answer is: "+solution);
}
Looks like a very clean program style. I would move all variables to the top instead of having some at the bottom, but other than that it is very readable.
Here is something I'd improve: the boolean type that is used to indicate whether we have an addition or subtraction:
private void produceType() {
type = rgen.nextBoolean();
}
produceType tells, that something is generated and I'd expect something to be returned. And I'd define enums to represent the type of the quiz. Here's my suggestion:
private QuizType produceType() {
boolean type = rgen.nextBoolean();
if (type == true)
return QuizType.PLUS;
else
return QuizType.MINUS;
}
The enum is defined like this:
public enum QuizType { PLUS, MINUS }
Almost good I have only a few improvements:
variables moves to the top
Inside produceNumbers and your while you have small repeat. I recommend refactor this
Small advice: Code should be like books - easy readable - in your run() method firstly you call produceNumber and then askForAnswer. So it will be better if in your code you will have the same order in definitions, so implementation askForAnswer before produceNumber. But it isn't necessary
Pay attention to have small methods. A method shouldn't have much to do - I think that askForAnswer you could split to two methods