JSFiddle - React, Tailwind, and code Playground

by Sébastien Lorentz

HTML

<table id="simon">
    <tr>
      <td><button id="green" /></td>
      <td><button id="red" /></td>
    </tr>
    <tr>
      <td><button id="yellow" /></td>
      <td><button id="blue" /></td>
    </tr>
  </table>

CSS

button {
  height: 100px;
  width: 100px;
  display:block;
}

button.light, button:active {
  filter: brightness(500%);
}

table {
  margin: 50px;
  transform: rotate(45deg)
}

table.playingHints * {
  cursor: not-allowed;
}

table.playingHints button {
  pointer-events: none;
}

#green {
  background-color: darkgreen;
}
#yellow {
  background-color: #999900;
}
#red {
  background-color: darkred;
}
#blue {
  background-color: darkblue;
}

JavaScript

const colors = ['green', 'red', 'yellow', 'blue']

class Game {
  constructor() {
    this.btns = colors.map(id => document.getElementById(id))
    this.simon = document.getElementById('simon')

    this.round = []
    this.guess = []
    this.btns.forEach(el => el.addEventListener('click', () => {
      this.guess.push(colors.indexOf(el.id))
      this.checkUserRun()
    }))
  }

  prepareNextStep() {
    this.guess = []
    this.round.push(Math.floor(Math.random() * 4))
  }

  startNewGame() {
    this.round = []
    this.prepareNextStep()
    game.startHints()
  }

  async startHints() {
    this.simon.classList.add('playingHints')
    let i = 0
    while (i <= this.round.length - 1) {
      await new Promise(resolve => setInterval(resolve, 500))
      this.btns[(this.round[i])].classList.add('light')
      await new Promise(resolve => setInterval(resolve, 500))
      this.btns[(this.round[i])].classList.remove('light')
      i++
    }
    this.simon.classList.remove('playingHints')
  }

  checkUserRun() {
    if (this.guess[this.guess.length - 1] !== this.round[this.guess.length - 1]) {
      alert(`Your score is ${this.round.length - 1}`)
      this.startNewGame()
    } else if (this.guess.length === this.round.length) {
      this.prepareNextStep()
      this.startHints()
    }
  }
}

const game = new Game()
setTimeout(() => {
  game.startNewGame()
}, 1000);