[英]Is it possible to check a condition after every method in a loop? If so, how?
Like I said in the title I have a loop in an RPG I'm making about High School. 就像我在标题中说的那样,我在RPG中有一个关于高中的循环。 This is the main loop that sets up your day to act out individual sequences in chronological order.
这是主要的循环,它按照时间顺序设置您的一天来执行单个序列。 My question is how could I make it so that I check whether the
boolean
"beat" or the boolean
"lost" (referring to the status of the game) has been tripped to true after every method in the loop but still keeping the methods together in a loop. 我的问题是我怎么能这样做,以便我检查
boolean
“节拍”或boolean
“丢失”(指游戏的状态)是否在循环中的每个方法之后被跳转到了真,但仍然将方法保持在一起在一个循环中。 Is nested if statements inside my while loop the only way? 嵌套在if循环中的if语句是唯一的方法吗?
while (!g.getBeat() || g.getLost())
{
g.wakeUp();
g.goToSchool();
g.beforeLunch();
g.lunchActivity();
g.afterLunch();
g.afterSchool();
g.home();
g.sleep();
}
You would have to do it manually. 你必须手动完成。 To help you write a little less code, make a method that checks both conditions:
为了帮助您编写更少的代码,请创建一个检查两个条件的方法:
private boolean stopTheLoop() {
return g.getBeat() || g.getLost();
}
Now convert your loop to infinite with checks after each method: 现在,在每个方法之后使用检查将循环转换为无限:
while (true) {
g.wakeUp();
if (stopTheLoop()) break;
g.goToSchool();
if (stopTheLoop()) break;
g.beforeLunch();
if (stopTheLoop()) break;
...
}
You could use a switch statement by introducing a state : 您可以通过引入状态来使用switch语句:
int state = 0;
while (!g.getBeat() || g.getLost())
{
switch (state) {
case 0:
g.wakeUp();
break;
case 1:
g.goToSchool();
break;
case 2:
g.beforeLunch();
break;
case 3:
g.lunchActivity();
break;
case 4:
g.afterLunch();
break;
case 5:
g.afterSchool();
break;
case 6:
g.home();
break;
case 7:
g.sleep();
break;
default:
// some error handling, depending on your logic,
// or perhaps state = -1 to restart
}
state++;
}
There isn't any "built-in" way to do this, but with some coding, anything's possible. 没有任何“内置”方法可以做到这一点,但通过一些编码,一切皆有可能。
First, regardless if how you handle this, I'd wrap the end condition into a single method, just to make things more convenient: 首先,无论你如何处理这个问题,我都会将结束条件包装到一个方法中,只是为了让事情变得更方便:
public class Game {
// method, members, etc...
public boolean isOver() {
return !getBeat() || getLost();
}
}
Now, The first option that comes to mind is to do this manually: 现在,想到的第一个选项是手动执行此操作:
while (!g.isOver()) {
g.wakeUp();
if (g.isOver()) {
break;
}
g.goToSchool();
if (g.isOver()) {
break;
}
// etc...
}
But this involves a lot of code, and isn't too elegant. 但这涉及很多代码,而且不是太优雅。
A more OO approach, perhaps, would be to warp every such call in a handler class: 或许更多的OO方法是在处理程序类中扭曲每个这样的调用:
public abstract GameStageHandler (Game g) {
protected Game g;
public GameStageHandler (Game g) {
this.g = g;
}
/**
* Play a stage in the game
* @return Whether the game should go on or not after this stage
*/
public boolean play() {
performStage();
return !g.isOver();
}
public abstract void performStage();
}
And implement it for every stage of the game. 并为游戏的每个阶段实施它。 Eg for the
wakeUp()
stage you'd have: 例如,对于
wakeUp()
阶段,你有:
public abstract WakeUpHandler (Game g) {
public WakeUpHandler (Game g) {
super(g);
}
@Override
public void performStage() {
g.wakeUp();
}
}
Then, in the main method, you could have an array of such handlers, and iterate over them: 然后,在main方法中,您可以拥有一个这样的处理程序数组,并迭代它们:
List<GameStageHandler> handlers = ...;
while (!g.isOver()) {
for (GameStageHandler handler : handlers) {
if (!g.play()) {
break;
}
}
}
This is probably beyond the scope of your assignment, as you noted the class hasn't even covered Runnable
yet. 这可能超出了你的任务范围,因为你注意到该课程甚至还没有涵盖
Runnable
。 This is an interesting question, though, and the challenge is to come up with a concise and elegant way to represent it, while avoiding as much repetition as possible. 然而,这是一个有趣的问题,挑战在于提出一种简洁而优雅的方式来表示它,同时避免尽可能多的重复。 Here's a solution that uses Java 8 and functional programming techniques.
这是一个使用Java 8和函数式编程技术的解决方案。
The first insight is to see that each game action or step can be represented as a lambda expression or method reference. 第一个见解是看到每个游戏动作或步骤可以表示为lambda表达式或方法引用。 I'll assume that you have a
Game
class. 我假设你有一个
Game
类。 Each such step takes a Game
instance as an argument (or receiver) and thus can be typed as a "consumer" of Game
instances. 每个这样的步骤都将
Game
实例作为参数(或接收者),因此可以键入Game
实例的“消费者”。 We can thus put them into a data structure: 因此我们可以将它们放入数据结构中:
List<Consumer<Game>> actions = Arrays.asList(
Game::wakeUp,
Game::goToSchool,
Game::beforeLunch,
Game::lunchActivity,
Game::afterLunch,
Game::afterSchool,
Game::home,
Game::sleep);
Now that we have them in a data structure, we can loop over them: 现在我们将它们放在数据结构中,我们可以遍历它们:
for (Consumer<Game> action : actions) {
action.accept(game);
}
Of course, we want to check if the game is over after each action. 当然,我们想要检查每个动作后游戏是否结束。 Let's assume you have a method
isOver
on the Game
class that checks the right termination conditions. 假设你在
Game
类上有一个方法isOver
来检查正确的终止条件。 You can then do: 然后你可以这样做:
for (Consumer<Game> a : actions) {
a.accept(game);
if (game.isOver()) {
break;
}
}
That only runs through one day of the game. 这只会持续一天的比赛。 Presumably you want to run the game indefinitely until it reaches its termination condition.
大概你想要无限期地运行游戏,直到达到终止状态。 For that you need an outer loop, and the termination check has to break out of the outer loop:
为此你需要一个外部循环,终止检查必须突破外部循环:
outer:
while (true) {
for (Consumer<Game> a : actions) {
a.accept(game);
if (game.isOver()) {
break outer;
}
}
}
This by itself might be sufficient: you have a list of game actions, and a loop that runs indefinitely, checking the termination condition after each action. 这本身就足够了:你有一个游戏动作列表,一个无限运行的循环,检查每个动作后的终止条件。
But wait, there's more! 但等等,还有更多! There's still a fair amount of boilerplate here, which can be eliminated using some of Java 8's stream features.
这里仍然有相当数量的样板,可以使用Java 8的一些流功能来消除它们。 Consider that every element of a stream can be tested against a predicate using the
noneMatch
method. 考虑使用
noneMatch
方法可以针对谓词测试流的每个元素。 This method terminates when one of the predicates returns true. 当其中一个谓词返回true时,此方法终止。
Since each action has type Consumer<Game>
, we need a little helper function that turns each action into a predicate: 由于每个动作都有类型
Consumer<Game>
,我们需要一个小助手函数将每个动作转换为谓词:
static Predicate<Consumer<Game>> stepAndCheck(Game game) {
return c -> { c.accept(game); return game.isOver(); };
}
Now we can run all the actions of a day as follows: 现在我们可以按如下方式运行一天的所有操作:
actions.stream().noneMatch(stepAndCheck(game))
To run the game indefinitely, we simply wrap this in a while loop. 要无限期地运行游戏,我们只需将其包装在while循环中。 Since
noneMatch
returns true
if, as it says, none of the predicates matches, we make this the loop condition and leave the loop body empty: 因为如果没有谓词匹配,所以如果
noneMatch
返回true
,那么我们将其设置为循环条件并将循环体留空:
while (actions.stream().noneMatch(stepAndCheck(game))) {
// nothing
}
This might seem like it's unnecessarily obscure. 这可能看起来像是不必要地模糊不清。 Indeed, it might be, for toy examples such as this.
事实上,对于像这样的玩具示例,它可能是。 However, for more complex problems, techniques like this are quite valuable.
但是,对于更复杂的问题,这样的技术非常有价值。
If you want to keep each step in its own method like you do in your example there is little you can do about it... 如果你想像你在你的例子中那样用自己的方法保持每一步,你几乎无能为力......
You can reduce the amount of code if you make all those methods to return "true" if the condition to stop the loop is met... however this might not be possible if you plan to use those methods in order context. 如果在满足停止循环的条件时使所有这些方法返回“true”,则可以减少代码量...但是,如果您计划在顺序上下文中使用这些方法,则可能无法实现。
if (!g.getBeat() || g.getLost()) do {
if (g.wakeUp()) break;
if (g.goToSchool()) break;
...
if (g.sleep()) break;
} while (true);
A possible trick is to make those methods to throw an exception if the stop condition is met. 一个可能的技巧是在满足停止条件时使这些方法抛出异常。 Then you would catch that exception in outside the loop.
然后你会在循环外捕获该异常。 That way you would save the if (...) break statements.
这样你就可以保存if(...)break语句。 However this is not considered a good practice.
然而,这不是一个好习惯。
if (!g.getBeat() || g.getLost()) {
try {
do {
g.wakeUp();
g.goToSchool();
...
g.sleep();
} while (true);
} catch (ActivityLoopFinished ex) {
// nothing to do here
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.