Problem taking simple turns in Simon Challenge - Any hints?

Starting the Simon project. Decided step one would just be make sure I could get the computer and player to take turns properly, and already running into a snag.

You can check out the codepen here. I have it outputting the status of variables for each turn and current level for each step to see how they’re changing to help trouble-shoot things:

https://codepen.io/jbworks/pen/JpJYBj

The turns are handled by a simple function that should check variables to see what to do next and then calls itself again to do each next turn. Right now, to simplify the player move, I’m only paying attention to the red div and not trying to compare the results against the computer’s sequence. So it should be simple. But it does the first computer turn fine, then seems to handle the player onclick move ok, then does the next computer turn ok. But the next player turn is broken – instead of being level 2, turn 0, it changes the variables to level 1, turn 1. After that,everything goes off the rails :slight_smile:

I’m guessing I’m making some fundamental error in regards to the scope of the anonymous function that handles the player’s onclick event (and maybe starting a duplicate loop by calling the function again), but I’m not sure exactly what I’ve done wrong.

Would greatly appreciate any hints or pointers!

Huh, weird to see me credited in code for an 18 month old post. Present me is glad that past me was of some help!

I’m not quite able to get my head around the whole computerPlaySequence function, but I think it would be far less complicated if you split up the functionality into multiple functions that handle player input and computer functions. My guess is that the setTimeout functions are not behaving as you expect them to and they’re stepping all over your application state (changing variables that you don’t want to be changed, for instance). I don’t know that, but it’s usually a safe guess with timeouts.

When you think about Simon, it isn’t so much that there’s a human and computer player as it is just a machine that checks user input. My suggestion is to take a step back and instead of working on switching between human and computer, think about how you would record the user’s inputs and how you might check against what the computer expects. Don’t even worry about making the computer choose a new color or play the existing sequence, just see if you can record what the user is clicking and compare that to a set sequence of colors.

There’s a video in Wes Bos’s JavaScript 30 that I think is directly applicable - Key Sequence Detection. It’s free and the whole series is great, but watching at least that one video should be enlightening.

1 Like

Ha :slight_smile: Actually your work was a great help in understanding how to force the computer do each animation/sound sequence with pauses in between. Prior to that, it would run through them so fast, you couldn’t follow. I don’t think the setTimeout impacts anything else, but since it’s not working properly, you could be totally right.

But I take your overall point. I’ll take a crack at basic restructuring.

The original thought was:

  1. Create a random 20-step Simon sequence in an array (red, yellow, yellow, blue, green, etc.);
  2. make a function that switched between computer and player
    2a. computer side just plays items from array, starting from 0 to current level
    2b. player clicks on colors, with a check that each click matches the array elements in order from 0 to current level
    2c. when either side is done, switch to the other, incrementing level after each player success
    2d. if player presses wrong sequence, step back to 2a and repeat current level
  3. when player matches full 20-step sequence, done - you win
  4. include option that lets you end/restart at any time

I guess instead of a single function with if…else tree to handle steps 2-3, I could break those out into multiple functions that would be less likely to step on each other.

Thanks for the feedback!

function compPlaySounds() {
    if(comp hasnt played all notes){
        flash panel off then on
        play sound 
    }else {
       playerTurn = true;
   }
}

Really basic sudo code for what happens when computer is playing … eg when you press start button have a function to add panel color to an array and then comp reads array and plays the notes
when finished it just set a boolean to true and player can then try and match the pattern.

I wrote it this way to make a point … eg you can focus on just one part instead of trying to work on both comp and on player … if you get the comp to flash the color and play the sound you can then just add the line playerTurn = true … and then you can work on the player part.

Like you i created four colored divs when i started on simon … but i just focused on getting them to flash and play sound depending what was in an array eg let panels = [’.red’];
so my goal here was just to get the red div to flash light red then play sound then … set back to dark red …then i changed array to let panels = [’.red’,’.blue’];
i found for me using setInterval was the best option … and with setInterval i just popped a call to my function inside it … and worked on getting it to work.

Best thing about this approach is not having to worry about getting more than one part working at the same time
when i got this section working i then set about working on what should happen when a player clicks on a panel
and then individually on the on off button and strict button and the little screen to record the count
It was like creating individual parts and then connecting them at the end when they were done.and working.

Thanks for the wise recommendation. I did get the divs to play in sequence. And I have a decent idea of how to check the player’s actions. As you’re saying, I think my biggest problem is trying to make a single function do too much instead of making several small functions that each focus on a single task. Easier to make and test. Thanks for the reminder to break things into digestible chunks.