是否可以在循环中的每个方法之后检查条件?如果是这样,怎么样?

时间:2015-02-22 06:41:55

标签: java loops while-loop

就像我在标题中说的那样,我在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();
}

5 个答案:

答案 0 :(得分:3)

你必须手动完成。为了帮助您编写少量代码,请创建一个检查两种条件的方法:

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;
    ...
}

答案 1 :(得分:3)

您可以通过引入状态来使用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++;
}

答案 2 :(得分:3)

没有任何“内置”方法可以做到这一点,但通过一些编码,一切皆有可能。

首先,无论你如何处理这个问题,我都会将结束条件包装到一个方法中,只是为了让事情变得更方便:

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;
        }
     }
}

答案 3 :(得分:2)

这可能超出了您的作业范围,因为您注意到该课程尚未覆盖Runnable。然而,这是一个有趣的问题,挑战在于提出一种简洁而优雅的方式来表示它,同时避免尽可能多的重复。这是一个使用Java 8和函数式编程技术的解决方案。

第一个见解是看每个游戏动作或步骤可以表示为lambda表达式或方法引用。我假设您有一个Game课程。每个这样的步骤都将Game实例作为参数(或接收者),因此可以键入&#34;消费者&#34; 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);
}

当然,我们想在每次动作后检查游戏是否结束。假设您在isOver类上有一个检查正确终止条件的方法Game。然后你可以这样做:

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
}

这看起来似乎不必要地模糊不清。事实上,对于像这样的玩具示例,它可能是。但是,对于更复杂的问题,这样的技术非常有价值。

答案 4 :(得分:0)

如果你想像你在你的例子中那样用自己的方法保持每一步,你几乎无能为力......

如果您使所有这些方法都返回&#34; true&#34;您可以减少代码量。如果满足停止循环的条件......但是如果您计划在顺序上下文中使用这些方法,则可能无法实现。

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
  }
}