0

I am trying to make a small game:

  • There are 2 heroes you can choose: 1 Warrior and 2 Mage.

  • Next, you should choose how to travel: 1 by Horse 2 Teleportation (available to Mage only).

  • Finally, choose a weapon: 1 Sword 2 Staff (*Mage can only use Staff; Warrior can use both).

I created a loop for my first question (choosing a hero) so that if the user enters something else aside from 1 or 2, the program will repeat the question ("Choose your hero: ...). I need the same done for my second and third question (especially since there are some restrictions, e. g. if the user chose Warrior, he can't choose Teleportation as his travel option).

public static void main(String[] args) {
    int hero, travel, weapon;
    Scanner scan = new Scanner(System.in);

    loop:
        while (true) {
            System.out.println("Choose your hero: 1 for Warrior, 2 for Mage");
            hero = scan.nextInt();
            switch (hero) {
            case 1:
                System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
                travel = scan.nextInt(); 
                break loop;
            case 2:
                System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
                travel = scan.nextInt(); 
                break loop;
            default:
                break;
            }
        }                       
}

I don't know how to use a loop inside another loop properly. I've tried several options but it always returns an error.

4
  • 1
    Why do you want your new loop to be inside this one? As far as I understand your problem, you could just place it after this one. Commented Jun 18, 2019 at 7:47
  • Do you have to use loops? Using multiple simple methods without any loop would probably be a better solution to that. Commented Jun 18, 2019 at 7:48
  • 1
    A side note: Do not use breaks with labels! Labels of any kind are evil. In a few years of programming I've forgot that they even exist and I hope not to see those any time soon. Why? If you have to use them then your method is probably too complicated anyway, you should come up with some other way to organize your code. Commented Jun 18, 2019 at 7:52
  • 1
    As a style guide suggestion - try not to offer suggestions that are unavailable. There is nothing more infuriating than the scenario you are proposing... think about it like this. Which hero do you want? A) warrior. Then: which transportation? A) teleporter. Then the program effectively says "ha ha you can't do that - bad luck have another go at guessing the correct combination!". But that is just my suggestion - it is after all your game. Also as tip, you probably don't need a while within a while. One while with some ifs will probably work for you. Commented Jun 18, 2019 at 8:00

3 Answers 3

1

It is always a good idea to split things up, instead of making nested loops. Here is a simple way to split the program in 3 methods, each one dealing with a choice.

Hero choice: Offer both choices and loop until given a valid answer. Then return the answer

private static int queryHero() {
    Scanner scan = new Scanner(System.in);
    int hero;
    while (true) {
        System.out.println("Choose your hero: 1 for Warrior, 2 for Mage");
        hero = scan.nextInt();
        if(hero == 1 || hero == 2) {
            break;
        } else {
            System.out.println(hero + " is not a valid choice");
        }
    }
    return hero;
}

Travel option choice: Offer choices depending on the chosen hero and loop until given a valid answer. Then return the answer

private static int queryTravelOptionForHero(int hero) {
    Scanner scan = new Scanner(System.in);
    int travelOption;
    while (true) {
        if (hero == 1) {
            System.out.println("Choose your travel option: 1 for Horse");
            travelOption = scan.nextInt();
            if (travelOption == 1) {
                break;
            } else {
                System.out.println(travelOption + " is not a valid choice");
            }
        } else if (hero == 2) {
            System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
            travelOption = scan.nextInt();
            if (travelOption == 1 || travelOption == 2) {
                break;
            } else {
                System.out.println(travelOption + " is not a valid choice");
            }
        }
    }
    return travelOption;
}

Weapon choice: Offer choices depending on the chosen hero and loop until given a valid answer. Then return the answer

private static int queryWeaponForHero(int hero) {
    Scanner scan = new Scanner(System.in);
    int weapon;
    while (true) {
        if(hero == 1) {
            System.out.println("Choose your weapon: 1 for Sword; 2 for Staff");
            weapon = scan.nextInt();
            if (weapon == 1 || weapon == 2) {
                break;
            } else {
                System.out.println(weapon + " is not a valid choice");
            }
        } else if(hero == 2) {
            System.out.println("Choose your weapon: 2 for Staff");
            weapon = scan.nextInt();
            if(weapon == 2) {
                break;
            }else {
                System.out.println(weapon + " is not a valid choice");
            }
        }

    }
    return weapon;
}

Then in your main:

int hero = queryHero();
int travelOption = queryTravelOptionForHero(hero);
int weapon = queryWeaponForHero(hero);

System.out.println("hero: " + hero);
System.out.println("travelOption: " + travelOption);
System.out.println("weapon: " + weapon);

Note: I am not sure if you know about them, but there are ways to make this code nicer using enums and Lists

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you, this seems to work exactly as I wanted. Unfortunately, I don't know anything about enums and lists, I'm a beginner.
@Felix I assumed so, as the question is beginner level. That is why I wrote it this way. But there is no problem with this solution, it is a correct way to do it.
@Bentaye thank you once again! Could you please also help me with this: if at first, I want the user to enter his name, and then use his name before each phrase (e. g. name + ", choose your hero), should I add a separate method for this? or should I put this into the method queryHero?
you can have a method to query for the name (like queryUserName()), then you can pass the name into each other methods, the same way you pass the hero, the new method signatures would be queryHero(String userName), queryTravelOptionForHero(int hero, String userName) ...
@bentaye It worked perfectly, thank you and best wishes!
1

Your flow can be written as a simple procedural code. As so, I would write it in the most simple form I can - at least as a start.

There is no real justification for using switch labels and loops inside loops

Just write 3 simple loops, one after another - It will be simple to read, understand and debug.

I dont want to write the code for you, it is not the purpose of this site, but here's a Pseudo code:

Loop 1 (selecting heroes)

If(heroes != Warrior)
    Loop 2 (selecting travel)
else travel=Horse

Loop 3 (selecing weapon)

Comments

1

Like the comments suggest i would not go with loops inside loops. Instead you should assign the variables one at the time. I have written a helper method selectVariable(String description, String varOne, String varTwo) that you can use to assign variables and give you a start for your story game. You could expand it if you want to give the user more choices. Also don't give the use the illusion a choice can be made, if there is no choice in that situation.

Here is the code that should do what you want:

import java.util.Scanner;

public class Story {

  static Scanner scan = new Scanner(System.in);

  public static void main(String[] args) {
    int hero = chooseHero();
    int travel = chooseTravel(hero);
    int weapon = chooseWeapon(hero);

    //For printing purposes give your choice their respective string name again. 
    String heroDesc = hero == 1 ? "Warrior" : "Mage";
    String travelDesc = travel == 1 ? "Horse" : "Teleportation";
    String weaponDesc = weapon == 1 ? "Sword" : "Staff";

    System.out.printf("you are a %s, traveling by %s, wielding a %s" + System.lineSeparator(), heroDesc, travelDesc, weaponDesc);
  }

  private static int chooseHero() {
    return selectVariable("choose your hero class", "warrior", "mage");
  }

  private static int chooseTravel(int hero) {
    if (hero == 1) { // if the user has no choice don't give the illusion a choice can be made
      System.out.println("you are a Warrior you will travel by horse");
      return 1;
    } else {
      return selectVariable("choose your way of travel", "by horse", "teleportation");
    }
  }

  private static int chooseWeapon(int hero) {
    if (hero == 2) {
      System.out.println("you are a mage you will wield a staff");
      return 2;
    } else {
      return selectVariable("choose your weapon", "sword", "staff");
    }
  }

  //you can reuse this method to also assign other traits to your story
  private static int selectVariable(String description, String varOne, String varTwo) {
    int var;
    do {
      System.out.printf("%s: 1 %s, 2 for %s" + System.lineSeparator(), description, varOne, varTwo);
      var = scan.nextInt();
      switch (var) {
        case 1:
          System.out.printf("you have chosen %s" + System.lineSeparator(), varOne);
          return var;
        case 2:
          System.out.printf("you have chosen %s" + System.lineSeparator(), varTwo);
          return var;
        default:
          System.out.println(var + " is an invalid choice");
      }
    }
    while (true);
  }
}

2 Comments

thank you so much for your answer! I have a question regarding giving each integer a string name for printing purposes: I have tried to do this for 4 different options (warrior, mage, rogue, and barbarian), but it hasn't worked... does it only work if there are two values?
@Felix in it current state it only works for the two options. If you want four options you have to extend the method or overload the method selectVariable (String description, String varOne, String varTwo). If you want i can edit the answer with another method for four variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.