Reducing duplication in code - java

I currently have multiple code like this for different toppings
// Toppings - Egg
System.out.print("Do you want " + egg.getType() + "?");
input = keyboard.nextLine();
choice = input.charAt(0);
if (choice == 'y') {
l.add(egg.getType());
c.add((double) egg.getCost());
numberOfToppings = numberOfToppings + 1;
totalToppingPrice = totalToppingPrice + egg.getCost();
toppings = toppings + "Egg";
}
It works fine, however i was hoping i could do all toppings in just one block of code. Because i've got around 5 of these, and it takes up far too much, and i've been advised to do so. Anyone got any ideas for how this could be done ? thanks

All the toppings should be gathered together in an enumeration, as long as the topping set is closed and cannot change during the program execution.
enum Topping{
EGG("egg", 22),... ;
private String type;
private double cost;
private Topping(String type, double cost){
this.type = type;
this.cost = cost;
}
//getters and setters
}
Then, you could write a method inside your class containing your code above that should be able to handle a Topping instance, like this:
private handleTopping(Topping top){
System.out.print("Do you want "+top.getType() +"?");
input = keyboard.nextLine();
choice = input.charAt(0);
if (choice == 'y'){
l.add(top.getType());
c.add(top.getCost());
numberOfToppings = numberOfToppings + 1;
totalToppingPrice = totalToppingPrice + top.getCost();
toppings = toppings + " " + top.getType();
}
}
Finally, call the method for all toppings available
for(Topping top : topping.values()){
handleTopping(top);
}
It's all about the DRY (don't repeat yourself principle). It's not even necessarily tied to the object oriented paradigm. Even in procedural programming, one of the core principles is to extract common and frequently used functionalities to parameterized procedures.

I would suggest you make a Topping class that you can use as follows:
Toppping egg = new Topping ("egg", 0.5); // Cost
ArrayList<Topping> toppings = new ArrayList<Topping>();
toppings.add(egg);
Later you can loop over the toppings vector similar to this:
for (Topping current : toppings) {
if (wantsTopping(current)) {
chosenToppings.addObject(current);
}
}
Note: This is Java like code, but it won't compile. There are still some things you need to look up

Related

Pizza price calculating using 'if' statements in java [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 3 years ago.
I've tried to make Java code to communicate with the user.
The code is about calculating a pizza price assuming the pizza price is a final int and doesn't change.
The only thing that affects the price is the add-on that the customer wants on the pizza (tomato, mushrooms, cheddar cheese).
I've tried to create code that covers every option the customer picks using 'if' statements,
but I think there is easier way to do it.
(I want the program to calculate the price given only the add-on name.)
For example, the customer picks Mushroom and Tomato so the pizza price will be the pizza price + tomato price + mushroom price.
Is there any easier way to solve it?
Or should I cover every option the customer picks with if/else statements?
public static void main(String[] args){
Scanner s= new Scanner(System.in);
final int pizzaPrice= 12;
int Mushrooms = 2;
int Tomato= 2;
int Corn = 2;
int Olives = 2;
int CheddarCheese=3;
int bulgaritCheese=3;
int yellowCheese= 3;
String cheapAddOns ="Mushrooms , Tomato, Corn, Olives";
String expensiveAddOns = "Cheddar cheese , Bulgarit cheese , Yellow cheese";
System.out.println("Please enter first AddOns(Mushrooms , Tomato , Corn, Olives): ");
cheapAddOns=s.next();
System.out.println("Please enter second AddOns (Cheddar cheese , Bulgarit cheese ,Yellow cheese)");
expensiveAddOns=s.next();
if( cheapAddOns== "Mushrooms" || expensiveAddOns=="Cheddar cheese" ) {
System.out.println("Your Pizza price is: $" + pizzaPrice + Mushrooms + CheddarCheese );
}
else if (cheapAddOns=="Tomato" || expensiveAddOns=="Bulgarit cheese") {
System.out.println("Your Pizza price is: $" +pizzaPrice+ Tomato + bulgaritCheese);
}
}
First of all when you name your variables, don't start with a capital letter
int mushrooms, not int Mushrooms.
Second thing, when you compare Strings == operator will not work. you must use stringName.equals(). In your case it would look like:
cheapAddOns = s.next();
if(cheapAddOns.equals("tomato") || cheapAddOns.equals("mushrooms") || ...){
//this way you can get one if for all cheap addons;
pizzaPrice += 2; //read below to undrstand why i would add price this way
}
And the same check for expensive addons.
What you do when you initiate cheapAddOns and expensiveAddOns is incorrect, I mean that you initiate them with start variable, and next you read them from standard input. Initiate them with no value:
String cheapAddOns;
String expensiveAddOns;
And for this example, you dont have to use final int, better initiate it as an normal integer, and if any statment is true, add to this value. It would look like this:
int pizzaPrice = 12;
int cheapAddonPrice = 2;
int expensiveAddonPrice = 3;
if(anyStatement){
pizzaPrice += 2; //2 for cheap, 3 for expensiv addon
}
System.out.println("Your pizza costs: $" + pizzaPrice)
It works only when all cheap addons cost $2 and all expensive addons cost $3. If each addon has another price, you will need more if statements to calculate price.
But calculate price in as many statements as you want and print it once (until you print only price (without addons list).
You made a lot of simple mistakes here so i think that you just start your programming adventure. Don't learn bad habbits, try to imporove your code with each day.
if all cheap add-ons have the same price, one way could be:
String cheapAddOns = "Mushrooms, Tomato, ...";
int cheapPrices = 2;
System.out.println("Please enter first AddOns(Mushrooms , Tomato , Corn, Olives): ");
String cheap = s.next();
int price = pizzaPrice;
if ( cheapAddOns.indexOf(cheap) >= 0 ) {
price += cheapPrice;
}
then repeat the code using expensiveAddOns.
Note that you will need to consume the CR before calling s.next() to get the user's next input.

Make a method run in a method java for my game?

I'm struggling with dealing of inventory scan for my game, it basically search for the user inventory if "Flying Broom" if present(it was collected in another method and upload the code is too long), if not it will run the method challengedragon() again; else, it will proceed to the next challenge if the item is present.I was think of inserting method as parameter but it is not possible. This is what I have now. :
public class Main {
String Flyingbroom = "Flying broom";
public static void main(String[] args) {
Player_inventory p = new Player_inventory();
challengedragon();
}
public void challengedragon() {
System.out.println("a Hungarian Horntail dragon! Let's start the battle! You have four options to beat the dragon: ");
System.out.println("1: Fly away with your broom");
System.out.println("2: Fight the dragon");
System.out.println("3: Just run to the egg and get it");
System.out.println("4: Hide behind a rock");
System.out.println("5: Go back to Hogwart");
System.out.println("Your choice is: ");
Scanner in = new Scanner(System.in);
int dragonfightchoice = in .nextInt();
if (dragonfightchoice == 1) {
{
p.Scanitem(Flyingbroom,
"Good choice! You managed to kill the Hungarian Horntail dragon and to get the golden egg",
"You dont have the broom. Try to search for the broom",
playerHP);
proceedtonextchallengelake();
} else if (dragonfightchoice == 2) {
System.out.println("The Hungarian Horntail dragon fired you. - 70HP. ");
playerHP -= 70;
challengedragon();
} else if (dragonfightchoice == 3) {
System.out.println("Bad idea... You lose 100 HP");
playerHP -= 100;
challengedragon();
} else if (dragonfightchoice == 4) {
System.out.println("The dragon found you. You lose 30 HP");
playerHP -= 30;
challengedragon();
} else if (dragonfightchoice == 5) {
Hogwart();
} else {
invalid();
challengedragon();
}
}
For my inventory class:
public void Scanitem(String item, String trueouputext, String textifconditionisnotmet) {
if (inv.contains(item) == true) {
System.out.println(trueouputext);
} else if (inv.contains(item) == false) {
System.out.println(textifconditionisnotmet);
}
public static ArrayList<String> inv = new ArrayList<String>();
Do you guys have any recommendation?
Are there additional steps to populate the inventory (variable inv)?
Also, wouldn't you want ScanItem to answer true or false, depending on whether the item was found? Then you would have something like this:
public boolean scanitem(String item) {
return ( inv.contains(item) );
}
if ( p.scanItem(flyingBroom) ) {
System.out.println("Good choice! You managed to kill the Hungarian Horntail dragon and to get the golden egg");
} else {
System.out.println("You dont have the broom. Try to search for the broom");
}
That will get you closer to what you want. However, there are two other issues which you'll need to put into your code:
You will need a loop of some sort, instead of calling challengeDragon from inside of itself.
Somehow, the return value from scanItem must be used to decide whether to loop.
Currently, you do a nested call of a method each time the player does something, this means that sooner or later you'll run out of the stack. A better idea for the framework for your text-based adventure is to have some kind of a description of the current game's state. The state could be represented as an object that contains the following information:
where's the player currently at (on which step, at which "crossing" etc.)
the player's stats (HP, available skills etc.)
the contents of the player's inventory
some previously made choices affecting the game
Then, the code could be written as a simple loop that does the following:
process player's input
change the state according to the player's input
present the player with available options according to the new state
wait for the next input
repeat

JAVA - Menu running in loop - How can I print out all choices?

I'm trying to learn JAVA and I'm working on a simple pizza order assignment running purely in text/console format.
I've made the user chose a pizza, but they need the option to add extra ingredients.
My thought was to use a for loop to show a toppings menu and then ask for a numbered input matching the ingredient they want to add.
I want them to be able to select several ingredients, why I'm doing it in a loop.
My code as of now looks like this:
for (int i = 0; ingredientInput>0; i++ ){
toppingsMenu();
ingredientInput = ingredientScan.nextInt();
ingredientScan.nextLine();
System.out.println("Type your choice here:");
}
System.out.println(ingredientInput);
Everything works great, but I'd like to add a system.out.println() telling the user, what they've chosen as:
"You've added extra cheese - Would you like to add more?"
If so, I would like to expand that sentence: "You've added extra cheese & pepperoni - Would you like to add more?"
Could you help me by pointing me in a direction that might work? I'm not into any object related part of JAVA yet, purely text-based so far.
Thanks.
Solution provided by Adeel Ahmad
ArrayList<Integer> ingredients = new ArrayList<>();
for (int i = 0; ingredientInput>0; i++ ){
toppingsMenu();
ingredientInput = ingredientScan.nextInt();
ingredientScan.nextLine();
ingredients.add(ingredientInput);
System.out.println("Type your choice here:");
}
System.out.println(ingredientInput);
Looking back it's so interesting to see which problems I struggled to solve, as now, a few months later, this seems so basic. But thanks anyway to everyone who helped :D
First off, you need to be able to store all the added ingredients in data container (e.g ArrayListor HashMap). Whenever user inputs an ingredient, just added that in your ArrayList
ArrayList<Integer> ingredients = new ArrayList<>();
for (int i = 0; ingredientInput>0; i++ ){
toppingsMenu();
ingredientInput = ingredientScan.nextInt();
ingredientScan.nextLine();
ingredients.add(ingredientInput);
System.out.println("Type your choice here:");
}
System.out.println(ingredientInput);
Once you have collected all the user selected ingredients in your ArrayList, you can then iterate over it in a loop and construct your final message.
You could use something like this
String orderedSoFar = "";
boolean done = false;
do {
// read next ingredient from user
String currentIngredient = scanner.nextLine();
// if first extra ingredient
if(orderedSoFar.equals("")){
orderedSoFar += currentIngredient;
// if not first extra ingredient
} else {
orderedSoFar += " & " + currentIngredient;
}
System.out.println("Ingredients so far " + orderedSoFar);
System.out.println("Add more extra ingredients?");
// read choice to continue or not from user
done = Boolean.valueOf(scanner.nextLine());
}while(!done);

Calling a method for calculation [duplicate]

This question already has answers here:
How to get the user input in Java?
(29 answers)
Closed 6 years ago.
So I made a class that is supposed to calculate the number of beers needed to become intoxicated. My class receives User Input for the name of the beer, the alcohol content, and then the user's weight to make the calculation.
Here's my whole Beer class
public class Beer {
private String name;
private double alcoholContent;
//Default apple values (Constructors)
public Beer()
{
this.name = "";
this.alcoholContent = 0.0;
}
//Accessors
public String getName()
{
return this.name;
}
public double getAlcoholContent()
{
return this.alcoholContent;
}
//Mutators
public void setName (String aName)
{
this.name = aName;
}
public void setAlcoholContent (double aAlcoholContent)
{
if (aAlcoholContent < 0 || aAlcoholContent > 1)
{
System.out.println("That is an invalid alcohol content");
return;
}
this.alcoholContent = aAlcoholContent;
}
//Methods
public double Intoxicated (double aWeight)
{
double numberOfDrinks = (0.08 + 0.015) * aWeight / (12 * 7.5 * this.alcoholContent);
return numberOfDrinks;
}
This is specifically my intoxicatedmethod in the class (I think it's right):
public double Intoxicated (double aWeight)
{
double numberOfDrinks = (0.08 + 0.015) * aWeight / (12 * 7.5 * this.alcoholContent);
return numberOfDrinks;
}
This is what the output window is supposed to look like, receiving User Input for the weight and then performing the calculation to see how many beers it would take based on the user's input when previously defining two beers to be considered intoxicated:
What’s the weight of the person consuming said beverages?
185
It would take 3.166 "firstBeerName" beers to become intoxicated.
It would take 1.979 "secondBeerName" beers to become intoxicated.
The intoxicated formula was given to me, I don't know how to properly set up my class testing main method file which calls this class to reflect that output.
You need to write a testing class, that contains a main method. In the main method you can create several Beer-Objects.
By iterating over your Beers, you can get the wanted results.
Look here to get information about how to set up a main method.
Create an Array of Beer-Objects in that method with different alcohol content
Get the user input for the weight and then
Iterate over your Array, call intoxicated() and print the results
You are going to want to create a main method which does the following:
1) Prints the prompt for the beer values (name and % alcohol)
2) Takes in user input for those beer values
3) Prints the prompt for the user's weight
4) Takes in the user input for the weight
5) Calculates and prints the result
For printing prompts, you will most likely want to use System.out.println("Some prompt here!");
For taking input, you will most likely want to use a Scanner. You can search around on this website and others, as well as read the documentation, for how to take input with using that class.
Here is an example of a main method:
public static void main(String[] args) {
Beer blueMoon = new Beer("Blue Moon", 5.4);
Beer hoegaarden = new Beer("Hoegaarden", 4.9);
System.out.println("Enter your weight: ");
Scanner input = new Scanner();
Double weight = input.nextLine();
double value = beer1.Intoxicated(weight);
System.out.println("It would take " + value + " of " + blueMoon.getName() + " to become intoxicated.");
}
I would suggest renaming your Intoxicated method to intoxicated, as method names are generally camelCased in Java.
I am not going to give you the exact code because this seems like homework and I already graduated, but that should be enough to get you started. My advice would be to search around for any specific questions you come up with.
You can write a main method like this:
public static void main(String [ ] args)
{
Beer beer1 = new Beer().
beer1.setName("firstBeerName");
beer1.setAlcoholContent(3.166);
Scanner reader = new Scanner(System.in); // Reading from System.in
System.out.println("What’s the weight of the person consuming said beverages?");
double weight = reader.nextDouble();
double answer = beer1.Intoxicated(weight);
System.out.println("It would take "+answer+" "+beer1.getName()+" beers to become intoxicated.")
// similar for beer2
}
I would encourage you to throw IllegalArgumentException when checking condition in setter:
public void setAlcoholContent(double aAlcoholContent) {
if (aAlcoholContent < 0 || aAlcoholContent > 1) {
throw new IllegalArgumentException("Alcohol content can't be more than 1 or less than 0");
}
this.alcoholContent = aAlcoholContent;
}
And for your question you can test it like this:
public static void main(String[] args) {
List<Beer> beers = new ArrayList<>();
beers.add(new Beer("firstBeerName", 0.04));
beers.add(new Beer("secondBeerName", 0.06));
Scanner reader = new Scanner(System.in);
System.out.println("What’s the weight of the person consuming said beverages?");
double weight = reader.nextDouble();
DecimalFormat decimalFormat = new DecimalFormat("0.000");
for(Beer beer : beers){
System.out.println("It would take " + decimalFormat.format(beer.Intoxicated(weight)) + " " + beer.getName() +" beers to become intoxicated.");
}
}
Also you can use loop for creating new beers, just ask user for amount of beers that he can obtain result for, and then create for loop.

Can't remember how to do this for some reason

This one should be fairly simple I think, I just can't remember how, when using get methods of an object, how to pull the highest double out of the pack and put it in the println.
So far I just get every object to print with its percentages. But for the life of me I just can't remember and I know I've done this before.
public void displayBookWithBiggestPercentageMarkup(){
Collection<Book> books = getCollectionOfItems();
Iterator<Book> it = books.iterator();
while(it.hasNext()){
Book b = it.next();
double percent = b.getSuggestedRetailPriceDollars() / b.getManufacturingPriceDollars() * 100.0;
System.out.println("Highest markup is " + percent + " " + b.getTitle() + " " + b.getAuthor().getName().getLastName());
}
}
I'm pretty sure I need another local variable but I can't seem to do anything but make it equal the other percent. I have removed the other variable for now as I try to think about it.
I won't go into a lot of detail because it's homework (well done for being up-front about that, by the way) but here's the key idea: keep track of the largest percentage you've seen so far as your loop runs. That's what you want in your other variable.
Good job posting what you've tried so far. You were on the right track. As you loop through your books, keep a variables continuously updated with the highest percent seen so far and another variable for the associated book. Output the variable at the end outside the loop after iteration is done. Also, don't forget to check the edge case of an empty list of books! Something like this should do the trick:
public void displayBookWithBiggestPercentageMarkup(){
Collection<Book> books = getCollectionOfItems();
if (books.size() == 0) {
return;
}
Iterator<Book> it = books.iterator();
double highestPercent = 0;
Book highestPercentBook = null;
while(it.hasNext()){
Book b = it.next();
double percent = b.getSuggestedRetailPriceDollars() / b.getManufacturingPriceDollars() * 100.0;
if (percent > highestPercent) {
highestPercent = percent;
highestPercentBook = b;
}
}
System.out.println("Highest markup is " + highestPercent
+ " " + highestPercentBook.getTitle()
+ " " + highestPercentBook.getAuthor().getName().getLastName());
}

Categories