[英]Is it possible to check a condition after every method in a loop? If so, how?
就像我在标题中说的那样,我在RPG中有一个关于高中的循环。 这是主要的循环,它按照时间顺序设置您的一天来执行单个序列。 我的问题是我怎么能这样做,以便我检查boolean
“节拍”或boolean
“丢失”(指游戏的状态)是否在循环中的每个方法之后被跳转到了真,但仍然将方法保持在一起在一个循环中。 嵌套在if循环中的if语句是唯一的方法吗?
while (!g.getBeat() || g.getLost())
{
g.wakeUp();
g.goToSchool();
g.beforeLunch();
g.lunchActivity();
g.afterLunch();
g.afterSchool();
g.home();
g.sleep();
}
你必须手动完成。 为了帮助您编写更少的代码,请创建一个检查两个条件的方法:
private boolean stopTheLoop() {
return g.getBeat() || g.getLost();
}
现在,在每个方法之后使用检查将循环转换为无限:
while (true) {
g.wakeUp();
if (stopTheLoop()) break;
g.goToSchool();
if (stopTheLoop()) break;
g.beforeLunch();
if (stopTheLoop()) break;
...
}
您可以通过引入状态来使用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++;
}
没有任何“内置”方法可以做到这一点,但通过一些编码,一切皆有可能。
首先,无论你如何处理这个问题,我都会将结束条件包装到一个方法中,只是为了让事情变得更方便:
public class Game {
// method, members, etc...
public boolean isOver() {
return !getBeat() || getLost();
}
}
现在,想到的第一个选项是手动执行此操作:
while (!g.isOver()) {
g.wakeUp();
if (g.isOver()) {
break;
}
g.goToSchool();
if (g.isOver()) {
break;
}
// etc...
}
但这涉及很多代码,而且不是太优雅。
或许更多的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();
}
并为游戏的每个阶段实施它。 例如,对于wakeUp()
阶段,你有:
public abstract WakeUpHandler (Game g) {
public WakeUpHandler (Game g) {
super(g);
}
@Override
public void performStage() {
g.wakeUp();
}
}
然后,在main方法中,您可以拥有一个这样的处理程序数组,并迭代它们:
List<GameStageHandler> handlers = ...;
while (!g.isOver()) {
for (GameStageHandler handler : handlers) {
if (!g.play()) {
break;
}
}
}
这可能超出了你的任务范围,因为你注意到该课程甚至还没有涵盖Runnable
。 然而,这是一个有趣的问题,挑战在于提出一种简洁而优雅的方式来表示它,同时避免尽可能多的重复。 这是一个使用Java 8和函数式编程技术的解决方案。
第一个见解是看到每个游戏动作或步骤可以表示为lambda表达式或方法引用。 我假设你有一个Game
类。 每个这样的步骤都将Game
实例作为参数(或接收者),因此可以键入Game
实例的“消费者”。 因此我们可以将它们放入数据结构中:
List<Consumer<Game>> actions = Arrays.asList(
Game::wakeUp,
Game::goToSchool,
Game::beforeLunch,
Game::lunchActivity,
Game::afterLunch,
Game::afterSchool,
Game::home,
Game::sleep);
现在我们将它们放在数据结构中,我们可以遍历它们:
for (Consumer<Game> action : actions) {
action.accept(game);
}
当然,我们想要检查每个动作后游戏是否结束。 假设你在Game
类上有一个方法isOver
来检查正确的终止条件。 然后你可以这样做:
for (Consumer<Game> a : actions) {
a.accept(game);
if (game.isOver()) {
break;
}
}
这只会持续一天的比赛。 大概你想要无限期地运行游戏,直到达到终止状态。 为此你需要一个外部循环,终止检查必须突破外部循环:
outer:
while (true) {
for (Consumer<Game> a : actions) {
a.accept(game);
if (game.isOver()) {
break outer;
}
}
}
这本身就足够了:你有一个游戏动作列表,一个无限运行的循环,检查每个动作后的终止条件。
但等等,还有更多! 这里仍然有相当数量的样板,可以使用Java 8的一些流功能来消除它们。 考虑使用noneMatch
方法可以针对谓词测试流的每个元素。 当其中一个谓词返回true时,此方法终止。
由于每个动作都有类型Consumer<Game>
,我们需要一个小助手函数将每个动作转换为谓词:
static Predicate<Consumer<Game>> stepAndCheck(Game game) {
return c -> { c.accept(game); return game.isOver(); };
}
现在我们可以按如下方式运行一天的所有操作:
actions.stream().noneMatch(stepAndCheck(game))
要无限期地运行游戏,我们只需将其包装在while循环中。 因为如果没有谓词匹配,所以如果noneMatch
返回true
,那么我们将其设置为循环条件并将循环体留空:
while (actions.stream().noneMatch(stepAndCheck(game))) {
// nothing
}
这可能看起来像是不必要地模糊不清。 事实上,对于像这样的玩具示例,它可能是。 但是,对于更复杂的问题,这样的技术非常有价值。
如果你想像你在你的例子中那样用自己的方法保持每一步,你几乎无能为力......
如果在满足停止循环的条件时使所有这些方法返回“true”,则可以减少代码量...但是,如果您计划在顺序上下文中使用这些方法,则可能无法实现。
if (!g.getBeat() || g.getLost()) do {
if (g.wakeUp()) break;
if (g.goToSchool()) break;
...
if (g.sleep()) break;
} while (true);
一个可能的技巧是在满足停止条件时使这些方法抛出异常。 然后你会在循环外捕获该异常。 这样你就可以保存if(...)break语句。 然而,这不是一个好习惯。
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.