Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Neon Tic-Tac-Toe</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap'); | |
body { | |
font-family: 'Orbitron', sans-serif; | |
background-color: #0f0f1a; | |
overflow: hidden; | |
perspective: 1000px; | |
height: 100vh; | |
width: 100vw; | |
} | |
.glass-box { | |
background: rgba(15, 15, 30, 0.2); | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); | |
border-radius: 10px; | |
transition: all 0.3s ease; | |
} | |
.cell { | |
position: relative; | |
transition: all 0.3s ease; | |
transform-style: preserve-3d; | |
} | |
.cell:hover { | |
transform: translateZ(20px); | |
box-shadow: 0 0 20px rgba(0, 255, 255, 0.7); | |
} | |
.cell::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
border-radius: 8px; | |
background: linear-gradient(135deg, rgba(0, 255, 255, 0.1), rgba(255, 0, 255, 0.1)); | |
opacity: 0; | |
transition: opacity 0.3s ease; | |
} | |
.cell:hover::before { | |
opacity: 1; | |
} | |
.x-symbol { | |
color: #ff2d75; | |
text-shadow: 0 0 10px #ff2d75, 0 0 20px #ff2d75; | |
} | |
.o-symbol { | |
color: #00ffff; | |
text-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff; | |
} | |
.winning-cell { | |
animation: pulse 0.5s infinite alternate; | |
} | |
@keyframes pulse { | |
0% { | |
transform: scale(1) translateZ(0); | |
box-shadow: 0 0 10px currentColor; | |
} | |
100% { | |
transform: scale(1.1) translateZ(10px); | |
box-shadow: 0 0 30px currentColor; | |
} | |
} | |
.confetti { | |
position: absolute; | |
width: 10px; | |
height: 10px; | |
background-color: currentColor; | |
opacity: 0; | |
} | |
.bg-pattern { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
z-index: -1; | |
opacity: 0.1; | |
} | |
.bg-symbol { | |
position: absolute; | |
font-size: 1rem; | |
opacity: 0; | |
animation: float 15s linear infinite; | |
pointer-events: none; | |
} | |
@keyframes float { | |
0% { | |
transform: translateY(100vh) rotate(0deg); | |
opacity: 0; | |
} | |
10% { | |
opacity: 0.3; | |
} | |
90% { | |
opacity: 0.3; | |
} | |
100% { | |
transform: translateY(-100px) rotate(360deg); | |
opacity: 0; | |
} | |
} | |
.explosion { | |
position: absolute; | |
width: 10px; | |
height: 10px; | |
border-radius: 50%; | |
background-color: white; | |
opacity: 0; | |
} | |
.smoke { | |
position: absolute; | |
width: 20px; | |
height: 20px; | |
border-radius: 50%; | |
background-color: rgba(255, 255, 255, 0.3); | |
opacity: 0; | |
} | |
.neon-text { | |
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #00ffff, 0 0 20px #00ffff; | |
} | |
.neon-border { | |
box-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff inset; | |
} | |
</style> | |
</head> | |
<body class="h-screen w-screen flex flex-col items-center justify-center p-4 overflow-hidden"> | |
<div class="bg-pattern" id="bgPattern"></div> | |
<div class="text-center mb-8"> | |
<h1 class="text-4xl md:text-5xl font-bold text-white neon-text mb-2">NEON TIC-TAC-TOE</h1> | |
<div class="flex justify-center space-x-8 text-white text-xl"> | |
<div class="glass-box px-4 py-2 rounded-lg"> | |
<span class="text-pink-500">X</span> Wins: <span id="xWins" class="text-white">0</span> | |
</div> | |
<div class="glass-box px-4 py-2 rounded-lg"> | |
<span class="text-cyan-400">O</span> Wins: <span id="oWins" class="text-white">0</span> | |
</div> | |
<div class="glass-box px-4 py-2 rounded-lg"> | |
<span class="text-yellow-400">Draws:</span> <span id="draws" class="text-white">0</span> | |
</div> | |
</div> | |
</div> | |
<div class="relative"> | |
<div id="gameBoard" class="grid grid-cols-3 gap-4 glass-box p-6 rounded-xl neon-border"> | |
<!-- Cells will be generated by JavaScript --> | |
</div> | |
</div> | |
<div class="mt-8"> | |
<button id="resetBtn" class="glass-box px-6 py-3 rounded-lg text-white text-lg font-bold hover:bg-cyan-500 hover:text-white transition-all duration-300 hover:scale-105"> | |
RESET GAME | |
</button> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
// Game state | |
let board = ['', '', '', '', '', '', '', '', '']; | |
let currentPlayer = 'X'; | |
let gameActive = true; | |
let xWins = 0; | |
let oWins = 0; | |
let draws = 0; | |
// DOM elements | |
const gameBoard = document.getElementById('gameBoard'); | |
const xWinsElement = document.getElementById('xWins'); | |
const oWinsElement = document.getElementById('oWins'); | |
const drawsElement = document.getElementById('draws'); | |
const resetBtn = document.getElementById('resetBtn'); | |
const bgPattern = document.getElementById('bgPattern'); | |
// Create background floating symbols | |
createFloatingSymbols(); | |
// Create game board cells | |
createBoard(); | |
// Create floating symbols in background | |
function createFloatingSymbols() { | |
for (let i = 0; i < 30; i++) { | |
const symbol = document.createElement('div'); | |
symbol.className = `bg-symbol ${Math.random() > 0.5 ? 'x-symbol' : 'o-symbol'}`; | |
symbol.innerHTML = Math.random() > 0.5 ? '×' : '○'; | |
symbol.style.left = `${Math.random() * 100}%`; | |
symbol.style.animationDuration = `${10 + Math.random() * 20}s`; | |
symbol.style.animationDelay = `${Math.random() * 5}s`; | |
bgPattern.appendChild(symbol); | |
} | |
} | |
// Create game board | |
function createBoard() { | |
gameBoard.innerHTML = ''; | |
for (let i = 0; i < 9; i++) { | |
const cell = document.createElement('div'); | |
cell.className = 'cell w-20 h-20 md:w-24 md:h-24 flex items-center justify-center text-5xl glass-box cursor-pointer'; | |
cell.setAttribute('data-index', i); | |
cell.addEventListener('click', handleCellClick); | |
// Add hover effect that throws symbols | |
cell.addEventListener('mousemove', (e) => { | |
if (cell.textContent !== '' || !gameActive) return; | |
const rect = cell.getBoundingClientRect(); | |
const x = e.clientX - rect.left; | |
const y = e.clientY - rect.top; | |
const symbol = document.createElement('div'); | |
symbol.className = `absolute text-xl ${currentPlayer === 'X' ? 'x-symbol' : 'o-symbol'}`; | |
symbol.textContent = currentPlayer === 'X' ? '×' : '○'; | |
symbol.style.left = `${x}px`; | |
symbol.style.top = `${y}px`; | |
symbol.style.opacity = '0'; | |
symbol.style.transform = 'scale(0)'; | |
symbol.style.transition = 'all 0.5s ease-out'; | |
cell.appendChild(symbol); | |
setTimeout(() => { | |
symbol.style.opacity = '0.7'; | |
symbol.style.transform = 'scale(1) translate(-50%, -50%)'; | |
setTimeout(() => { | |
symbol.style.opacity = '0'; | |
symbol.style.transform = 'scale(0.5) translate(-50%, -50%)'; | |
setTimeout(() => { | |
cell.removeChild(symbol); | |
}, 500); | |
}, 300); | |
}, 10); | |
}); | |
gameBoard.appendChild(cell); | |
} | |
} | |
// Handle cell click | |
function handleCellClick(e) { | |
const cell = e.target; | |
const index = parseInt(cell.getAttribute('data-index')); | |
if (board[index] !== '' || !gameActive) return; | |
// Update board | |
board[index] = currentPlayer; | |
cell.textContent = currentPlayer; | |
cell.classList.add(currentPlayer === 'X' ? 'x-symbol' : 'o-symbol'); | |
// Add animation | |
cell.style.transform = 'translateZ(30px)'; | |
cell.style.boxShadow = `0 0 30px ${currentPlayer === 'X' ? '#ff2d75' : '#00ffff'}`; | |
setTimeout(() => { | |
cell.style.transform = 'translateZ(10px)'; | |
cell.style.boxShadow = `0 0 20px ${currentPlayer === 'X' ? '#ff2d75' : '#00ffff'}`; | |
}, 300); | |
// Check for winner | |
if (checkWinner()) { | |
gameActive = false; | |
celebrateWin(); | |
return; | |
} | |
// Check for draw | |
if (!board.includes('')) { | |
gameActive = false; | |
draws++; | |
drawsElement.textContent = draws; | |
setTimeout(() => { | |
alert('Game ended in a draw!'); | |
}, 500); | |
return; | |
} | |
// Switch player | |
currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; | |
// Add floating indicator | |
const indicator = document.createElement('div'); | |
indicator.className = `absolute -top-8 text-xl ${currentPlayer === 'X' ? 'x-symbol' : 'o-symbol'}`; | |
indicator.textContent = currentPlayer === 'X' ? '×' : '○'; | |
indicator.style.opacity = '0'; | |
indicator.style.transform = 'translateY(20px)'; | |
gameBoard.parentNode.appendChild(indicator); | |
setTimeout(() => { | |
indicator.style.opacity = '1'; | |
indicator.style.transform = 'translateY(0)'; | |
setTimeout(() => { | |
indicator.style.opacity = '0'; | |
indicator.style.transform = 'translateY(-20px)'; | |
setTimeout(() => { | |
gameBoard.parentNode.removeChild(indicator); | |
}, 500); | |
}, 1000); | |
}, 10); | |
} | |
// Check for winner | |
function checkWinner() { | |
const winningCombos = [ | |
[0, 1, 2], [3, 4, 5], [6, 7, 8], // rows | |
[0, 3, 6], [1, 4, 7], [2, 5, 8], // columns | |
[0, 4, 8], [2, 4, 6] // diagonals | |
]; | |
for (let combo of winningCombos) { | |
const [a, b, c] = combo; | |
if (board[a] && board[a] === board[b] && board[a] === board[c]) { | |
// Highlight winning cells | |
document.querySelectorAll(`[data-index="${a}"], [data-index="${b}"], [data-index="${c}"]`).forEach(cell => { | |
cell.classList.add('winning-cell'); | |
}); | |
// Update score | |
if (board[a] === 'X') { | |
xWins++; | |
xWinsElement.textContent = xWins; | |
} else { | |
oWins++; | |
oWinsElement.textContent = oWins; | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
// Celebrate win with confetti | |
function celebrateWin() { | |
const winner = currentPlayer; | |
const color = winner === 'X' ? '#ff2d75' : '#00ffff'; | |
for (let i = 0; i < 100; i++) { | |
const confetti = document.createElement('div'); | |
confetti.className = 'confetti'; | |
confetti.style.backgroundColor = color; | |
confetti.style.left = `${Math.random() * 100}%`; | |
confetti.style.top = `${Math.random() * 100}%`; | |
confetti.style.transform = `rotate(${Math.random() * 360}deg)`; | |
const size = Math.random() * 10 + 5; | |
confetti.style.width = `${size}px`; | |
confetti.style.height = `${size}px`; | |
if (Math.random() > 0.5) { | |
confetti.style.borderRadius = '50%'; | |
} | |
document.body.appendChild(confetti); | |
setTimeout(() => { | |
confetti.style.opacity = '1'; | |
confetti.style.transform = `translate(${Math.random() * 200 - 100}px, ${Math.random() * 200 + 100}px) rotate(${Math.random() * 360}deg)`; | |
setTimeout(() => { | |
confetti.style.opacity = '0'; | |
setTimeout(() => { | |
document.body.removeChild(confetti); | |
}, 1000); | |
}, 2000); | |
}, i * 20); | |
} | |
// Add celebration text | |
const celebration = document.createElement('div'); | |
celebration.className = 'absolute inset-0 flex items-center justify-center pointer-events-none'; | |
celebration.innerHTML = `<div class="text-6xl font-bold ${winner === 'X' ? 'x-symbol' : 'o-symbol'} opacity-0 transform scale(0)">${winner} WINS!</div>`; | |
gameBoard.parentNode.appendChild(celebration); | |
setTimeout(() => { | |
celebration.firstChild.style.opacity = '1'; | |
celebration.firstChild.style.transform = 'scale(1)'; | |
setTimeout(() => { | |
celebration.firstChild.style.opacity = '0'; | |
celebration.firstChild.style.transform = 'scale(1.5)'; | |
setTimeout(() => { | |
gameBoard.parentNode.removeChild(celebration); | |
}, 500); | |
}, 2000); | |
}, 100); | |
} | |
// Reset game | |
resetBtn.addEventListener('click', () => { | |
// Create explosion effect | |
const cells = document.querySelectorAll('.cell'); | |
cells.forEach(cell => { | |
if (cell.textContent !== '') { | |
// Create explosion particles | |
for (let i = 0; i < 10; i++) { | |
const particle = document.createElement('div'); | |
particle.className = 'explosion'; | |
particle.style.left = `${Math.random() * 80 + 10}%`; | |
particle.style.top = `${Math.random() * 80 + 10}%`; | |
particle.style.backgroundColor = cell.classList.contains('x-symbol') ? '#ff2d75' : '#00ffff'; | |
cell.appendChild(particle); | |
setTimeout(() => { | |
particle.style.opacity = '1'; | |
particle.style.transform = `translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px) scale(${Math.random() * 2 + 1})`; | |
setTimeout(() => { | |
particle.style.opacity = '0'; | |
setTimeout(() => { | |
if (cell.contains(particle)) { | |
cell.removeChild(particle); | |
} | |
}, 500); | |
}, 300); | |
}, 10); | |
} | |
// Create smoke | |
for (let i = 0; i < 5; i++) { | |
const smoke = document.createElement('div'); | |
smoke.className = 'smoke'; | |
smoke.style.left = `${Math.random() * 80 + 10}%`; | |
smoke.style.top = `${Math.random() * 80 + 10}%`; | |
cell.appendChild(smoke); | |
setTimeout(() => { | |
smoke.style.opacity = '0.5'; | |
smoke.style.transform = `translate(${Math.random() * 40 - 20}px, ${Math.random() * 40 - 20}px) scale(${Math.random() * 3 + 1})`; | |
setTimeout(() => { | |
smoke.style.opacity = '0'; | |
setTimeout(() => { | |
if (cell.contains(smoke)) { | |
cell.removeChild(smoke); | |
} | |
}, 500); | |
}, 1000); | |
}, 10); | |
} | |
} | |
}); | |
// Reset game state after animation | |
setTimeout(() => { | |
board = ['', '', '', '', '', '', '', '', '']; | |
currentPlayer = 'X'; | |
gameActive = true; | |
// Remove all winning cell classes | |
document.querySelectorAll('.cell').forEach(cell => { | |
cell.className = 'cell w-20 h-20 md:w-24 md:h-24 flex items-center justify-center text-5xl glass-box cursor-pointer'; | |
cell.textContent = ''; | |
}); | |
// Create a new board (for visual refresh) | |
createBoard(); | |
}, 1000); | |
}); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=miiann/tic-toc-toe" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |