How to clean up code with too many if/else java - java

I am making something right now that gives you an item based on a command and it's input.
If the command is
/item mythical destroyer or /item mythical 1 (an ID system)
it gives you a destroyer item (arbitrary, don't worry about the specifics).
Looking at other questions, they all have to do with enums, but what I am looking for is how to do it with integers and strings.
Here is what I am doing right now:
interface MythicalItem {
ItemStack getItem();
int getPrice();
void setPrice(int var1);
int getID();
}
class DestroyerMI implements MythicalItem {
private int price = 50;
int getID(){
return 1;
}
void setPrice(int var1){
this.price = var1;
}
int getPrice(){
return price;
}
Item getItem(){
Item item = new Item()
return item;
}
}
class MythicalUtil{
public static ItemStack parseItem(MythicalItem mythicalItem){
return mythicalItem.getItem();
}
public static int parseID(MythicalItem mythicalItem){
return mythicalItem.getID();
}
public static int parsePrice(MythicalItem mythicalItem){
return mythicalItem.getPrice();
}
}
My problem arises right here, and it doesn't seem like there is a way to get the mythical item by name/id without a giant switch or if/else, which I am trying to prevent.
// String[] args = {"mythical", "destroyer"};
if(args[0].equalsIgnoreCase("mythical")){
// I know it is supposed to be Integer.parseInt(args[1]), but dont worry about that please.
if(args[1].equals("1") || args[1].equalsIgnoreCase("destroyer")){
player.giveItem(MythicalUtil.parseItem(new DestroyerItem()));
}else if(args[1].equalsIgnoreCase("shooter"){
plaer.giveItem(MythicalUtil.parseItem(new ShooterItem()));
}else if(...
}
I want to make a method that can return the item to me without spaghettifying my code.

If you really need to do all of that on Strings and Integers and you don't want to refactor all the code you already have but that particular part only, you can try to use switch case
String appropriateNameForArg0 = args[0].toUpperCase();
String appropriateNameForArg1 = args[1].toUpperCase();
if (appropriateNameForArg0.equals("MYTHICAL")) {
switch (appropriateNameForArg1) {
case "1":
case "DESTROYER":
player.giveItem(MythicalUtil.parseItem(new DestroyerItem()));
break;
case "SHOOTER":
plaer.giveItem(MythicalUtil.parseItem(new ShooterItem()));
break;
case "...":
// some other action here
default:
// here you have a place for actions which will be triggered if appropriateNameForArg1 will not meet any of the defined cases
break;
}
}

Related

using Java switch statement return null but not the expected outcome

public class Phone {
private String Band;
double price;
String Category;
void setPrice(double newPrice)
{
price = newPrice;
}
double getPrice(){
return price;
}
void setBand(String newBand)
{
Band = newBand;
}
String getBand(){
return Band;
}
void setCategory(String newCategory){
Category = newCategory;
}
String getCategory()
{
return Category;
}
public String Category(double price){
switch(price){
case 1:
if (price>=8000){
Category= "Expensive";
break;
}
case 2:
if(price>=5000 && size<7000){
Category = "Normal";
break;
}
default:
Category = "Cheap";
}
return Category;
}
}
public class TestPhone{
public static void main (String[]args){
Phone PhoneN = new Phone();
PhoneN.setPrice=6500;
System.out.println(PhoneA.getCategory());
}
}
However, the result is null. (when I run the TestPhone class)
Actually , it should be "Normal".
What did I set wrongly in the code?
I just try to use the getter and setter method, and try to apply in the Category also.
Or is it Is this the problem of the data type of price?
Is this the problem of operator?
What's the problem?
Can anyone help me?
Thanks a lot.
Please learn how switch statement works. You can learn from here: Switch in Java
You're passing price in switch(price) but comparing with 1, 2, 3,etc. Here is the problem.
switch-case are always denotes equal. Your program is working like:
if(price == 1) {
if (price>=8000){
Category= "Expensive";
} else if(price == 2) {
if(price>=5000 && size<7000){
Category = "Normal";
} else {
Category = "Cheap";
}
switch is can't be used in this case. Use if else instead.
There are several things wrong with your code.
It doesn't compile because you cannot have a switch statement over double values - the value must be either char, byte, short, int, Character, Byte, Short, Integer, String, or an enum - you can fix this by declaring the method as public String Category(int price) {}
Then the switch statement tries to use an undefined symbol size - probably you meant to use price there?
In the main method you write PhoneN.setPrice=6500;, but the Phone class has no field setPrice - you probably wanted to write PhoneN.setPrice(6500);
the next line is System.out.println(PhoneA.getCategory()); - here again, the symbol PhoneA is never declared, you probably meant System.out.println(PhoneN.getCategory());
Fixing all these points you still have the problem that #philoopher97 mentions in his answer: in the switch-case the statements after case 1: are executed when price is 1, which means that the condition price >= 8000 cannot be fulfilled, similar for case 2:
This leads to the last problem: your code never calls the setCategory() or the Category() method and that means that the Category field of the PhoneN object is never set to anything but null.

How to change from Constructors to Enum in java?

I have these integers and this method which uses constructors but I am supposed to change this into an Enum since thise code is outdated. I do understand how Enums work in theory but no matter what I try to change I do it wrong.
public static final int CHILDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;
private Price price;
public void setPriceCode(int priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
I thaught that to change to enums I should first delete the given integers at the top and then add this before the method:
enum cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
And now I do not know how to change the method's code accordingly.
How do I give the cases the integers, should I not delete these: ?
public static final int CHILDRENS = 2;
How should I change my switch case accordingly?
Would really appreciate some help, I watched a bunch of videos on enums but the cases were very different.
Do it like this:
enum PriceCode {
REGULAR(0), // calls constructor with value 0
NEW_RELEASE(1), // calls constructor with value 1
CHILDREN(2) // calls constructor with value 2
;
private final int priceCode;
private PriceCode(int priceCode) {
this.priceCode = priceCode;
}
int value() {
return priceCode;
}
}
public class Main {
// Usage
public static void setPriceCode(PriceCode priceCode) {
System.out.println("The value of " + priceCode + " is " + priceCode.value());
switch (priceCode) {
case REGULAR:
// Do something
break;
case CHILDREN:
// Do something
break;
case NEW_RELEASE:
// Do something
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
public static void main(String[] args) {
// Set price code as CHILDREN
setPriceCode(PriceCode.CHILDREN);
// Another sample usage
System.out.println("Price code of NEW_RELEASE is " + PriceCode.NEW_RELEASE.value());
}
}
Output:
The value of CHILDREN is 2
Price code of NEW_RELEASE is 1
Learn more about enum and enum constructor at Java tutorial by Oracle.
Think of an enum as a class or interface, in other words it is a type. I recommend the following tutorial: Enum Types And according to java coding conventions, names of types should begin with a capital letter. Therefore, in the below code, I changed the name of the enum to Cases.
Hence the parameter to method setPriceCode should be Cases. The rest of the code remains the same.
enum Cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
private Price price;
public void setPriceCode(Cases priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
Here is an example call to method setPriceCode()
setPriceCode(Cases.CHILDRENS);

The method x is unidentified for type y

So I am trying to get a random word from a list of words in a Class called Lexicon.
public abstract class Lexicon {
public String getWord(int index) {
switch (index) {
case 0: return "UNIVERSITY";
case 1: return "COMPUTER";
case 2: return "LAPTOP";
case 3: return "HEADPHONES";
case 4: return "FUZZY";
case 5: return "HOTEL";
case 6: return "KEYHOLE";
case 7: return "TELEPHONE";
case 8: return "PRINTER";
case 9: return "BUILDING";
default: return "Illegal index";
}
};
}
To a class called Game :
import java.util.Random;
public class Game {
private int MaxGuess;
private boolean GameOver;
private String RandomWord;
public Game(int maxGuess, boolean gameOver, Lexicon randomWord) {
super();
MaxGuess = maxGuess;
GameOver = gameOver;
Random rand = new Random();
int n = rand.nextInt(9);
RandomWord=getWord(n);
}
public void Result(boolean GameOver) {
if(GameOver) {
System.out.println("You have won the game!!");
}
else {
System.out.println("You Lost!!");
}
}
}
and I get an error that says Method getWord(int) is unidentified for type Game.
It must be something really simple but I cannot get myself to find the mistake. Been trying for like an hour.My java skills got rusty through out Summer. Any help would be appreciated.Thank you in advance.
Two problems are needed to be addressed,
The nextInt function will never get 0-9, but 0-8, please changed this line
int n = rand.nextInt(9);
to
int n = rand.nextInt(10);
The getWord() is not defined in Game Class. You should be calling from the Lexicon Class. And i recommend you to change it to static. which is changed from
public String getWord(int index) {
to
public static String getWord(int index) {
So you can call the function directly with
RandomWord = Lexicon.getWord(n);
In this way, you saved performance and also have the proper way to implement a function as static logic should always be implemented this way.
*Remark: not related to compiling or bugs, but for you variable naming:
private int MaxGuess;
private boolean GameOver;
private String RandomWord;
unless you should always begin with small letter following smallCamelToe convention, some examples are as follow:
//variable
private int maxGuess;
private boolean gameOver;
private String randomWord;
//constant variable
private final int MAX_GUESS = 1;
//static constant variable, usually be used when implementing constant files and import from other classes
public static final boolean GAME_OVER;
and it is ok to implement the following:
public Game(int maxGuess, boolean gameOver) {
super();
maxGuess = maxGuess; //you can use this.maxGuess if compile failed
gameOver = gameOver; //you can use this.gameOver if compile failed
Random rand = new Random();
RandomWord = Lexicon.getWord(rand.nextInt(9));
}
Because getWord() is defined in class Lexicon and not in class Game .
You need game to extend Lexicon if you wish it to inherit the functions
public class Game extends Lexicon {
...
}
Or use the Lexicon you have:
RandomWord=randomWord.getWord(n);
The function getWord is in a different class. You can either copy the method into the game class or try to call Lexicon.getWord() instead
Well, you should do RandomWord = randomWord.getWord(n), not just RandomWord=getWord(n).
In any case it is not clear to my why you do it in this way. The lexicon can be just a list of strings instead of a switch statements hidden inside a class (and an abstract one!)

how can I improve my code for this task

I am newbie to object orientated programming and trying to construct something which resembles a basic vote counter which should take an int parameter that represents a choice of two candidates and print the election results to the terminal window. albeit (the votes attributable to each candidate and the total votes cast)
The method I am looking for should also return a string that gives information on the success or failure of casting the vote.”your vote has been cast” “invalid choice, no vote cast"
I have created a class and the constructors and also implemented some basic get methods.
I am wondering how I should go about achieving this objective albeit through a conditional statement or using some sort of advanced method.
any help in terms of the syntax or wider approach would be appreciated.
public class VoteCounter {
private String candidate1;
private String candidate2;
private int candidate1Votes;
private int candidate2Votes;
private boolean completed;
public VoteCounter(String candidate1, String candidate2) {
this.candidate1 = candidate1;
this.candidate2 = candidate2;
this.candidate1Votes = 0;
this.candidate2Votes = 0;
this.completed = false;
}
public VoteCounter() {
this("CANDIDATE 1", "CANDIDATE 2");
}
public String getCandidate1 () {
return this.candidate1;
}
public String getCandidate2 () {
return this.candidate2;
}
public Boolean getCompleted () {
return this.completed;
}
public void setCompleted (boolean completed) {
this.completed = completed;
}
}
Something like this?
private String vote(int choice)
{
if(choice == 1)
{
candidate1Votes++;
}
else if(choice == 2)
{
candidate2Votes++;
}
else
{
return "invalid choice, no vote cast";
}
return "your vote has been cast";
}
I would do that in more general manner, avoiding code duplication and allowing to change number of candidates easily.
So let's make a class Vote similar to your VoteCounter but only for one candidate, with following fields:
private String candidate; // init this in constructor
private int candidateVotes; // initially 0, so no need to init
and with vote() method like in other answer but also without a candiadate, so:
public void vote() {
candidateVotes++;
}
Then you can make class VoteCounter which will take any number of candidates and will keep them in Array or Map.
Map<Integer, Vote> votes = new HashMap<>();
then you're creating vote method with choice:
public void vote(int choice) {
votes.get(choice).vote();
}
Then all is left is to iterate through your votes map and find the one with biggest number of votes.

How do I access enum by int or by string

I have the following enum:
public enum Difficulty {
EASY(2), MEDUIM(3), HARD(5), EXTREME(8);
private int length;
Difficulty(int length) {
this.length = length;
}
public int length() {
return length;
}
}
I want to be able to reach the correct enum instance whether I know the number or the name.
For instance, if I have the int 3, I need a simple function that is able to return MEDIUM. And if I have the string extreme I need a simple function that is able to return 8.
By simple, I mean that I don't want to iterate each time or keep a static array inside the enum.
Answer must be in Java, Please. Thanks.
What edits do I need to make to the Difficulty enum structure?
public static Difficulty getByName(String name) {
return valueOf(name.toUpperCase());
}
public static Difficulty getByLength(int length) {
switch (length) {
case 2:
return EASY;
case 3:
return MEDIUM;
case 5:
return HARD;
case 8:
return EXTREME;
default:
throw new IllegalArgumentException("invalid length : " + length);
}
}

Categories

Resources