JSFiddle - React, Tailwind, and code Playground

by mostafa91

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Audiowide">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Aclonica">
  <link rel="stylesheet" href="./styles/Gameboard.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <!-- <script src="Gameboard.js" defer></script> -->
  <script src="../scripts/Gameboard.js"></script>
  <title>Document</title>
</head>
<body>
    <h1 id="h1"><a2 href="#" class="previous round" onclick="back()" id="back">&#8249;</a2>
        NOUGHTS & CROSSES</h1>
        <div class="dropdown"> 
        <h2 id="h2"><button class="dropbtn" id="Themes">Themes</button>
        <div class="dropdown-content">
        <a href="#" onclick="space()">Space Theme</a>
        <a href="#" onclick="wooden()">Wooden Theme</a>
        <a href="#" onclick="medieval()">Medieval Theme</a>
        </div>
        </div>
        </h2><br><br><br>
        <h3 id="h3">Please choose an option to start</h3>
        <button onclick ="Ai()" id="AI">vs. AI</button><br>
        <div class="difficulty" id="difficulty">
            <button onclick="vsAi()">Easy</button><br>
            <button onclick="vsAi()">Medium</button><br>
            <button onclick="vsAi()">Hard</button><br>
        </div>
        <button onclick ="vsPlayer()" id="Player">vs. Player</button>
        <div class="hiddenboard" id="hiddenboard">
  <div class="board" id="board">
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
    <div class="cell" data-cell></div>
...

CSS

*, *::after, *::before {
    box-sizing: border-box;
  }
  
  :root {
    --cell-size: 100px;
    --mark-size: calc(var(--cell-size) * .9);
  }
  
  body {
    margin: 0;
  }
  
  .board {
    display: grid;
    justify-content: center;
    align-content: center;
    justify-items: center;
    align-items: center;
    grid-template-columns: repeat(3, auto)
  }
  
  .cell {
    width: var(--cell-size);
    height: var(--cell-size);
    border: 3px solid white;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    cursor: pointer;
  }
  
  .cell:first-child,
  .cell:nth-child(2),
  .cell:nth-child(3) {
    border-top: none;
  }
  
  .cell:nth-child(3n + 1) {
    border-left: none;
  }
  
  .cell:nth-child(3n + 3) {
    border-right: none;
  }
  
  .cell:last-child,
  .cell:nth-child(8),
  .cell:nth-child(7) {
    border-bottom: none;
  }
  
  .cell.x,
  .cell.circle {
    cursor: not-allowed;
  }
  
  .cell.x::before{
      background-color: #fdbf00;
  }
  .cell.x::after{
      background-color: #fdbf00;
  }
  .cell.circle::before {
    background-color: #ff4949;
  }
  
  .board.x .cell:not(.x):not(.circle):hover::before,
  .board.x .cell:not(.x):not(.circle):hover::after,
  .board.circle .cell:not(.x):not(.circle):hover::before {
    background-color: lightgrey;
  }
  
  .cell.x::before,
  .cell.x::after,
  .board.x .cell:not(.x):not(.circle):hover::before,
  .board.x .cell:not(.x):not(.circle):hover::after {
    content: '';
    position: absolute;
    width: calc(var(--mark-size) * .15);
    height: var(--mark-size);
  }
  
  .cell.x::before,
  .board.x .cell:not(.x):not(.circle):hover::before {
    transform: rotate(45deg);
  }
  
  .cell.x::after,
  .board.x .cell:not(.x):not(.circle):hover::after {
    transform: rotate(-45deg);
  }
  
  .cell.circle::before,
  .cell.circle::after,
  .board.circle .cell:not(.x):not(.circle):hover::before,
  .board.circle .cell:not(.x):not(.circle):hover::after {
    content: '';
...

JavaScript

const X_CLASS = 'x'
const CIRCLE_CLASS = 'circle'
const WINNING_COMBINATIONS = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6]
]
const cellElements = document.querySelectorAll('[data-cell]')
const board = document.getElementById('board')
const winningMessageElement = document.getElementById('winningMessage')
const restartButton = document.getElementById('restartButton')
const winningMessageTextElement = document.querySelector('[data-winning-message-text]')
let circleTurn

startGame()

restartButton.addEventListener('click', startGame)

function startGame() {
  circleTurn = false
  cellElements.forEach(cell => {
    cell.classList.remove(X_CLASS)
    cell.classList.remove(CIRCLE_CLASS)
    cell.removeEventListener('click', handleClick)
    cell.addEventListener('click', handleClick, { once: true })
  })
  setBoardHoverClass()
  winningMessageElement.classList.remove('show')
}

function handleClick(e) {
  const cell = e.target
  const currentClass = circleTurn ? CIRCLE_CLASS : X_CLASS
  placeMark(cell, currentClass)
  if (checkWin(currentClass)) {
    endGame(false)
  } else if (isDraw()) {
    endGame(true)
  } else {
    swapTurns()
    setBoardHoverClass()
  }
}

function endGame(draw) {
  if (draw) {
    winningMessageTextElement.innerText = 'Draw!'
  } else {
    winningMessageTextElement.innerText = `${circleTurn ? "O's" : "X's"} Wins!`
  }
  winningMessageElement.classList.add('show')
}

function isDraw() {
  return [...cellElements].every(cell => {
    return cell.classList.contains(X_CLASS) || cell.classList.contains(CIRCLE_CLASS)
  })
}

function placeMark(cell, currentClass) {
  cell.classList.add(currentClass)
}

function swapTurns() {
  circleTurn = !circleTurn
}

function setBoardHoverClass() {
  board.classList.remove(X_CLASS)
  board.classList.remove(CIRCLE_CLASS)
  if (circleTurn) {
    board.classList.add(CIRCLE_CLASS)
  } else {
    board.classList.add(X_CLASS)
  }
}

function...