I mean, does it work as intended? If so and works as intended over time, then great!
If you are also asking about different techniques you might have used that will be less cumbersome to build upon or sort of think about in your plan for another project, you have already heard of @paulpaulson array suggestion and @xfpd mission critical suggestion to use a button debounce. @alto777 suggested to me one time to use a button library that iirc, in alto's words "doesn't suck", namely
https://github.com/ArduinoGetStarted/button
Another technique you might look into is to make a finite state machine by using switch/case instead of if/else. There are examples of course in the IDE. I find it much easier to keep track of this way, especially as your projects grow or you maybe made something like you did (is it for a cat feeder?) that you may want to import to another project one day.
I like to think of state machines as the secret behind every video game, because they kind of are. Is the door to the castle open or closed? are you on level 1 stage 1 or level 8 stage 8 and so on, such as in Super Mario Bros for the NES.
Every one of these variables is its own state machine, including a general wrapper for whether you are on the splash screen waiting to start the game or whether or are actually in the game and playing it.
Thus, you might imagine a completed game such as Super Mario Bros as a big tree with various branches of state machines, with other twigs off those branches that are also state machines, and so on.
Here is a very simple example that illustrates the point and requires no extra hardware. I broke off all the code in each time state into its own function. You might replace the free running clock time based state changing mechanism with your button push. I used discrete functions to make changing just certain things easier if such a project would grow in the future, avoiding spaghetti code in void loop().
You can even nest state machines inside state machines, although the code below doesn't do that and it opens a door to spaghetti code if you aren't careful. Anywho...
/* April 03, 2024
revised December 11, 2024 to make the concept a bit more obvious
Hallowed31
State/Mode Machine - events/functions driven by built in
millis timer and nothing else
It's like a game, only much less fun. Just watch the game play itself!
Circuit: just an Arduino
Set Serial monitor to 9600 baud, no line ending
Working as intended. Tested on Uno R3
*/
byte level = 0; // you could have 0 - 255 levels if you wanted.
unsigned long currentTime;
unsigned long lastTimeAround;
void setup() {
Serial.begin(9600);
// just the sketch name so I know what's loaded on my Arduino
Serial.println(F("automaticByteDrivenStateMachine"));
delay(500);
Serial.println();
level = 0;
currentTime = 0;
lastTimeAround = 0;
}
void loop() {
// start free running timer, this never stops running in the "game"
currentTime = millis();
/* set conditional statement whose condition is to
check built in millis clock and announce what "game"
level it's on every two seconds */
if (currentTime - lastTimeAround > 2000) {
switch (level) {
case 0:
zero();
break;
case 1:
one();
break;
case 2:
two();
break;
case 3:
three();
break;
case 4:
four();
break;
}
// sync the time marker to the free running clock
lastTimeAround = currentTime;
}
}
void zero() {
// you might think of this as reset or awaiting players
Serial.println("level 0");
level += 1; // increment level by one, to level 1
}
void one() {
// this might be level one
Serial.println("level 1");
level += 1; // exit to level 2
}
void two() {
// level two
Serial.println("level 2");
level += 1;
}
void three() {
// and so on
Serial.println("level 3");
level += 1;
}
void four() {
Serial.println("level 4");
level = 0; // reset to level 0
}