0

我正在制作一个简单的基于文本的游戏。我的类中有一个方法引用同一个类中的另一个方法,但是如果满足某个条件,该方法引用引用它的方法。

因此,基本上,如果角色选择打开菜单,则调用 Character.mainMenu() 方法,并根据所选内容引用 Character.invMenu() 或 Character.statsMenu()。

如果用户选择从 mainMenu() 中选择 Back,则调用另一个名为 backSetter() 的方法。此方法采用当前 x 和 y 坐标并返回位置 ID,以将用户返回到他们打开菜单的任何位置。

在invMenu()等子菜单方法(mainMenu()方法调用的方法)内部,也有返回选项:1.返回和2.主页。Back 选项将用户返回到调用 mainMenu() 方法的主菜单。Home 选项将用户返回到他们打开菜单的位置,调用 backSetter() 方法。然而,问题是,如果我从 invMenu() 方法调用这些方法,它们似乎什么也没做,我的程序就会冻结。

这是我的 Character 类的基本模板(这里引用的其他类是 MainClass,它包含 setLocation() 方法和 GameText 类,它引用了 gameText() 方法)。

class Character{

    static Scanner userInput = new Scanner();
    static String choice;
    static int backChoice = 0;

    public static void backSetter(){
        if (xAxis == 0 && yAxis == 0){
            backChoice = MainClass.setLocation(0,0);
            GameText.gameText(backChoice);
        }else if (xAxis == 0 && yAxis == 1){
            .....
        }
    }

    public static void mainMenu(){
        //My menu options: 1. Inventory, 2. Stats, etc... 5. BACK <- important
        choice = userInput.next();

        if (choice.equals("1")){
            invMenu();
        }else if (choice.equals("5")){
            backSetter();
    }

    public static void invMenu(){
        // Determines current items in inventory and prints them out
        //My menu options: 1. Back, 2. Home <- where the problem happens
        choice = userInput.next();

        if (choice.equals("1")){
            mainMenu();
        }else if (choice.equals("2")){
            backSetter();
        }
    }
}
4

4 回答 4

1

是的,这是合法的——这就是递归方法的含义。确保您没有无限递归的情况,即确保您的方法最终停止相互调用 - 如果递归最终终止,那么您就可以开始了。

于 2013-04-11T02:08:10.007 回答
0

感谢您的帮助,我认为它可能会导致无限循环。是的,如果没有完整的代码,很难发现我哪里出错了。我想将此添加为评论,但字符太多,因此我将其添加为答案。

我一直在研究我的方法,但看不出它是如何陷入无限循环的。调用 Method2 的 Method1 在确定要做什么之前必须接受用户输入。所以如果 Methpd1 调用 Method2,Method2 又调用 Method1,为什么会卡住,因为用户在任何一种方法中都有返回正常游戏的选项。这是我的方法,也许完全看到它可以阐明我哪里出错了。

FantasyGameText.gameText 方法只接受 locID 并输出该位置的对话选项。FantasyGameText.setLocation 方法是设置位置 ID 的实际方法,backSetter 方法只是将它与 gameText 方法结合起来(基本上和我开始游戏的方式相同,xAxis = 0, yAxis = 0,所以 locId = 0,即我游戏的开始部分)。

public static void backSetter(){
    if (xAxis == 2 && yAxis == 1){
        backChoice = setLocation(2, 1);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 4 && yAxis == 1){
        backChoice = setLocation(4, 1);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 2 && yAxis == 2){
        backChoice = setLocation(2, 2);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 3 && yAxis == 2){
        backChoice = setLocation(3, 3);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 4 && yAxis == 2){
        backChoice = setLocation(4, 2);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 5 && yAxis == 2){
        backChoice = setLocation(5, 2);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 1 && yAxis == 3){
        backChoice = setLocation(1, 3);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 2 && yAxis == 3){
        backChoice = setLocation(2, 3);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 3 && yAxis == 3){
        backChoice = setLocation(3, 3);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 4 && yAxis == 3){
        backChoice = setLocation(4, 3);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 2 && yAxis == 4){
        backChoice = setLocation(2, 4);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 3 && yAxis == 4){
        backChoice = setLocation(3, 4);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 4 && yAxis == 4){
        backChoice = setLocation(4, 4);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 5 && yAxis == 4){
        backChoice = setLocation(5, 4);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 3 && yAxis == 5){
        backChoice = setLocation(3, 5);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 4 && yAxis == 5){
        backChoice = setLocation (4, 5);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 30 && yAxis == 30){
        backChoice = setLocation(30, 30);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 31 && yAxis == 31){
        backChoice = setLocation(31, 31);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 50 && yAxis == 50){
        backChoice = setLocation(50, 50);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 51 && yAxis == 51){
        backChoice = setLocation(51, 51);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 52 && yAxis == 52){
        backChoice = setLocation(52, 52);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 53 && yAxis == 53){
        backChoice = setLocation(53, 53);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 54 && yAxis == 54){
        backChoice = setLocation(54, 54);
        FantasyGameText.gameText(backChoice);
    }else if (xAxis == 55 & yAxis == 55){
        backChoice = setLocation(55, 55);
        FantasyGameText.gameText(backChoice);
    }else{
        FantasyGameText.gameText(100);
    }
}

public static void menuHome(){
    boolean correctAnswer = false;
    System.out.println("");
    System.out.println("-------- CHARACTER --------");
    System.out.println("1. Inventory");
    System.out.println("2. Equip");
    System.out.println("3. Stats");
    System.out.println("4. Quests");
    System.out.println("5. Back");
    while (correctAnswer == false){
        menuChoice = userInput.next();
        System.out.println("");
        if (menuChoice.equals("1") || menuChoice.equalsIgnoreCase("inventory") || menuChoice.equalsIgnoreCase("inv")){
            correctAnswer = true;
            invMenu();
        }else if (menuChoice.equals("2") || menuChoice.equalsIgnoreCase("equip")){
            correctAnswer = true;
            equipMenu();
        }else if (menuChoice.equals("3") || menuChoice.equalsIgnoreCase("stats") || menuChoice.equalsIgnoreCase("statistics")){
            correctAnswer = true;
            statsMenu();
        }else if (menuChoice.equals("4") || menuChoice.equalsIgnoreCase("quests") || menuChoice.equalsIgnoreCase("quest")){
            correctAnswer = true;
            questMenu();
        }else if (menuChoice.equals("5") || menuChoice.equalsIgnoreCase("back") || menuChoice.equalsIgnoreCase("home")){
            correctAnswer = true;
            backSetter();
        }else{
            System.out.println("That is not a valid option, choose again,");
            menuChoice = userInput.next();
            System.out.println("");
        }
    }
return;
}

public static void invMenu(){
    boolean correctAnswer = false;
    int invList[] = new int[50];
    int itemAmount[] = new int[50];
    for (int i = 0; i <= 3; i++){
        if (healthPotionAmount > 0){
            invList[0] = 1;
            itemTempName[0] = "Health Potion x ";
            itemAmount[0] = healthPotionAmount;
        }else{
            invList[0] = 0;
        }
        if (rustySwordAmount > 0){
            invList[1] = 1;
            itemTempName[1] = "Rusty Sword x ";
            itemAmount[1] = rustySwordAmount;
        }else{
            invList[1] = 0;
        }
        if (ragsBodyAmount > 0){
            invList[2] = 1;
            itemTempName[2] = "Rags x ";
            itemAmount[2] = ragsBodyAmount;
        }else{
            invList[2] = 0;
        }
        if (chainBodyAmount > 0){
            invList[3] = 1;
            itemTempName[3] = "Chainmail Armor x ";
            itemAmount[3] = chainBodyAmount;
        }else{
            invList[3] = 0;
        }
    }
    for (int i = 0; i <= 3; i++){
        if (invList[i] > 0){
            System.out.println(itemTempName[i] + itemAmount[i]);
        }else if (invList[0] == 0 && invList[1] == 0 && invList[2] == 0 && invList[3] == 0){
            System.out.println("You have no items.");
        }
    }
    System.out.println("");
    System.out.println("1. Back");
    System.out.println("2. Home");
    menuChoice = userInput.next();
    System.out.println("");
    while (correctAnswer == false);
    if (menuChoice.equals("1") || menuChoice.equalsIgnoreCase("back") || menuChoice.equalsIgnoreCase("b")){
        correctAnswer = true;
        menuHome();
    }else if (menuChoice.equals("2") || menuChoice.equalsIgnoreCase("home") || menuChoice.equalsIgnoreCase("h")){
        correctAnswer = true;
        backSetter();
    }else{
        System.out.println("That is not a valid option, choose again.");
        menuChoice = userInput.next();
        System.out.println(""); 
    }
}
于 2013-04-11T22:11:30.610 回答
0

Yes, this is pretty much an example of recursion. It won't create any errors. But, because it's recursive, it may cause an infinite loop if their is no way of getting to a base case state. In a case like this where methods call each other and the recursion isn't evident at first glance, an infinite loop is a lot more likely.

It might not be a bad idea to somehow isolate that recursion so it is a lot more evident, making the code cleaner, and easier to maintain.

于 2013-04-11T02:13:46.227 回答
0

是的,这是合法的,但这是一个非常糟糕的设计。递归菜单调用会给你带来一些麻烦。我觉得返回会更好,但是我不知道这段代码的上下文。

public static void invMenu(){
    // Determines current items in inventory and prints them out
    //My menu options: 1. Back, 2. Home <- where the problem happens
    choice = userInput.next();

    if (choice.equals("1")){
       return;
    }else if (choice.equals("2")){
        backSetter();
    }
}

如果你打算这样做,你需要调整主菜单的代码来处理返回(即某种循环)。

于 2013-04-11T02:14:20.330 回答