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">‹</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...