Stopping a while loop after set amount of time

Hello I am working on a Whack a mole project, and I'm uneable to solve the following problem.
There is a part in my code that controls the duration of the game, and I want it to run for set amount of time "period".

My functions are called inside a while loop and so to check that I don't go over the time on every while loop I run the equation (millis() - startMillis < period) as a conditional, therefore, if I go over the time my code stops and moves on to a light pattern.

The code:

startMillis = millis();

    while (millis() - startMillis < period) {
      int newColor = pickNewColor(mantas);
      bool hit = false;
      ledOn(newColor);

      while (!hit && (millis() - startMillis < period)) {

        if ( isWhacked(newColor) == true) {
          ledOffAll();
          score_buenos ++;
          hit = true;
          delay(200);
        }
        else {
          boomerang(isButtonPressed2()); 
          hit = false;
          score_malos++;
        }

      }


      delay(20);
    }

If you read the code you will understand that once you are in the second while loop, unless you whack a mole, you can stay still for as long as you want and the game would never finish, but the moment you Whack another mole it finishes.

My question is the following. How can I implement a function that would stop the game the moment we have run out of time and not after a whack??

I have tried doing this:

 while (millis() - startMillis < period) {
      int newColor = pickNewColor(mantas);
      bool hit = false;
      ledOn(newColor);

      while (!hit) {
        if ((millis() - startMillis < period) == false){
          hit = true
        }
        else if ( isWhacked(newColor) == true) {
          ledOffAll();
          score_buenos ++;
          hit = true;
          delay(200);
        }
        else if (isWhacked(newColor) == false){
          boomerang(isButtonPressed2()); 
          hit = false;
          score_malos++;
        }

If i leave the final "else" statment out does it mean that if no mole is whacked it will read in loop until it runs outs of time and the first if statement will brake the loop?
Do you think it's a good way of approching the problem?
Any other ideas?

Thank you.

Have you considered including "and" in the while loop?

I put && as you can see on the first code but it doesn't trigger until I whack.

Where are your serial.Print() statements so you can follow the logic and see where the logic fails?

Thank you for your suggestion but I think you are missing the point. My question really is if I the optio I'm suggesting can work. Will an if loop run forever if there is no else statement at the end??

Eventually something will fail. Doesn't your test show you the answer?

There is no such thing as an 'if loop'. IF and ELSE constructs never repeat unless they are enclosed in some other repeating structure.

I need the device to test it and of now I only have the code, but next I will try to run it on the hardware and see if it behaves as I want it.

So If nothing is whacked what will happen to the code in this lines:

while (!hit) {
        if ((millis() - startMillis < period) == false){
          hit = true
        }
        else if ( isWhacked(newColor) == true) {
          ledOffAll();
          score_buenos ++;
          hit = true;
          delay(200);
        }
        else if (isWhacked(newColor) == false){
          boomerang(isButtonPressed2()); 
          hit = false;
          score_malos++;
        }

Let us know when you have hardware. Then I would feel useful commenting.

1 Like

Eschew that approach to code as soon as you can. Code explains things to the computer, not human beings.

2 Likes

I don't have a coding answer however if I were to write such a program, I would have to create a flow chart first.

Lately I've been using diagrams.net to make flow charts.

I realize flow charting is not as much fun as coding, however I've found in many cases looking at the flow chart of my initial program concept there were changes that can be made to significantly simplify the program.

Your mileage may vary.

consider
note use of mode and how timer switch mode back to Stop

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

unsigned long Period = 5000;
unsigned long msecLst;
unsigned long msec;

enum { Stop, Run };
int mode = Stop;

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    msec = millis ();

    if (Run == mode)  {
        if (msec - msecLst > Period)  {
            mode = Stop;
            digitalWrite (pinsLed [0], Off);
        }

        switch (chkButtons ())  {
        case 2:
            digitalWrite (pinsLed [2], ! digitalRead (pinsLed [2]));
            break;

        case 1:
            digitalWrite (pinsLed [1], ! digitalRead (pinsLed [1]));
            break;
        }
    }
    else if (0 == chkButtons ())  {
        msecLst = msec;
        mode    = Run;
        digitalWrite (pinsLed [0], On);
    }
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.