簡體   English   中英

如何解決此無限While循環?

[英]How Can I Fix This Infinite While Loop?

這是我之前提出的問題的延續,但我需要這個小冒險游戲的一部分,這是我作為AP Java類的最終項目而制作的。
在我的冒險中,我有一個功能,可以讓玩家與處於指定位置的各種怪物進行戰斗。 我的問題是,一旦到達程序中的該位置,程序就會停止響應。
經過一些調試后,我發現這是一個while循環 ,可以在player.isAliveenemy.isAlivedoBattle()方法中執行所有enemy.isAlive 唯一的問題是,一旦我刪除了while循環 ,該程序就跳到怪物死亡或玩家死亡之后的右邊,而它應該讓您選擇是否重復攻擊怪物直到兩個實體中的任何一個是死的。

這是doBattle()方法的代碼:

public void doBattle(Monster enemy)
    {
        //boolean fled = false;
        //Greets player into battle by telling what monster they are fighting
        text.appendText("\n" + "A wild " + enemy.getName() + " has appeared!" + "\n" );
        mobImagePane.setImage(enemy.getImage());

        //System.out.print("THIS RAN"); //debug


        while ( p.getHealth() > 0 && enemy.getHealth() > 0 ) //while enemy and player are alive
        {
            //Prompts user to attack or run
            text.appendText("Attack " + enemy.getName() + "? (Y/N) " + "\n");
            inputText.setOnAction(event ->
            {
                String fightChoice = inputText.getText();
                fightChoice = fightChoice.toUpperCase();
                //String fightChoice = this.choice;


                if (fightChoice.equals("Y"))//if they want to fight
                {
                    //Player turn
                    enemy.setHealth(enemy.getHealth() - p.getDamage()); //Sets the monsters health as their current health minus the players damage
                    text.appendText("You attack " + enemy.getName() + " for " + p.getDamage() + " damage!" + "\n" + "Enemy health is " + enemy.getHealth() + "\n");

                    //Monster turn
                    p.setHealth(p.getHealth() - enemy.getDamage()); //Sets the players health as their current health minus the monsters damage
                    text.appendText("The " + enemy.getName() + " hit you for " + enemy.getDamage() + " damage!" + "\n" + "Your health is " + p.getHealth() + "\n"); //prints how much damage the monster does to the player
                    if (p.health < 20.0) {
                        text.appendText("Your health is low, you should return home and restore health!" + "\n");
                    }

                    //checks if the player or monster is dead
                    this.checkLife();
                    enemy.checkLife();

                } else {
                    if (fightChoice.equals("N")) // if they don't want to fight
                    {
                        mobImagePane.setImage(null);
                        text.appendText("You fled from the fight!" + "\n");
                        this.setNewLoc("TOWN"); // brings you back to town
                        fled = true;
                        //JOptionPane.showMessageDialog(null, "You are now in " + this.currentLoc.getName() + "\n" + this.currentLoc.getDescription());
                        //String move2 = JOptionPane.showInputDialog(null,"Which way do you want to go? (N, E, S, W)");
                        //makeMove(move2);
                        //break;
                    } else // they don't make any sense
                    {
                        text.appendText("Unrecognized command" + "\n");
                    }
                }

                //}

                //when someone dies
                if (!fled) {
                    if (p.alive) // if you are still standing
                    {
                        //print results (money earned, health remaining)
                        mobImagePane.setImage(null);
                        p.wallet += enemy.getLoot();
                        playerInfo.setText(p.getPlayerName() + "\n" + "Health: " + p.getHealth() + "\n" + "Wallet: " + p.getWallet() + "\n");
                        text.setText("You shrekt the " + enemy.getName() + "\n" + "You got $" + enemy.getLoot() + " for winning!" + "\n" + "You now have $" + p.wallet + "\nYour health is " + p.getHealth() + "\n");
                    } else //if you died
                    {
                        mobImagePane.setImage(null);
                        text.setText("You have been shrekt by the " + enemy.getName() + "\n" + "GAME OVER" + "\n");
                        text.appendText("\nPlay again? (Y/N)" + "\n");
                        inputText.setOnAction(event2 -> {
                            String answer = inputText.getText();
                            answer.toUpperCase();
                            //String answer = this.choice;

                            if (answer.equals("Y")) //if they want to play again
                            {
                                text.appendText("Alright! Let's go!" + "\n");
                                this.reset();
                            } else //if they want to quit
                            {
                                text.appendText("Wow. What a skrub, okay bye." + "\n");
                                System.out.close();
                            }
                        });

                    }
                }
            });
        }
    } //end doBattle

請記住,我是本網站的新手,而Java還是新手,所以如果您需要更多信息或其他任何可以幫助我獲得更好建議的信息,請告訴我,我們將不勝感激。
另外,請不要拒絕投票,至少不要告訴我為什么,我想在這種事情上變得更好。
我還應該提到我為此使用JavaFX ,並且textTextAreainputTextTextField

您似乎誤解了代碼的執行方式。 您將輸入處理代碼( inputText.setOnAction )放入循環中,您似乎認為這將在該時間執行。 但這是不正確的。 該處理程序是異步的,將在事件發生時執行。 循環中實際發生的情況是,處理程序被設置,設置,設置,設置,設置,直到永恆。 (不確定Swing的線程安全性,但是我猜想甚至沒有設置處理程序,因為您沒有給事件線程提供同步的機會)

您真正想要的是讓代碼在發生輸入事件時實際繼續。 這意味着所有繼續邏輯都應該處理程序中,而不是在處理程序周圍。

因此,我為您提供了三種繼續的方法:

  • 轉到使用Simpeler的工作方式,而改用控制台(最少的代碼更改)。 這將起作用,因為控制台讀取被阻止(您不會使用事件處理程序,而是使用簡單的讀取)
  • 將此代碼移到一個單獨的線程中,在設置處理程序后阻塞當前線程( wait ),並在事件發生時notify
  • 完全分割邏輯,以便任何延續都由事件驅動。 那將意味着更多地進入狀態機的工作方式。

第二種方法的缺點是它涉及線程和同步。 正確無比。 但是您的游戲邏輯仍然會像整體一樣“讀”起來。 如果您將線程處理程序很好地封裝到UserInput類中,則可以使其變得可管理(但我不認為您還處於該級別)

第三種方法的缺點是您的邏輯最終會散布到各處。

考慮到您的初學者水平,我能給您的最務實的建議是采用方法1,而改用基於控制台的方法。

對於方法2

關於第二種方法的一些細節-請注意,這是偽代碼。 我也不是說這不是理想的設計,也不是代碼庫。 但這是可傳遞代碼的快速修復。

// this should not run on the event handling thread of javafx

Holder<String> inputReceived = new Holder<String>(); //Holder is an often used hack to set values from a closure.  It's not builtin, but you'll find hundreds of examples.

inputText.setHandler(e->{
   inputReceived.set(inputText.getText());
});

while (player.isAlive() && monster.isAlive()){
   // wait for input
   while (!isValidInput(inputReceived.get())){
      Thread.sleep(200);
   }
   ... do your code based on the value in inputReceived
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM