这是我之前提出的一个问题的延续,但我需要帮助解决这个小型冒险游戏的一部分,我将其作为AP Java Class的最终项目。
在我的冒险中,我有一个功能,允许玩家在各个怪物的战斗中,如果他们在一个给定的位置。我的问题是,一旦我到达我的程序中的这个位置,程序就会停止响应
在做了一些调试之后,我发现它是一个 while循环我在doBattle()
方法中执行了所有操作player.isAlive
和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 ,而文本是TextArea
而 inputText 是{{1} }
答案 0 :(得分:2)
您似乎误解了代码的执行方式。您将输入处理代码(inputText.setOnAction
)放在循环中,您似乎认为这意味着它将在那时执行。但这不正确;处理程序是异步的,将在事件发生时执行。循环中实际发生的事情是处理程序被设置,设置,设置,设置和设置,直到永恒。 (不确定Swing的线程安全性,但我猜测处理程序甚至没有设置,因为你没有给事件线程同步的机会)
您真正想要的是您的代码在输入事件发生时实际继续。这意味着所有的延续逻辑应该 in 处理程序,而不是它周围。
所以我认为有三种方法可以继续:
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
}