Is it possible to check the condition after each method in the loop? If so, how?

As I said in the title, I have a loop in the RPG that I do in high school. This is the main cycle that sets your day to play individual sequences in chronological order. My question is, how can I make sure that I check whether boolean β€œbeat” or boolean β€œlost” (bearing in mind the status of the game) Truth worked after each method in the loop, but still supporting the methods together in the loop. Is it nested if the expressions inside my while loop are the only way?

 while (!g.getBeat() || g.getLost()) { g.wakeUp(); g.goToSchool(); g.beforeLunch(); g.lunchActivity(); g.afterLunch(); g.afterSchool(); g.home(); g.sleep(); } 
+5
source share
5 answers

You will have to do it manually. To help you write a little less code, create 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; ... } 
+3
source

You can use the switch statement by entering the state:

 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++; } 
+3
source

There is no "built-in" way to do this, but with some coding, whatever.

First, no matter how you deal with this, I would wrap the final condition in one method 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 it manually:

 while (!g.isOver()) { g.wakeUp(); if (g.isOver()) { break; } g.goToSchool(); if (g.isOver()) { break; } // etc... } 

But this is due to the large amount of code and not too elegant.

Perhaps a more OO approach would be to warp every such call in the handler class:

 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. For instance. for the wakeUp() step you will have:

 public abstract WakeUpHandler (Game g) { public WakeUpHandler (Game g) { super(g); } @Override public void performStage() { g.wakeUp(); } } 

Then in the main method you can have an array of such handlers and iterate over them:

 List<GameStageHandler> handlers = ...; while (!g.isOver()) { for (GameStageHandler handler : handlers) { if (!g.play()) { break; } } } 
+3
source

This is probably beyond your scope as you notice that the class has not yet covered Runnable . This is an interesting question, and the challenge is to come up with a concise and elegant way to present it, while avoiding as many repetitions as possible. It uses a solution using Java 8 and functional programming methods.

The first understanding is to see that every action or step in a game can be represented as a lambda expression or a method reference. I assume you have a Game class. Each such step takes a Game instance as an argument (or receiver), and thus can be introduced as a β€œconsumer” of Game instances. Thus, we can introduce them into the 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 the data structure, we can iterate over them:

 for (Consumer<Game> action : actions) { action.accept(game); } 

Of course, we want to check if the game is over after each action. Suppose you have an isOver method in the Game class that checks for the correct termination conditions. Then you can:

 for (Consumer<Game> a : actions) { a.accept(game); if (game.isOver()) { break; } } 

It runs through just one day of the game. Presumably, you want to start the game indefinitely until you reach your completion condition. To do this, you need an external loop, and the completion check should exit the outer loop:

 outer: while (true) { for (Consumer<Game> a : actions) { a.accept(game); if (game.isOver()) { break outer; } } } 

This may be enough: you have a list of game actions and a loop that runs indefinitely, checking the termination condition after each action.

But wait, there still! There are still quite a few templates here that can be eliminated using some functions of the Java 8 stream. Note that each element of the stream can be tested against the predicate using the noneMatch method. This method exits when one of the predicates returns true.

Since each action is of the Consumer<Game> , we need a small helper function that turns each action into a predicate:

 static Predicate<Consumer<Game>> stepAndCheck(Game game) { return c -> { c.accept(game); return game.isOver(); }; } 

Now we can run all the actions of the day as follows:

 actions.stream().noneMatch(stepAndCheck(game)) 

To start the game endlessly, we simply transfer this to the while loop. Since noneMatch returns true if, as they say, none of the predicates match, we make this loop condition and leave the loop body empty:

 while (actions.stream().noneMatch(stepAndCheck(game))) { // nothing } 

This may seem unnecessarily hidden. Indeed, this can be, for example, for toy examples. However, for more complex problems, such methods are very valuable.

+2
source

If you want to save each step in your own method, as in your example, you can do this a little ...

You can reduce the amount of code if you make all of these methods true "true" if the condition for stopping the loop is met ... however, this may not be possible if you plan to use these methods in a context context.

 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 force these methods to throw an exception if the stop condition is met. Then you catch this exception outside the loop. This way you save the if (...) break statements. However, this is not considered good practice.

 if (!g.getBeat() || g.getLost()) { try { do { g.wakeUp(); g.goToSchool(); ... g.sleep(); } while (true); } catch (ActivityLoopFinished ex) { // nothing to do here } } 
0
source

Source: https://habr.com/ru/post/1213892/


All Articles