<header>
  <h1>
    <span style="color: #9b59b6;">S</span>
    <span style="color: #27AE60;">i</span>
    <span style="color: #C0392B;">m</span>
    <span style="color: #2980B9;">o</span>
    <span style="color: #F39C12;">n</span> 
    <span style="color: #27AE60;">G</span>
    <span style="color: #C0392B;">a</span>
    <span style="color: #2980B9;">m</span>
    <span style="color: #F39C12;">e</span>
  </h1>
</header>

<section>
  <div id="green" class="colors"></div>
  <div id="red" class="colors"></div>
  <div id="yellow" class="colors"></div>
  <div id="blue" class="colors"></div>
  
  <div id="center">
    <input id="level" value="" readonly>
    <div id="basic">Basic</div>
    <div id="strict">Strict</div>
    <div id="on-off" class="glow">
      <div class="switch" id="on"></div>
      <div class="switch active" id="off"></div>
    </div>
  </div>
</section>

<footer>
  <p>Created by <a href="https://remybeumier.be" target="_blank">Rémy Beumier</a></p>
</footer>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}

html {
  background: url(https://res.cloudinary.com/beumsk/image/upload/v1514984443/music_flpbpz.png);
  background-size: 50px;
  background-repeat: space;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  background: rgba(256,256,256,0.8);
  text-align: center;
  font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
}

header {
  color: #9b59b6;
  font-size: 20px;
  padding: 10px 5px;
  letter-spacing: 6px;
  text-shadow: 1px 1px #fff, 2px 2px #333;
}
@media only screen and (min-width:768px) and (min-height: 560px) {
  header {
    font-size: 26px;
  }
}

section {
  height: 300px;
  width: 300px;
  margin: auto;
  border-radius: 100%;
  position: relative;
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;
}
@media only screen and (min-width:768px) and (min-height: 560px) {
  section {
    height: 400px;
    width: 400px;
  }
}

#center {
  height: 150px;
  width: 150px;
  background: #9b59b6;
  position: absolute;
  left: 75px;
  top: 75px;
  border-radius: 100%;
  border: solid #333 4px;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
  align-items: space-around;
  align-content: space-around;
  padding: 20px;
}
@media only screen and (min-width:768px) and (min-height: 560px) {
  #center {
    height: 200px;
    width: 200px;
    left: 100px;
    top: 100px;
  }
}

#center input {
  width: 60px;
  height: 24px;
  margin: 0 calc(100% - 60px);
  font-size: 18px;
  text-align: center;
  border-radius: 5px;
  border: solid 2px #333;
}
@media only screen and (min-width: 768px) and (min-height: 560px) {
  #center input {
    font-size: 25px;
    height: 30px;
  }
}

#basic, 
#strict {
  width: 46px;
  height: 24px;
  padding: 2px;
  border-radius: 5px;
  cursor: pointer;
  border: solid #333 2px;
  background: #333;
  color: whitesmoke;
  font: 400 13.3333px Arial;
}
@media only screen and (min-width: 768px) and (min-height: 560px) {
  #basic, 
  #strict {
    width: 60px;
    padding: 5px 10px;
    height: 30px;
  }
}

#basic.active, 
#strict.active {
  background: whitesmoke;
  color: #333;
}

#on-off {
  height: 24px;
  margin: auto calc(100% - 120px);
  display: flex;
  flex-direction: row;
  border-radius: 5px;
}
@media only screen and (min-width: 768px) and (min-height: 560px) {
  #on-off {
    height: 30px;
  }
}

#on-off.glow {
  animation: glowing 2s infinite;
}
@keyframes glowing {
  100% { box-shadow: 0 0 2px 2px yellow; }
}

.switch {
  background: #333;
  border: solid 2px #333;
  width: 20px;
  padding: 5px 10px;
  cursor: pointer;
}

#on { border-radius: 5px 0 0 5px; }
#on.active { background: #388E3C; }

#off { border-radius: 0 5px 5px 0; }
#off.active { background: #D32F2F; }

.colors {
  height: 150px;
  width: 150px;
  cursor: pointer;
  box-shadow: none;
  border: solid #333 4px;
}
@media only screen and (min-width:768px) and (min-height:560px) {
  .colors {
    height: 200px;
    width: 200px;
  }
}
.colors:hover {
/*   box-shadow: inset 0 0 2px 2px #333; */
}

#green {
  background: #27ae60;
  border-radius: 100% 0 0 0;
  border-width: 8px 2px 2px 8px;
}
#green.active { background: #2ecc71; }

#red {
  background: #c0392b;
  border-radius: 0 100% 0 0;
  border-width: 8px 8px 2px 2px;
}
#red.active { background: #e74c3c; }

#yellow {
  background: #f39c12;
  border-radius: 0 0 0 100%;
  border-width: 2px 2px 8px 8px;
}
#yellow.active { background: #f1c40f; }

#blue {
  background: #2980b9;
  border-radius: 0 0 100% 0;
  border-width: 2px 8px 8px 2px;
}
#blue.active { background: #3498db; }

footer {
  color: #9b59b6;
  font-size: 14px;
  clear: left;
  padding: 5px;
  background: rgba(256,256,256,0.7);
}

footer a {
  color: #333;
  text-decoration: none;
}
footer a:hover {
  color: #9b59b6;
  text-decoration: underline;
}


// fix mobile audio delay

var index = 0,
    strict = 0,
    compColors = [],
    // playerColors = [],
    colors = ["green", "red", "yellow", "blue"];

var onOffElt = document.querySelector("#on-off"),
    levelElt = document.querySelector("#level"),
    basicElt = document.querySelector("#basic"),
    strictElt = document.querySelector("#strict"),
    colorElts = document.querySelectorAll(".colors");

// on off button
onOffElt.addEventListener("click", function(e) {
  // turning ON
  if (!this.childNodes[1].classList.contains("active")) {
    onOffElt.classList.remove("glow");
    reset();
    this.childNodes[1].classList.add("active");
    this.childNodes[3].classList.remove("active");
    levelElt.value = "--";
    basicElt.addEventListener("click", start);
    strictElt.addEventListener("click", start);
  }
  //turning OFF
  else if (!this.childNodes[3].classList.contains("active")) {
    reset();
    turnOff();
  }
});
 
// start when basic or strict pressed
function start(e) {
  var curr = e.target;
  if (curr.getAttribute("id") == "basic") {
    if (!curr.classList.contains("active")) {
      reset();
      curr.classList.add("active");
      strictElt.classList.remove("active");
      goo();
    }
    else {
      curr.classList.remove("active");
    }
  }
  else if (curr.getAttribute("id") == "strict") {
    if (!curr.classList.contains("active")) {
      reset();
      strict = 1;
      curr.classList.add("active");
      basicElt.classList.remove("active");
      goo();
    }
    else {
      strict = 0;
      curr.classList.remove("active");
    }
  }
}

function goo() {
  randomizer();
  playList(compColors);
  addColorEvents();
}

// gets a random color and updates round number
function randomizer() {
  var random = Math.floor(Math.random() * 4);
  compColors.push(colors[random]);
  levelElt.value = compColors.length;
  return compColors;
}

function playList(array) {
  var i = 0;
  var interval = setInterval(function() {
    playSong(array[i]);
    i++;
    if (i >= array.length) {
      clearInterval(interval);
    }
  }, 650);
}

function playSong(color) {
  if (color === "green") {
    greenAudio = new Audio("https://s3.amazonaws.com/freecodecamp/simonSound1.mp3");
    greenAudio.play();
    colorElts[0].classList.add("active");
    setTimeout(function() {
      colorElts[0].classList.remove("active");
    }, 200);
  }
  if (color === "red") {
    redAudio = new Audio("https://s3.amazonaws.com/freecodecamp/simonSound2.mp3");
    redAudio.play();
    colorElts[1].classList.add("active");
    setTimeout(function() {
      colorElts[1].classList.remove("active");
    }, 200);
  }
  if (color === "yellow") {
    yellowAudio = new Audio("https://s3.amazonaws.com/freecodecamp/simonSound3.mp3");
    yellowAudio.play();
    colorElts[2].classList.add("active");
    setTimeout(function() {
      colorElts[2].classList.remove("active");
    }, 200);
  }
  if (color === "blue") {
    blueAudio = new Audio("https://s3.amazonaws.com/freecodecamp/simonSound4.mp3");
    blueAudio.play();
    colorElts[3].classList.add("active");
    setTimeout(function() {
      colorElts[3].classList.remove("active");
    }, 200);
  }
}

function checker(e) {
  var currColor = e.target.getAttribute("id");
  playSong(currColor);
  // playerColors.push(currColor);

  // failed the serie
  if (currColor !== compColors[index]) {
    index = 0;
    levelElt.value = "X";
    removeColorEvents();
    if (strict) {
      reset();
      strict = 1;
      setTimeout(function () {
        levelElt.value = "--";
        goo();
      }, 1000);
      return false;
    }
    setTimeout(function() {
      levelElt.value = compColors.length;
      playList(compColors);
      addColorEvents();
    }, 1000);
  }
  // win the serie
  else if (typeof compColors[index+1] === "undefined") {
    removeColorEvents();
    // win the game
    if (typeof compColors[19] !== "undefined") {
      removeColorEvents();
      levelElt.value = "GG";
      setTimeout(function() {
        winAnimation();
      }, 500);
      return false;
    }
    setTimeout(function() {
      index = 0;
      goo();
    }, 1000);
  }
  // win a sound
  else {
    index++;
  }
}

function addColorEvents() {
  for (var j=0; j<colorElts.length; j++) {
    colorElts[j].addEventListener("click", checker);
  }
}

function removeColorEvents() {
  for (var i=0; i<colorElts.length; i++) {
    colorElts[i].removeEventListener("click", checker);
  }
}

function winAnimation() {
  var iterations = 3;
  var sett = setInterval(function() {
    colorElts[0].classList.add("active");
    colorElts[1].classList.add("active");
    colorElts[2].classList.add("active");
    colorElts[3].classList.add("active");
    setTimeout(function(){
      colorElts[0].classList.remove("active");
      colorElts[1].classList.remove("active");
      colorElts[2].classList.remove("active");
      colorElts[3].classList.remove("active");
    }, 200);
    iterations--;
    if (iterations < 1) {
      clearInterval(sett);
    }
  }, 400);
  setTimeout(function() {
    reset();
    turnOff();
  }, 1600);
}

function reset() {
  compColors = [];
  // playerColors = [];
  j = 0;
  strict = 0;
  removeColorEvents()
}

function turnOff() {  
  levelElt.value = "";
  basicElt.removeEventListener("click", start);
  strictElt.removeEventListener("click", start);
  basicElt.classList.remove("active");
  strictElt.classList.remove("active");
  onOffElt.childNodes[1].classList.remove("active");
  onOffElt.childNodes[3].classList.add("active");
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.