Break label in switch

2019-02-23 22:27发布

问题:

Edited: Thank you all for your help. I was able to get it working using the the skills I learned in the previous chapters and your advice. Thank you so much!

I decided to try cementing the things I have learned from Java: A Beginner's Guide by creating a simple text adventure. I am about to start Chapter 4 which involves classes and methods. The first three chapters have dealt with, if, for, while, do-while, switch, simple keyboard interaction, and break/continue.

I plan on going back after every chapter and editing it to use the new skills that I have learned. I have barely scratched the surface and I am running into a problem.

// A basic, but hopefully, lengthy text adventure.

class TextAdventure
{
    public static void main(String args[])
    throws java.io.IOException
    {
        System.out.println("\t\t BASIC TEXT ADVENTURE");


        // variables I need, attributes, classes, character name, player's choice, gold
        int str = 0, inte = 0, chr = 0, con = 0, dex = 0, gold;
        char charName, choice;

        System.out.println("Welcome player! You are about to embark upon a quest in the form of a text adventure.");
        System.out.println("You will make choices, fight monsters, and seek treasure. Come back victorious and you");
        System.out.println("could quite possibly buy your way into nobility!");
        System.out.println();


caseChoice: {       
        System.out.println("Please select your class:");
        System.out.println("1. Warrior");
        System.out.println("2. Mage");
        System.out.println("3. Rogue");
        System.out.println("4. Archer");

        choice = (char) System.in.read(); // Get players choice of class



        switch(choice)
        {
        case '1': 
            System.out.println("You have chosen the Warrior class!");
            System.out.println("You're stats are as followed:");
            System.out.println("Str: 16");
            System.out.println("Int: 11");
            System.out.println("Chr: 14");
            System.out.println("Con: 15");
            System.out.println("Dex: 9");
            str = 16; 
            inte = 11;
            chr = 14;
            con = 15;
            dex = 9;
            break;

        case '2':
            System.out.println("You have chosen the Mage class!");
            System.out.println("You're stats are as followed:");
            System.out.println("Str: 16");
            System.out.println("Int: 11");
            System.out.println("Chr: 14");
            System.out.println("Con: 15");
            System.out.println("Dex: 9");
            str = 9; 
            inte = 16;
            chr = 14;
            con = 15;
            dex = 11;
            break;

        case '3':
            System.out.println("You have chosen the Rogue class!");
            System.out.println("You're stats are as followed:");
            System.out.println("Str: 16");
            System.out.println("Int: 11");
            System.out.println("Chr: 14");
            System.out.println("Con: 15");
            System.out.println("Dex: 9");
            str = 15; 
            inte = 11;
            chr = 14;
            con = 9;
            dex = 16;
            break;

        case '4':
            System.out.println("You have chosen the Archer class!");
            System.out.println("You're stats are as followed:");
            System.out.println("Str: 16");
            System.out.println("Int: 11");
            System.out.println("Chr: 14");
            System.out.println("Con: 15");
            System.out.println("Dex: 9");
            str = 9; 
            inte = 11;
            chr = 14;
            con = 15;
            dex = 16;
            break;

            default:
                System.out.println("Not a valid choice, please enter a digit 1-4");
                break caseChoice;

        }

}

    }
}

The intent of the default statement in the switch is to bring the flow of code back to the class choice. I DO NOT receive a compile error or run time error. When you select anything besides 1, 2, 3, or 4. It says " Not a valid choice, please enter a digit 1-4" like it's suppose to, but the program ends.

Am I not allowed to use a label like that in a switch? Or does it not work because it's technically outside the block of code?

回答1:

I believe that what you are describing in your problem is some kind of goto functionality and that is not how labels in Java works.

Java unfortunately supports labels. This is described in this article from Oracle.

So, basically you can have loops with labels and you can use keyword continue, break and so on to control the flow of the loop.

The following sample illustrates how to use the loop with the break keyword. When break is invoked it terminates the labeled statement i.e. the statement following someLabel. It does NOT go back to execute where the label was specified.

someLabel:
    for (i = 0; i < 100; i++) {
        for (j = 0; j < 100; j++) {
            if (i % 20 == 0) {
                break someLabel;
            }
        }
    }

The continue keyword handles labels the same way. When you invoke e.g. continue someLabel; the outer loop will be continued.

As per this SO-question you can also do constructs like this:

BlockSegment:
if (conditionIsTrue) {
    doSomeProcessing ();
    if (resultOfProcessingIsFalse()) break BlockSegment;
    otherwiseDoSomeMoreProcessing();
    // These lines get skipped if the break statement
    // above gets executed
}
// This is where you resume execution after the break
anotherStatement();

So, basically what happens if you break to a label in your switch you will break that entire statement (and not jump to the beginning of the statement).

You can test labels further by running the program below. It breaks the while-loop if you enter "quit", otherwise it simply breaks the switch.

public static void main(String... args) {
    programLoop:
    {
        while (true) {
            Scanner scanner = new Scanner(System.in);
            final String input = scanner.next();
            switch (input) {
                case "quit":
                    break programLoop; // breaks the while-loop
                default:
                    break; // break the switch
            }
            System.out.println("After the switch");
        }
    }
}

Personally, it would take a very special case in order for me to ever recommend using labels. I find that the code gets easier to follow if you instead rearrange your code so that labels are not needed (by e.g. break out complex code to smaller functions).



回答2:

You can enclose the code in a while loop as follows to achieve the task:

boolean validChoice=false;
while(!validChoice){
switch(choice){
    case 1:
        //logic
        validChoice=true;
    case 2:
        //logic
        validChoice=true;
    case 3:
        //logic
        validChoice=true;
    default:
        //print "invalid choice" and ask to reenter

}


回答3:

I think that using label combined to the break statement put you on the wrong way. You can simply use the break statement in the switch and if you want to avoid the program exit, simply use a while. Below the updated code.

// A basic, but hopefully, lengthy text adventure.

import java.util.Scanner;

class TextAdventure
{
    public static void main(String args[])
    {
        System.out.println("\t\t BASIC TEXT ADVENTURE");


        // variables I need, attributes, classes, character name, player's choice, gold
        int str = 0, inte = 0, chr = 0, con = 0, dex = 0, gold;
        char charName, choice;

        System.out.println("Welcome player! You are about to embark upon a quest in the form of a text adventure.");
        System.out.println("You will make choices, fight monsters, and seek treasure. Come back victorious and you");
        System.out.println("could quite possibly buy your way into nobility!");
        System.out.println();

        boolean toEnd = false;
        while(!toEnd) {

            {
                System.out.println("Please select your class:");
                System.out.println("1. Warrior");
                System.out.println("2. Mage");
                System.out.println("3. Rogue");
                System.out.println("4. Archer");

                Scanner scanner = new Scanner(System.in);
                choice = scanner.next().charAt(0); // Get players choice of class

                toEnd = true;

                switch (choice) {
                    case '1':
                        System.out.println("You have chosen the Warrior class!");
                        System.out.println("You're stats are as followed:");
                        System.out.println("Str: 16");
                        System.out.println("Int: 11");
                        System.out.println("Chr: 14");
                        System.out.println("Con: 15");
                        System.out.println("Dex: 9");
                        str = 16;
                        inte = 11;
                        chr = 14;
                        con = 15;
                        dex = 9;

                        break;

                    case '2':
                        System.out.println("You have chosen the Mage class!");
                        System.out.println("You're stats are as followed:");
                        System.out.println("Str: 16");
                        System.out.println("Int: 11");
                        System.out.println("Chr: 14");
                        System.out.println("Con: 15");
                        System.out.println("Dex: 9");
                        str = 9;
                        inte = 16;
                        chr = 14;
                        con = 15;
                        dex = 11;

                        break;

                    case '3':
                        System.out.println("You have chosen the Rogue class!");
                        System.out.println("You're stats are as followed:");
                        System.out.println("Str: 16");
                        System.out.println("Int: 11");
                        System.out.println("Chr: 14");
                        System.out.println("Con: 15");
                        System.out.println("Dex: 9");
                        str = 15;
                        inte = 11;
                        chr = 14;
                        con = 9;
                        dex = 16;

                        break;

                    case '4':
                        System.out.println("You have chosen the Archer class!");
                        System.out.println("You're stats are as followed:");
                        System.out.println("Str: 16");
                        System.out.println("Int: 11");
                        System.out.println("Chr: 14");
                        System.out.println("Con: 15");
                        System.out.println("Dex: 9");
                        str = 9;
                        inte = 11;
                        chr = 14;
                        con = 15;
                        dex = 16;

                        break;

                    default:
                        System.out.println("Not a valid choice, please enter a digit 1-4");
                        toEnd = false;
                        break;// caseChoice;

                }

            }
        }

    }
}

Using label in Java is allowed but not a good practice. One more think, avoid to use unnecessary exception like IOException since is not thrown by your code.