FCC Simon Game

In this example below you will see how to do a FCC Simon Game with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by divi-The-Great, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright divi-The-Great ©
  • HTML
  • CSS
  • JavaScript
    <h1>Simon Game</h1>
<section id="plate">
  <div id="one"></div>
  <div id="two"></div>
  <div id="three"></div>
  <div id="four"></div>
  <div id="handler">
    <p id="label">Level 01</p>
    <div class="buttons">
      <button id="start" class="start"></button>
      <button id="strict" class="disabled"></button>
      <br>
      <p id="start-label" class="label">start</p>
      <p class="label">strict</p>
    </div>
  </div>
</section>
<audio id="sound-one" src="https://s3.amazonaws.com/freecodecamp/simonSound1.mp3"></audio>
<audio id="sound-two" src="https://s3.amazonaws.com/freecodecamp/simonSound2.mp3"></audio>
<audio id="sound-three" src="https://s3.amazonaws.com/freecodecamp/simonSound3.mp3"></audio>
<audio id="sound-four" src="https://s3.amazonaws.com/freecodecamp/simonSound4.mp3"></audio>

/*Downloaded from https://www.codeseek.co/divi-The-Great/fcc-simon-game-MOJyJd */
    $bgColor: #cecece;
$plateColor: #424242;
$textColor: #f5f5f5;

@mixin rotate($args...) {
  transform: rotate($args);
  -webkit-transform: rotate($args);
  -ms-transform: rotate($args);
}

@mixin translate($args...) {
  transform: translate($args);
  -webkit-transform: translate($args);
  -ms-transform: translate($args);
}

body {
  font: 16px/1.5em sans-serif;
  margin: 0;
  padding: 0;
  background-color: $bgColor;
}

h1 {
  display: block;
  text-align: center;
  font-size: 3rem;
  margin-top: 8%;
  text-shadow: -12px 12px 15px rgba(#000, 0.1);

  @media screen and (max-width: 24rem) {
    font-size: 2rem;
  }
}

#plate {
  position: relative;
  width: 24rem;
  height: 24rem;
  display: block;
  margin: 4% auto 0;
  padding: 1.3rem;
  background-color: $plateColor;
  border-radius: 100%;
  overflow: hidden;
  box-sizing: border-box;
  box-shadow: 0 0 15px 5px rgba(#000, 0.2);

  @media screen and (max-width: 24rem) {
    width: 16rem;
    height: 16rem;
    margin: 12% auto 0;
    padding: 0.9rem;
  }
}

#one,
#two,
#three,
#four {
  position: absolute;
  display: block;
  width: 10.3rem;
  height: 10.3rem;
  opacity: 0.6;
  cursor: pointer;

  &.enabled {
    opacity: 1;
  }

  @media screen and (max-width: 24rem) {
    width: 7rem;
    height: 7rem;
  }
}

#one {
  border-top-left-radius: 100%;
  background-color: forestgreen;
}

#two {
  border-top-right-radius: 100%;
  background-color: orangered;
}

#three {
  border-bottom-left-radius: 100%;
  background-color: yellow;
}

#four {
  border-bottom-right-radius: 100%;
  background-color: dodgerblue;
}

#two,
#four {
  right: 1.3rem;
  @media screen and (max-width: 24rem) {
    right: 0.9rem;
  }
}

#three,
#four {
  bottom: 1.3rem;
  @media screen and (max-width: 24rem) {
    bottom: 0.9rem;
  }
}

#handler {
  position: absolute;
  width: 11.5rem;
  height: 11.5rem;
  display: block;
  top: 50%;
  left: 50%;
  @include translate(-50%, -50%);
  border-radius: 100%;
  background-color: $plateColor;
  box-shadow: 0px 0px 10px 5px rgba(#000, 0.1);

  @media screen and (max-width: 24rem) {
    width: 8rem;
    height: 8rem;
  }

  p {
    padding: 0.7rem 0 0 0;
    margin-bottom: 1.5rem;
    font-family: "VT323", monospace;
    font-size: 2.4rem;
    color: $textColor;
    text-transform: uppercase;
    text-align: center;
    @media screen and (max-width: 24rem) {
      padding: 0.3rem 0 0 0;
      margin-bottom: 0.7rem;
      font-size: 1.5rem;
    }
  }

  p.label {
    display: inline-block;
    padding-top: 0;
    margin: 0 0.4rem 0 0.4rem;
    font-size: 0.9rem;
    text-align: center;
    opacity: 0.9;
    @media screen and (max-width: 24rem) {
      margin: 0 0.2rem 0 0.2rem;
      font-size: 0.85rem;
    }
  }

  .buttons {
    display: block;
    text-align: center;
  }

  button {
    width: 1.7rem;
    height: 1.7rem;
    display: inline-block;
    margin: 0 0.5rem;
    border: none;
    border-radius: 50%;
    outline: none;
    cursor: pointer;
    box-sizing: border-box;

    &#start {
      background: linear-gradient($textColor, darken($textColor, 10%));
      border-bottom: 3px solid #000;
      &:hover {
        background: linear-gradient(darken($textColor, 5%), $textColor);
        border-bottom-width: 4px;
      }
      &.restart {
        background: linear-gradient(yellow, darken(yellow, 10%));
      }
    }

    &#strict {
      background: linear-gradient(green, darken(green, 10%));
      border-bottom: 3px solid #000;
      &:hover {
        background: linear-gradient(darken(green, 5%), green);
        border-bottom-width: 4px;
      }
      &.disabled {
        background: linear-gradient(red, darken(red, 10%));
      }
    }

    @media screen and (max-width: 24rem) {
      width: 1.3rem;
      height: 1.3rem;
      margin: 0 0.3rem;
    }
  }
}



/*Downloaded from https://www.codeseek.co/divi-The-Great/fcc-simon-game-MOJyJd */
    // declare start and strict buttons
var startBtn = document.getElementById("start");
var startLabel = document.getElementById("start-label");
var strictBtn = document.getElementById("strict");
var label = document.getElementById("label");

function initSimon(startBtn, startLabel, strictBtn, label) {
  // the whole simon game as an object
  function Plate(start, startLabel, strict, label) {
    this.startBtn = start;
    this.startLabel = startLabel;
    this.strictBtn = strict;
    this.label = label;
    this.one = document.getElementById("one");
    this.two = document.getElementById("two");
    this.three = document.getElementById("three");
    this.four = document.getElementById("four");
    this.buttons = [one, two, three, four];
    this.steps = [];
    this.userSteps = [];
    this.userTurn = false;
    this.level = 1;
  }
  var simon = new Plate(startBtn, startLabel, strictBtn, label);

  // a method to add new steps
  Plate.prototype.addSteps = function() {
    var newStep = Math.floor(Math.random() * 4);
    this.steps.push(newStep);
    return this;
  };

  // a method to show the steps
  Plate.prototype.showSteps = function() {
    var delayTime = 500;
    var that = this;
    for (var i = 0; i < that.steps.length; i++) {
      (function(item) {
        var delay = setTimeout(function() {
          that.buttons[that.steps[item]].className = "enabled";
          var sound = "sound-" + that.buttons[that.steps[item]].id;
          document.getElementById(sound).play();
          var clearDelay = setTimeout(function() {
            that.buttons[0].className = "";
            that.buttons[1].className = "";
            that.buttons[2].className = "";
            that.buttons[3].className = "";
          }, 1000);
          if (item === that.steps.length - 1) {
            that.userTurn = true;
            that.userSteps = that.steps.slice(0);
            that.level = that.level + 1;
          }
        }, delayTime);
      })(i);
      delayTime += 1500;
    }
    return this;
  };

  // method when user selects a wrong button
  Plate.prototype.error = function() {
    var that = this;
    console.log(that.level);
    that.level = that.level - 1;
    console.log(that.level);
    that.label.innerHTML = "Try Again";
    that.userSteps = that.steps.slice(0);
    console.log(this.steps);
    var tryagain = setTimeout(function() {
      that.strictBtn.className === "enabled"
        ? that
            .reset()
            .addSteps()
            .showSteps()
        : that.updateLabel().showSteps();
    }, 1000);
    return this;
  };

  // method for starting the next level
  Plate.prototype.nextLevel = function() {
    var that = this;
    if (this.level >= 21) {
      this.label.innerHTML = "You Won!";
      this.userTurn = false;
      return this;
    } else if (this.level < 10) {
      this.label.innerHTML = "Level 0" + this.level;
    } else {
      this.label.innerHTML = "Level " + this.level;
    }
    this.userTurn = false;
    this.addSteps();
    var delay = setTimeout(function() {
      that.showSteps();
    }, 500);
    return this;
  };

  // method for starting the next level
  Plate.prototype.reset = function() {
    this.level = 1;
    this.label.innerHTML = "Level 0" + "1";
    this.userTurn = false;
    this.steps = [];
    this.userSteps = [];
    return this;
  };

  // update label when an error occured in non-stricted mode
  Plate.prototype.updateLabel = function() {
    if (simon.level < 10) {
      simon.label.innerHTML = "Level 0" + simon.level;
    } else {
      simon.label.innerHTML = "Level " + simon.level;
    }
    return this;
  };

  // start the game when the start button is clicked
  simon.startBtn.onclick = function(e) {
    var that = this;
    if (that.className === "start") {
      that.className = "restart";
      simon.startLabel.innerHTML = "restart";
      simon
        .reset()
        .addSteps()
        .showSteps();
    } else {
      that.className = "start";
      var flashBtn = setTimeout(function() {
        that.className = "restart";
      }, 100);
      console.log(simon.userTurn);
      if (simon.userTurn === true || simon.level >= 21) {
        console.log(simon.userTurn);
        simon
          .reset()
          .addSteps()
          .showSteps();
      }
    }
  };

  // toggle the strict state
  simon.strictBtn.onclick = function(e) {
    var that = this;
    that.className === "enabled"
      ? (this.className = "disabled")
      : (this.className = "enabled");
  };

  // user turn
  simon.buttons.forEach(function(item) {
    item.onclick = function(e) {
      var that = this;
      if (simon.userTurn === true) {
        that.className = "enabled";
        simon.userTurn = false;
        var sound = "sound-" + that.id;
        document.getElementById(sound).play();

        if (simon.buttons.indexOf(that) === simon.userSteps[0]) {
          simon.userSteps.shift();
          var duration = setTimeout(function() {
            that.className = "";
            simon.userTurn = true;
            if (simon.userSteps.length < 1) {
              console.log("yeah");
              simon.nextLevel();
            }
          }, 200);
        } else {
          simon.error();
          var duration = setTimeout(function() {
            that.className = "";
          }, 1000);
        }
      }
    };
  });
}

initSimon(startBtn, startLabel, strictBtn, label);


Comments