
Tic tac toe.
First test
Prompt
Create an Tic tac toe game, add thing to make him more spécial and spicy
A system prompt was added to support web rendering
Of course! Here is a "Spicy" Tic-Tac-Toe game. Instead of a standard game, some squares are secretly "spicy"! Clicking them will trigger a random event: * **🌶️ BOMB:** Destroys a random opponent's piece next to it. * **🌶️ SHUFFLE:** All pieces on the board are randomly scrambled! * **🌶️ BONUS TURN:** You get to go again immediately. The spicy squares are marked with a subtle glow—you won't know the effect until you claim the square! ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spicy Tic-Tac-Toe</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Bungee&display=swap" rel="stylesheet"> <style> :root { --board-bg: #1a1a1a; --cell-bg: #2c2c2c; --border-color: #444; --player-x-color: #ff4757; /* Neon Red/Pink */ --player-o-color: #5352ed; /* Neon Blue/Purple */ --text-color: #f1f2f6; --spicy-glow: #f9ca24; /* Gold/Yellow */ --win-bg: #f9ca24; --font-main: 'Bungee', cursive; } body { background-color: var(--board-bg); color: var(--text-color); font-family: 'Arial', sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; text-align: center; } #game-container { display: flex; flex-direction: column; align-items: center; gap: 20px; } h1 { font-family: var(--font-main); font-size: 3rem; color: var(--text-color); text-shadow: 0 0 5px var(--player-x-color), 0 0 10px var(--player-o-color); margin-bottom: 0; } #game-board { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); gap: 10px; background-color: var(--board-bg); padding: 10px; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.5); } .cell { width: 100px; height: 100px; background-color: var(--cell-bg); border: 2px solid var(--border-color); border-radius: 5px; display: flex; justify-content: center; align-items: center; font-size: 4rem; font-weight: bold; cursor: pointer; transition: background-color 0.3s ease, transform 0.2s ease; position: relative; font-family: var(--font-main); } .cell:hover { background-color: #3d3d3d; transform: scale(1.05); } .cell.x { color: var(--player-x-color); text-shadow: 0 0 10px var(--player-x-color); } .cell.o { color: var(--player-o-color); text-shadow: 0 0 10px var(--player-o-color); } .cell.spicy::before { content: '🌶️'; position: absolute; font-size: 1.5rem; top: 5px; right: 5px; opacity: 0.7; animation: spicy-pulse 2s infinite; } @keyframes spicy-pulse { 0% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(1); opacity: 0.7; } } .cell.winning-cell { background-color: var(--win-bg); animation: win-pulse 1s infinite; } @keyframes win-pulse { 0% { background-color: var(--win-bg); } 50% { background-color: #ffdd59; } 100% { background-color: var(--win-bg); } } #status-container { min-height: 50px; display: flex; align-items: center; justify-content: center; } #status { font-size: 1.5rem; font-family: var(--font-main); transition: all 0.3s ease; } .status-enter { opacity: 0; transform: translateY(-20px); } #restart-button { font-family: var(--font-main); background: linear-gradient(45deg, var(--player-x-color), var(--player-o-color)); color: white; border: none; padding: 15px 30px; font-size: 1.2rem; border-radius: 50px; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; box-shadow: 0 4px 15px rgba(0,0,0,0.4); } #restart-button:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,0.5); } #modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; z-index: 1000; } #modal-overlay.show { opacity: 1; visibility: visible; } #modal-content { background: var(--cell-bg); padding: 40px; border-radius: 15px; text-align: center; border: 2px solid var(--spicy-glow); box-shadow: 0 0 30px var(--spicy-glow); transform: scale(0.8); transition: transform 0.3s ease; } #modal-overlay.show #modal-content { transform: scale(1); } #modal-message { font-family: var(--font-main); font-size: 2.5rem; margin-bottom: 30px; } </style> </head> <body> <div id="game-container"> <h1>Spicy Tic-Tac-Toe</h1> <div id="game-board"></div> <div id="status-container"> <div id="status"></div> </div> <button id="restart-button">Restart Game</button> </div> <div id="modal-overlay"> <div id="modal-content"> <div id="modal-message"></div> <button id="play-again-button">Play Again</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const boardElement = document.getElementById('game-board'); const statusElement = document.getElementById('status'); const restartButton = document.getElementById('restart-button'); const modalOverlay = document.getElementById('modal-overlay'); const modalMessageElement = document.getElementById('modal-message'); const playAgainButton = document.getElementById('play-again-button'); let boardState = Array(9).fill(''); let currentPlayer = 'X'; let isGameActive = true; let spicySquares = []; const winningConditions = [ [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 ]; const displayStatus = (message, isSpicy = false) => { statusElement.classList.add('status-enter'); statusElement.innerHTML = message; statusElement.style.color = isSpicy ? 'var(--spicy-glow)' : 'var(--text-color)'; setTimeout(() => statusElement.classList.remove('status-enter'), 10); }; const initializeGame = () => { boardState.fill(''); currentPlayer = 'X'; isGameActive = true; spicySquares = []; boardElement.innerHTML = ''; modalOverlay.classList.remove('show'); // Determine 2 or 3 spicy squares const numSpicy = Math.floor(Math.random() * 2) + 2; while (spicySquares.length < numSpicy) { const randomIndex = Math.floor(Math.random() * 9); if (!spicySquares.includes(randomIndex)) { spicySquares.push(randomIndex); } } boardState.forEach((_, index) => { const cell = document.createElement('div'); cell.classList.add('cell'); cell.dataset.index = index; if(spicySquares.includes(index)) { cell.classList.add('spicy'); } cell.addEventListener('click', handleCellClick); boardElement.appendChild(cell); }); displayStatus(`Player <span style="color:var(--player-x-color)">X</span>'s turn`); }; const handleCellClick = (event) => { const clickedCell = event.target; const clickedCellIndex = parseInt(clickedCell.dataset.index); if (boardState[clickedCellIndex] !== '' || !isGameActive) { return; } if (clickedCell.classList.contains('spicy')) { handleSpicyTurn(clickedCell, clickedCellIndex); } else { handleNormalTurn(clickedCell, clickedCellIndex); } }; const placeMark = (cell, index) => { boardState[index] = currentPlayer; cell.textContent = currentPlayer; cell.classList.add(currentPlayer.toLowerCase()); }; const handleNormalTurn = (cell, index) => { placeMark(cell, index); if (checkResult()) return; switchPlayer(); }; const handleSpicyTurn = (cell, index) => { cell.classList.remove('spicy'); const spicyEvent = Math.floor(Math.random() * 3); placeMark(cell, index); switch (spicyEvent) { case 0: // BOMB handleBombEvent(index); break; case 1: // SHUFFLE handleShuffleEvent(); break; case 2: // BONUS TURN handleBonusTurnEvent(); return; // Skip player switch } if (checkResult()) return; switchPlayer(); }; const handleBombEvent = (bombIndex) => { displayStatus('🌶️ BOMB! An opponent piece was destroyed!', true); const adjacent = [ bombIndex-3, bombIndex+3, // Above, Below (bombIndex % 3 !== 0) ? bombIndex-1 : -1, // Left (bombIndex % 3 !== 2) ? bombIndex+1 : -1, // Right ].filter(i => i >= 0 && i < 9); const opponent = currentPlayer === 'X' ? 'O' : 'X'; const opponentPieces = adjacent.filter(i => boardState[i] === opponent); if(opponentPieces.length > 0) { const targetIndex = opponentPieces[Math.floor(Math.random() * opponentPieces.length)]; boardState[targetIndex] = ''; document.querySelector(`.cell[data-index='${targetIndex}']`).textContent = ''; document.querySelector(`.cell[data-index='${targetIndex}']`).classList.remove('x', 'o'); } }; const handleShuffleEvent = () => { displayStatus('🌶️ SHUFFLE! The board is a mess!', true); let occupiedIndices = []; let pieces = []; boardState.forEach((piece, i) => { if (piece !== '') { occupiedIndices.push(i); pieces.push(piece); } }); // Fisher-Yates shuffle for (let i = pieces.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [pieces[i], pieces[j]] = [pieces[j], pieces[i]]; } occupiedIndices.forEach((originalIndex, i) => { boardState[originalIndex] = pieces[i]; const cell = document.querySelector(`.cell[data-index='${originalIndex}']`); cell.textContent = pieces[i]; cell.classList.remove('x', 'o'); cell.classList.add(pieces[i].toLowerCase()); }); }; const handleBonusTurnEvent = () => { displayStatus(`🌶️ BONUS! Player <span style="color:${currentPlayer === 'X' ? 'var(--player-x-color)' : 'var(--player-o-color)'}">${currentPlayer}</span> goes again!`, true); // The turn just doesn't switch. if (checkResult()) return; }; const switchPlayer = () => { currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; const color = currentPlayer === 'X' ? 'var(--player-x-color)' : 'var(--player-o-color)'; displayStatus(`Player <span style="color:${color}">${currentPlayer}</span>'s turn`); }; const checkResult = () => { let roundWon = false; let winningLine = []; for (let i = 0; i < winningConditions.length; i++) { const winCondition = winningConditions[i]; const a = boardState[winCondition[0]]; const b = boardState[winCondition[1]]; const c = boardState[winCondition[2]]; if (a === '' || b === '' || c === '') { continue; } if (a === b && b === c) { roundWon = true; winningLine = winCondition; break; } } if (roundWon) { endGame(false, winningLine); return true; } if (!boardState.includes('')) { endGame(true); return true; } return false; }; const endGame = (isDraw, winningLine = []) => { isGameActive = false; winningLine.forEach(index => { document.querySelector(`.cell[data-index='${index}']`).classList.add('winning-cell'); }); if (isDraw) { modalMessageElement.innerHTML = "It's a Draw!"; } else { const winnerColor = currentPlayer === 'X' ? 'var(--player-x-color)' : 'var(--player-o-color)'; modalMessageElement.innerHTML = `Player <span style="color:${winnerColor}">${currentPlayer}</span> Wins!`; } displayStatus('Game Over!'); setTimeout(() => modalOverlay.classList.add('show'), 1000); }; restartButton.addEventListener('click', initializeGame); playAgainButton.addEventListener('click', initializeGame); initializeGame(); }); </script> </body> </html> ```
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Spicy Tic-Tac-Toe</title> <style> /* ----------- BASIC LAYOUT ------------ */ html,body{ height:100%; margin:0; display:flex; justify-content:center; align-items:center; background:#0e0e10; color:#ffffff; font-family:"Segoe UI",Roboto,Helvetica,Arial,sans-serif; } #wrapper{ text-align:center; } h1{ margin-top:0; margin-bottom:10px; font-weight:600; text-shadow:0 0 10px #00ffff; } /* ------------- GRID ------------------ */ #game{ display:grid; grid-template-columns:repeat(3,120px); grid-gap:10px; margin:auto; } .cell{ width:120px; height:120px; background:#111; border:2px solid #333; cursor:pointer; position:relative; transition:transform .25s; } .cell:hover{ box-shadow:0 0 12px #00ffff; transform:scale(1.05); } .cell.X::after, .cell.O::after{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); font-size:78px; font-weight:700; text-shadow:0 0 22px currentColor; } .cell.X::after{content:'X';color:#00eaff;} .cell.O::after{content:'O';color:#ff006a;} /* ------------- WIN GLOW -------------- */ @keyframes bling{ 0% {box-shadow:0 0 6px #ffff00;} 100%{box-shadow:0 0 30px #ff3300;} } .win{ animation:bling .5s infinite alternate; } /* -------------- BUTTONS -------------- */ .controls{margin-top:18px;} button{ background:#222; border:none; color:#fff; padding:8px 14px; margin:4px; border-radius:5px; cursor:pointer; transition:background .2s,transform .2s; } button:hover{background:#444;transform:translateY(-2px);} button:disabled{background:#555;cursor:not-allowed;transform:none;} #status{ margin-top:14px; font-size:20px; min-height:26px; } /* ------------- CONFETTI ------------- */ canvas#confetti{ position:fixed; top:0;left:0; pointer-events:none; z-index:50; } </style> </head> <body> <div id="wrapper"> <h1>✨ Spicy Tic-Tac-Toe ✨</h1> <div id="game"></div> <div class="controls"> <button id="resetBtn">Restart 🔄</button> <button id="modeBtn">Play vs Friend 👫</button> <button id="jokerBtn">Use JOKER 🃏</button> </div> <div id="status"></div> </div> <canvas id="confetti"></canvas> <script> /* ------------------------------------------------- Utility: tiny audio beeps (no external files) ---------------------------------------------------*/ function beep(freq,len){ const ctx=new (window.AudioContext||window.webkitAudioContext)(); const osc=ctx.createOscillator(); const gain=ctx.createGain(); osc.frequency.value=freq; osc.type="square"; osc.connect(gain); gain.connect(ctx.destination); osc.start(); gain.gain.exponentialRampToValueAtTime(0.0001,ctx.currentTime+len/1000); setTimeout(()=>ctx.close(),len+50); } /* ------------------------------------------------- CONFETTI CELEBRATION simple lightweight routine – 80 particles, 1.2s ---------------------------------------------------*/ function confetti(){ const canvas=document.getElementById("confetti"); const ctx=canvas.getContext("2d"); canvas.width=window.innerWidth; canvas.height=window.innerHeight; const parts=[]; for(let i=0;i<80;i++){ parts.push({ x:Math.random()*canvas.width, y:Math.random()*-canvas.height/2, speed:2+Math.random()*3, size:5+Math.random()*6, ang:Math.random()*Math.PI, color:`hsl(${Math.random()*360},90%,60%)` }); } let t=0; const anim=()=>{ ctx.clearRect(0,0,canvas.width,canvas.height); parts.forEach(p=>{ p.y+=p.speed; p.x+=Math.sin(p.ang); p.ang+=0.05; ctx.fillStyle=p.color; ctx.fillRect(p.x,p.y,p.size,p.size); }); t++; if(t<75) requestAnimationFrame(anim); else ctx.clearRect(0,0,canvas.width,canvas.height); }; anim(); } /* ------------------------------------------------- GAME LOGIC ---------------------------------------------------*/ const board=Array(9).fill(""); const cells=[]; let current="X"; let ai=false; // vs AI? let over=false; const jokerUsed={X:false,O:false}; let jokerMode=false; const gameDiv=document.getElementById("game"); const statusDiv=document.getElementById("status"); const resetBtn=document.getElementById("resetBtn"); const modeBtn=document.getElementById("modeBtn"); const jokerBtn=document.getElementById("jokerBtn"); /* Build cells */ for(let i=0;i<9;i++){ const d=document.createElement("div"); d.className="cell"; d.addEventListener("click",()=>handleClick(i)); gameDiv.appendChild(d); cells.push(d); } function handleClick(idx){ if(over) return; /* Joker phase */ if(jokerMode){ if(board[idx]===""||board[idx]===current){ setStatus("Pick an OPPONENT cell 🛑"); return; } board[idx]=current; jokerUsed[current]=true; jokerMode=false; jokerBtn.disabled=true; updateUI(); beep(300,80); nextTurn(); return; } /* Regular move */ if(board[idx]!=="") return; board[idx]=current; updateUI(); beep(440,80); nextTurn(); } function nextTurn(){ if(checkWin(current)){ setStatus(`${current} wins! 🎉`); over=true; confetti(); beep(880,250); return; } if(board.every(s=>s!=="")){ setStatus("Draw 🤝"); over=true; return; } current=current==="X"?"O":"X"; setStatus(`Turn: ${current}`); if(current==="O" && ai && !over){ setTimeout(aiMove,400); } } function aiMove(){ /* AI difficulty: unbeatable, but may randomly use joker if losing opportunity exists */ let useJ=false; if(!jokerUsed.O){ const w=willPlayerWin("X"); if(w!==-1 && Math.random()<0.6){useJ=true;} } if(useJ){ jokerUsed.O=true; board[w]="O"; jokerAnimation(w); setTimeout(()=>{updateUI();nextTurn();},350); return; } const best=minimax(board.slice(),true).idx; board[best]="O"; updateUI(); beep(220,80); nextTurn(); } /* ------------ Joker visuals for AI ---------- */ function jokerAnimation(i){ const el=cells[i]; el.style.transition="transform .15s"; el.style.transform="scale(1.2)"; setTimeout(()=>el.style.transform="scale(1)",150); } /* ------------ Minimax ----------------------- */ function minimax(newBoard,isAI){ const wins=[ [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 avail=newBoard.map((v,i)=>v===""?i:null).filter(v=>v!==null); if(checkStatic(newBoard,"X")) return {score:-10}; if(checkStatic(newBoard,"O")) return {score:10}; if(avail.length===0) return {score:0}; const moves=[]; for(const i of avail){ const move={idx:i}; newBoard[i]=isAI?"O":"X"; const result=minimax(newBoard,!isAI); move.score=result.score; newBoard[i]=""; moves.push(move); } let best; if(isAI){ let max=-Infinity; moves.forEach((m,i)=>{if(m.score>max){max=m.score;best=i;}}); }else{ let min=Infinity; moves.forEach((m,i)=>{if(m.score<min){min=m.score;best=i;}}); } return moves[best]; } /* ----------- Helper to see if player about to win (for Joker) */ function willPlayerWin(p){ const lines=[[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]; for(const line of lines){ const vals=line.map(i=>board[i]); if(vals.filter(v=>v===p).length===2 && vals.includes("")){ return line[vals.indexOf("")]; } } return -1; } /* ------------- UI Functions ----------------- */ function updateUI(){ board.forEach((v,i)=>{ cells[i].className="cell"+(v?(" "+v):""); }); } function setStatus(t){statusDiv.textContent=t;} function checkWin(p){ const wins=[ [0,1,2],[3,4,5],[6,7,8], [0,3,6],[1,4,7],[2,5,8], [0,4,8],[2,4,6] ]; for(const w of wins){ if(w.every(i=>board[i]===p)){ w.forEach(i=>cells[i].classList.add("win")); return true; } } return false; } function checkStatic(b,p){ return ( (b[0]===p&&b[1]===p&&b[2]===p)|| (b[3]===p&&b[4]===p&&b[5]===p)|| (b[6]===p&&b[7]===p&&b[8]===p)|| (b[0]===p&&b[3]===p&&b[6]===p)|| (b[1]===p&&b[4]===p&&b[7]===p)|| (b[2]===p&&b[5]===p&&b[8]===p)|| (b[0]===p&&b[4]===p&&b[8]===p)|| (b[2]===p&&b[4]===p&&b[6]===p) ); } /* ------------- Controls ---------------------*/ resetBtn.onclick=()=>init(); modeBtn.onclick=()=>{ ai=!ai; modeBtn.textContent=ai?"Play vs Friend 👫":"Play vs A.I. 🤖"; init(); }; jokerBtn.onclick=()=>{ if(over||jokerUsed[current])return; jokerMode=true; setStatus(`JOKER! Click an opponent cell to steal 🃏`); }; function init(){ for(let i=0;i<9;i++){board[i]="";cells[i].className="cell";} current="X"; over=false; jokerMode=false; jokerUsed.X=false; jokerUsed.O=false; jokerBtn.disabled=false; setStatus("Turn: X"); if(ai && current==="O") aiMove(); } init(); </script> </body> </html> ```
Drag to resize
Here's a unique and "spicy" version of a Tic-Tac-Toe game with a fiery theme, animations, and special effects. I've added a scoring system, a reset feature, and some visual flair with a fiery background and sound effects for a more engaging experience. The game is built with HTML, CSS, and JavaScript, and uses CDN links for popular libraries like Tailwind CSS for styling and Howler.js for sound effects. Everything is contained in a single HTML code block for easy rendering. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spicy Tic-Tac-Toe</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script> <style> body { background: linear-gradient(to bottom, #1a1a1a, #ff4d00); font-family: 'Arial', sans-serif; overflow: hidden; } .fire { position: absolute; width: 100%; height: 100%; background: url('https://i.giphy.com/media/26BRvP8RB2D877M6Y/giphy.webp') repeat; opacity: 0.3; z-index: -1; } .board { display: grid; grid-template-columns: repeat(3, 100px); gap: 5px; background: rgba(0, 0, 0, 0.7); padding: 20px; border-radius: 15px; box-shadow: 0 0 20px #ff4d00; } .cell { width: 100px; height: 100px; background: rgba(255, 255, 255, 0.1); border: 3px solid #ff4d00; font-size: 3em; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: transform 0.2s, background 0.2s; border-radius: 10px; } .cell:hover { transform: scale(1.1); background: rgba(255, 77, 0, 0.3); } .cell.x { color: #ffcc00; text-shadow: 0 0 10px #ff8800; } .cell.o { color: #ff3300; text-shadow: 0 0 10px #ff0000; } .scoreboard { background: rgba(0, 0, 0, 0.7); padding: 20px; border-radius: 10px; box-shadow: 0 0 15px #ff4d00; } .btn-reset { background: #ff3300; transition: background 0.2s, transform 0.2s; } .btn-reset:hover { background: #ff5500; transform: scale(1.05); } .modal { display: none; position: fixed; z-index: 10; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); justify-content: center; align-items: center; } .modal-content { background: rgba(0, 0, 0, 0.9); padding: 30px; border-radius: 15px; text-align: center; box-shadow: 0 0 20px #ff4d00; transform: scale(0.8); transition: transform 0.3s; } .modal.show .modal-content { transform: scale(1); } .btn-close { background: #ff3300; transition: background 0.2s; } .btn-close:hover { background: #ff5500; } </style> </head> <body class="min-h-screen flex flex-col justify-center items-center text-white"> <div class="fire"></div> <h1 class="text-4xl font-bold mb-6 text-center" style="text-shadow: 0 0 10px #ff8800;">Spicy Tic-Tac-Toe</h1> <div class=" scoreboard text-center mb-6 text-xl"> <p class="mb-2">🔥 Player X: <span id="scoreX">0</span></p> <p>🌶️ Player O: <span id="scoreO">0</span></p> </div> <div id="status" class="text-2xl mb-6" style="text-shadow: 0 0 10px #ff8800;">Player X's Turn</div> <div id="board" class="board"></div> <button id="reset" class="btn-reset text-white px-6 py-3 rounded-lg text-lg font-bold mt-6">Reset Game</button> <div id="winModal" class="modal"> <div class="modal-content"> <h2 id="winnerText" class="text-3xl font-bold mb-4"></h2> <button id="closeModal" class="btn-close text-white px-4 py-2 rounded-lg">Play Again</button> </div> </div> <script> const board = document.getElementById('board'); const status = document.getElementById('status'); const resetBtn = document.getElementById('reset'); const scoreX = document.getElementById('scoreX'); const scoreO = document.getElementById('scoreO'); const winModal = document.getElementById('winModal'); const winnerText = document.getElementById('winnerText'); const closeModal = document.getElementById('closeModal'); let cells = []; let currentPlayer = 'X'; let gameActive = true; let scores = { X: 0, O: 0 }; const clickSound = new Howl({ src: ['https://cdn.freesound.org/previews/128/128275_60825-lq.mp3'], volume: 0.5 }); const winSound = new Howl({ src: ['https://cdn.freesound.org/previews/274/274183_5123851-lq.mp3'], volume: 0.8 }); const winningCombos = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; function createBoard() { board.innerHTML = ''; cells = []; for (let i = 0; i < 9; i++) { const cell = document.createElement('div'); cell.classList.add('cell'); cell.dataset.index = i; cell.addEventListener('click', handleCellClick); board.appendChild(cell); cells.push(cell); } } function handleCellClick(e) { const cell = e.target; if (!gameActive || cell.textContent) return; cell.textContent = currentPlayer; cell.classList.add(currentPlayer.toLowerCase()); clickSound.play(); if (checkWin()) { status.textContent = `${currentPlayer} Wins!`; gameActive = false; scores[currentPlayer]++; updateScoreboard(); showWinModal(`${currentPlayer === 'X' ? '🔥 Player X' : '🌶️ Player O'} Wins!`); highlightWinningCells(); winSound.play(); disableCellHover(); return; } if (cells.every(c => c.textContent)) { status.textContent = "It's a Draw!"; gameActive = false; showWinModal("It's a Draw!"); winSound.play(); disableCellHover(); return; } currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; status.textContent = `Player ${currentPlayer}'s Turn`; } function checkWin() { return winningCombos.some(combo => { return combo.every(index => { return cells[index].textContent === currentPlayer; }); }); } function highlightWinningCells() { winningCombos.forEach(combo => { const isWinningCombo = combo.every(index => cells[index].textContent === currentPlayer); if (isWinningCombo) { combo.forEach(index => { cells[index].style.background = currentPlayer === 'X' ? 'rgba(255, 204, 0, 0.5)' : 'rgba(255, 51, 0, 0.5)'; }); } }); } function disableCellHover() { cells.forEach(cell => { cell.style.pointerEvents = 'none'; }); } function updateScoreboard() { scoreX.textContent = scores.X; scoreO.textContent = scores.O; } function showWinModal(message) { winnerText.textContent = message; winModal.style.display = 'flex'; setTimeout(() => winModal.classList.add('show'), 10); } function closeWinModal() { winModal.style.display = 'none'; winModal.classList.remove('show'); resetGame(); } function resetGame() { currentPlayer = 'X'; gameActive = true; status.textContent = "Player X's Turn"; cells.forEach(cell => { cell.textContent = ''; cell.classList.remove('x', 'o'); cell.style.background = 'rgba(255, 255, 255, 0.1)'; cell.style.pointerEvents = 'auto'; }); } resetBtn.addEventListener('click', () => { scores = { X: 0, O: 0 }; updateScoreboard(); resetGame(); }); closeModal.addEventListener('click', closeWinModal); createBoard(); </script> </body> </html> ``` This "Spicy Tic-Tac-Toe" game includes the following special features to make it stand out: - **Fiery Theme**: A dark, fiery gradient background with an animated fire GIF overlay for ambiance. - **Scoreboard**: Tracks wins for both players (Player X with 🔥 and Player O with 🌶️ emojis for extra spice). - **Sound Effects**: Click sounds for moves and a victory sound for wins, powered by Howler.js. - **Animations**: Cells scale on hover, and a modal pops up with a smooth animation to announce the winner or a draw. - **Visual Feedback**: Winning cells are highlighted, and player symbols (X and O) glow with fiery colors. - **Reset Options**: A full reset to clear scores and a "Play Again" option after each game via the modal. - **Responsive Design**: Built with Tailwind CSS for a modern, responsive look that works on different screen sizes. The game maintains the classic Tic-Tac-Toe mechanics—players alternate turns, win by aligning three symbols, or draw if the board fills up—but the spicy theme and interactive elements elevate the experience. Enjoy battling it out in this fiery arena!
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Spicy Tic Tac Toe</title> <!-- Google Fonts for better visuals --> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@900&display=swap" rel="stylesheet"> <style> body { background: linear-gradient(135deg, #8e2de2, #4a00e0, #f7971e, #ffd200); min-height: 100vh; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; font-family: 'Roboto', sans-serif; color: #222; } h1 { font-size: 2.5rem; margin-top: 30px; margin-bottom: 10px; background: linear-gradient(90deg, #f7971e, #8e2de2 80%); color: transparent; background-clip: text; -webkit-background-clip: text; font-weight: 900; text-shadow: 2px 4px 8px rgba(70,0,100,0.1); text-align: center; } #game-container { background: rgba(255,255,255,0.92); box-shadow: 0 8px 28px rgba(120,20,200,0.15); border-radius: 20px; padding: 35px 20px; margin: 20px auto; width: 350px; } #board { display: grid; grid-template-columns: repeat(3, 80px); grid-template-rows: repeat(3, 80px); gap: 10px; margin-bottom: 20px; justify-content: center; } .cell { width: 80px; height: 80px; background: linear-gradient(135deg, #8e2de2 60%, #f7971e); border: none; border-radius: 14px; font-size: 2.7rem; font-weight: 900; color: #fff; box-shadow: 0 2px 12px rgba(72,44,123,0.13); cursor: pointer; transition: background 0.19s, transform 0.1s; outline: none; position: relative; user-select: none; } .cell.winner { background: linear-gradient(135deg, #ffd200 80%, #f7971e); color: #4a00e0; animation: winner-glow 1.1s infinite alternate; } @keyframes winner-glow { from { box-shadow: 0 0 8px #ffe066;} to { box-shadow: 0 0 36px #ffe066, 0 0 50px #ffb300;} } .cell:hover:enabled { background: linear-gradient(135deg, #b085f5, #ffd200 50%); transform: scale(1.08); } #status { font-size: 1.5rem; text-align: center; margin: 8px 0 9px; } #current-player { display: flex; align-items: center; justify-content: center; font-size: 1.3rem; margin: 10px 0; } #spicy-mode { display: inline-block; vertical-align: middle; margin-left: 10px; accent-color: #f7971e; width: 18px; height: 18px; } #reset-btn { background: linear-gradient(90deg, #f7971e, #ffd200 70%); border: none; border-radius: 10px; color: #4a00e0; font-size: 1rem; font-weight: 700; padding: 14px 32px; margin-top: 16px; cursor: pointer; box-shadow: 0 2px 8px #f7971eb0; text-transform: uppercase; transition: filter 0.12s, background 0.2s; letter-spacing: 1.2px; } #reset-btn:hover { filter: brightness(1.15); background: linear-gradient(90deg, #8e2de2, #ffd200 80%); } .firework { position: absolute; pointer-events: none; z-index: 999; width: 10px; height: 10px; border-radius: 50%; animation: firework-explode 0.84s cubic-bezier(0.36, 1.22, 0.92, 0.99) forwards; } @keyframes firework-explode { from { opacity:1; transform: scale(0.5);} 60% {opacity:0.95;} to {opacity:0; transform: scale(6);} } .confetti { pointer-events: none; position: fixed; left: 0; top: 0; width: 100vw; height: 100vh; z-index: 1999; pointer-events: none; overflow: hidden; } /* Emoji Anim */ .emoji-bounce { display: inline-block; animation: bounce-emoji 0.85s cubic-bezier(.45,.02,.49,1.96) 1; margin-right: 8px; filter: drop-shadow(0 2px 10px #f7971e66); } @keyframes bounce-emoji { 0%,100% { transform: translateY(0);} 30% {transform: translateY(-35px);} 50% { transform:translateY(-18px);} 80% {transform: translateY(-7px);} } </style> </head> <body> <h1> <span class="emoji-bounce">🌶️</span> Spicy Tic Tac Toe </h1> <div id="game-container"> <div id="status"></div> <div id="current-player"> <span id="player-symbol"></span> <label style="margin-left:auto;display:flex;align-items:center;font-size:0.96em;"> <input type="checkbox" id="spicy-mode" /> <span style="margin-left:7px;color:#d72e29;font-weight:600;">Spicy Mode</span> </label> </div> <div id="board"></div> <button id="reset-btn">Reset Game</button> </div> <canvas class="confetti"></canvas> <script> // --- Game State --- let board = Array(9).fill(''); let currentPlayer = Math.random() > 0.5 ? 'X' : 'O'; let gameActive = true; let spicyMode = false; let moveNumber = 1; let scores = { X: 0, O: 0 }; // --- DOM Elements --- const boardDiv = document.getElementById('board'); const statusDiv = document.getElementById('status'); const resetBtn = document.getElementById('reset-btn'); const currentPlayerDiv = document.getElementById('player-symbol'); const spicyCheckbox = document.getElementById('spicy-mode'); const confettiCanvas = document.querySelector('.confetti'); let confettiCtx; // --- EMOJI THEMES --- const emojiMap = { X: ['🍕','🌶️','🦄','🎉','🔥'], O: ['🍔','🍭','🍀','🍩','🍌'], empty: ['🍳','🥚',''] }; let useEmojis = false; // --- Board rendering --- function renderBoard() { boardDiv.innerHTML = ''; for (let i = 0; i < 9; i++) { const btn = document.createElement('button'); btn.className = 'cell'; btn.disabled = !!board[i] || !gameActive; btn.setAttribute('data-index', i); // Show emoji in spicy mode, or normal X/O. if (useEmojis) { if (board[i] === 'X') btn.innerText = emojiMap.X[(i+moveNumber)%emojiMap.X.length]; else if (board[i] === 'O') btn.innerText = emojiMap.O[(i+moveNumber)%emojiMap.O.length]; else btn.innerText = emojiMap.empty[(i+moveNumber)%emojiMap.empty.length]; } else { btn.innerText = board[i]; } btn.onclick = () => handleMove(i, btn); boardDiv.appendChild(btn); } } // --- Status update --- function updateStatus(msg) { statusDiv.innerHTML = msg || ''; } // --- Current player display --- function updateCurrentPlayer() { const color = currentPlayer === 'X' ? '#8e2de2' : '#f7971e'; const emoji = useEmojis ? (currentPlayer === 'X' ? emojiMap.X[moveNumber%emojiMap.X.length] : emojiMap.O[moveNumber%emojiMap.O.length]) : ''; currentPlayerDiv.innerHTML = `<span class="emoji-bounce" style="font-size:1.3em;">${emoji}</span>` + `<span style="color:${color}; font-size: 1.3em; font-weight:800;">${currentPlayer}</span>'s turn`; } // --- Winning lines --- const winLines = [ [0,1,2], [3,4,5], [6,7,8], // rows [0,3,6], [1,4,7], [2,5,8], // cols [0,4,8], [2,4,6] // diags ]; function checkWinner() { for (let line of winLines) { let [a,b,c] = line; if (board[a] && board[a] === board[b] && board[a] === board[c]) { return {winner: board[a], line}; } } return null; } // --- Spicy Move: Board Flip, Swap, Double Move --- function spicySurprise() { let action = Math.floor(Math.random() * 3); let msg = ''; switch(action) { case 0: // board flip flipBoard(); msg = '🌪️ The board flipped!'; shakeBoard(); break; case 1: // random swap two non-empty cells if (board.filter(x => x).length > 1) { randomSwap(); msg = '🔄 Two pieces have swapped!'; } break; case 2: // grant a bonus turn msg = '🔥 Bonus move! Play again!'; setTimeout(()=> {updateStatus(msg);},160); return true; } setTimeout(()=>{if(msg) updateStatus(msg);}, 130); return false; } function flipBoard() { // reverse array (simulate board flip) board = [board[8],board[7],board[6],board[5],board[4],board[3],board[2],board[1],board[0]]; renderBoard(); } function randomSwap() { let filled = board.map((v,i)=>v?i:-1).filter(i=>i>=0); if (filled.length < 2) return; let [i1, i2] = [filled[Math.floor(Math.random()*filled.length)], filled[Math.floor(Math.random()*filled.length)]]; if (i1 === i2) i2 = filled[(filled.indexOf(i1)+1)%filled.length]; [board[i1],board[i2]] = [board[i2],board[i1]]; renderBoard(); } function shakeBoard() { boardDiv.animate([ { transform: 'translateX(0px)' }, { transform: 'translateX(-8px)' }, { transform: 'translateX(8px)' }, { transform: 'translateX(-8px)' }, { transform: 'translateX(0px)' } ], { duration: 350, iterations: 1 }); } // --- Spicy fireworks on win --- function launchFireworks(line) { for (const i of line) { const cell = boardDiv.children[i]; const rect = cell.getBoundingClientRect(); const firework = document.createElement('div'); firework.className = 'firework'; firework.style.left = '30px'; firework.style.top = '30px'; firework.style.background = `radial-gradient(circle at 40% 30%, #ffcf00 70%, ${randColor()} 90%)`; cell.appendChild(firework); setTimeout(()=>{ firework.remove(); }, 800+Math.random()*400); } setTimeout(emitConfetti, 300); } function randColor() { const colors = ['#f7971e', '#8e2de2', '#ffd200', '#ff5e62', '#14e698']; return colors[Math.floor(Math.random()*colors.length)]; } // --- Spicy confetti --- function emitConfetti() { let ctx = confettiCtx; if (!ctx) return; // Animate simple confetti for 1s: let t = 0, conf= []; for (let i=0;i<32;i++) { conf.push({ x: Math.random()*confettiCanvas.width, y: -Math.random()*80, r: 7+Math.random()*6, d: 2+Math.random()*3, c: randColor(), e: Math.random()>.7 }); } function draw() { ctx.clearRect(0,0,confettiCanvas.width, confettiCanvas.height); conf.forEach(f=>{ ctx.beginPath(); if (f.e) ctx.ellipse(f.x,f.y, f.r, f.r/2, Math.random()*Math.PI, 0, Math.PI*2); else ctx.arc(f.x,f.y,f.r,0,2*Math.PI); ctx.fillStyle = f.c; ctx.fill(); ctx.globalAlpha = .7; }); ctx.globalAlpha = 1.0; } function update() { for (let f of conf) { f.y += f.d*1.3; if (f.y>confettiCanvas.height) f.y = -10; } t++; draw(); if (t<38) requestAnimationFrame(update); } update(); } // --- Main move handler --- function handleMove(index, btn) { if (!gameActive || board[index]) return; board[index] = currentPlayer; renderBoard(); // Spicy: Chance for a surprise after every move in Spicy Mode let spicyDoubleMove = false; if (spicyMode && Math.random() < 0.22) { spicyDoubleMove = spicySurprise(); renderBoard(); } const res = checkWinner(); if (res) { endGame(res.winner, res.line); return; } if (board.every(cell=>cell)) { endGame(null); return; } updateCurrentPlayer(); // Turn step if (!(spicyDoubleMove && spicyMode)) { currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; moveNumber++; } updateCurrentPlayer(); } // --- End Game --- function endGame(winner, winLine) { gameActive = false; if (winner) { // Animate winning cells for (let idx of winLine) { boardDiv.children[idx].classList.add('winner'); } // Scoreboard scores[winner] = (scores[winner]||0)+1; let text = `<span class="emoji-bounce" style="font-size:1.72em;">${useEmojis ? (winner=='X'?emojiMap.X[moveNumber%emojiMap.X.length]:emojiMap.O[moveNumber%emojiMap.O.length]) : (winner)}</span> <b>${winner}</b> Wins! <br/> Score: X ${scores.X} - O ${scores.O}`; updateStatus(text); launchFireworks(winLine); } else { updateStatus(`🤜🤛 <b>It's a tie!</b>`); } } // --- Resets --- function resetGame(fresh = false) { board = Array(9).fill(''); gameActive = true; moveNumber = 1; currentPlayer = Math.random() > 0.5 ? 'X' : 'O'; if (fresh) scores = { X: 0, O: 0 }; renderBoard(); updateCurrentPlayer(); updateStatus(''); setTimeout(()=>{ confettiCtx && confettiCtx.clearRect(0,0,confettiCanvas.width, confettiCanvas.height);},420); } // --- Spicy toggle --- spicyCheckbox.addEventListener('change', (e)=>{ spicyMode = !!spicyCheckbox.checked; useEmojis = spicyMode; resetGame(false); updateStatus('<b style="color:#d72e29;">Spicy Mode '+(spicyMode?'ON 🌶️':'OFF')+'</b>') setTimeout(()=>{updateStatus('');}, 1270); }); window.addEventListener('resize', ()=>{ confettiCanvas.width = window.innerWidth; confettiCanvas.height = window.innerHeight; }); // --- INIT --- function init() { confettiCanvas.width = window.innerWidth; confettiCanvas.height = window.innerHeight; confettiCtx = confettiCanvas.getContext('2d'); renderBoard(); updateCurrentPlayer(); } // --- Reset Button --- resetBtn.onclick = () => resetGame(false); // Start! init(); </script> </body> </html> ``` **Features of this "Spicy" Tic Tac Toe:** - **Spicy Mode**: Toggle for extra fun: - Board flip, random swaps, or bonus turns can occur at random after a move. - Board and messages become emoji-themed. - **Fireworks & Confetti** celebrate a win! - **Scoreboard** persists unless you reload. - **Colorful, animated interface** for a special experience. - **Responsive and mobile-friendly**. Turn Spicy Mode on for surprises! 🌶️
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>🌌 Spicy Tic Tac Toe 🌟</title> <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500&display=swap" rel="stylesheet"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Orbitron', sans-serif; background: linear-gradient(135deg, #0f2027, #203a43, #2c5364); color: #fff; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; overflow: hidden; } h1 { margin: 20px 0; font-size: 2.5em; text-shadow: 0 0 5px #00ffcc; animation: pulse 2s infinite; } .board { display: grid; grid-template-columns: repeat(3, 100px); gap: 15px; margin: 20px; } .cell { width: 100px; height: 100px; background: rgba(255, 255, 255, 0.1); display: flex; align-items: center; justify-content: center; font-size: 2.5em; cursor: pointer; border-radius: 12px; transition: 0.2s all ease; box-shadow: 0 0 10px #000; } .cell:hover { transform: scale(1.1) rotate(3deg); background: rgba(255, 255, 255, 0.2); } .cell.played { pointer-events: none; } .status { margin: 10px; font-size: 1.2em; text-shadow: 0 0 5px #ff4757; } button { padding: 10px 20px; border: none; background: #00ffcc; color: #000; font-size: 1em; font-weight: bold; border-radius: 25px; cursor: pointer; box-shadow: 0 0 15px #00ffcc; transition: 0.3s all ease; } button:hover { transform: scale(1.1) rotate(-5deg); box-shadow: 0 0 20px #00ffcc, 0 0 40px #00ffcc; } .scoreboard { margin: 20px; font-size: 1.2em; display: flex; gap: 30px; text-shadow: 0 0 5px #00ffcc; } .win-highlight { background-color: #ffd700 !important; animation: vibrate 0.5s ease-in-out; } @keyframes vibrate { 0% { transform: translate(0); } 20% { transform: translate(-2px, 2px); } 40% { transform: translate(2px, -2px); } 60% { transform: translate(-2px, 2px); } 80% { transform: translate(2px, -2px); } 100% { transform: translate(0); } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.8; } } </style> </head> <body> <h1>✨ Spicy Galactic Tic Tac Toe 🚀</h1> <div class="status" id="status">Player 🟢 X's turn</div> <div class="board" id="board"> <!-- Cells dynamically created --> </div> <button id="reset">🔄 Reset</button> <div class="scoreboard"> <div>X Wins: <span id="x-score">0</span></div> <div>O Wins: <span id="o-score">0</span></div> <div>Draws: <span id="draw-score">0</span></div> </div> <canvas id="confetti-canvas"></canvas> <script type="module"> import confetti from 'https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/+esm'; const boardElement = document.getElementById('board'); const statusElement = document.getElementById('status'); let currentPlayer = 'X'; let gameBoard = Array(9).fill(''); let gameActive = true; let scores = { X: 0, O: 0, Draw: 0 }; const xScoreDisplay = document.getElementById('x-score'); const oScoreDisplay = document.getElementById('o-score'); const drawScoreDisplay = document.getElementById('draw-score'); const canvas = document.getElementById('confetti-canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '9999'; canvas.style.display = 'none'; function createBoard() { boardElement.innerHTML = ''; gameBoard.forEach((cell, index) => { const cellElement = document.createElement('div'); cellElement.classList.add('cell'); cellElement.dataset.index = index; cellElement.dataset.value = cell; cellElement.innerHTML = cell; cellElement.addEventListener('click', handleCellClick); boardElement.appendChild(cellElement); }); } function handleCellClick(e) { const index = e.target.dataset.index; if (!gameActive || gameBoard[index]) return; gameBoard[index] = currentPlayer; e.target.dataset.value = currentPlayer; e.target.innerHTML = currentPlayer; e.target.classList.add('played'); playSound(); if (checkWin()) { statusElement.textContent = `🏆 Player ${currentPlayer} wins!`; scores[currentPlayer]++; updateScores(); gameActive = false; confettiAnimation(); highlightWinningCells(getWinningIndices()); return; } if (gameBoard.every(Boolean)) { statusElement.textContent = `🤝 It's a draw!`; scores.Draw++; updateScores(); gameActive = false; return; } currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; statusElement.textContent = `Player 🟢 ${currentPlayer}'s turn`; } function checkWin() { const winPatterns = [ [0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6] ]; for (const pattern of winPatterns) { const [a,b,c] = pattern; if (gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c]) { winners = pattern; return true; } } return false; } let winningIndices = []; function getWinningIndices() { const winPatterns = [ [0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6] ]; for (const pattern of winPatterns) { const [a,b,c] = pattern; if (gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c]) { return pattern; } } return []; } function highlightWinningCells(indices) { indices.forEach(index => { const cell = boardElement.children[index]; cell.classList.add('win-highlight'); }); } function confettiAnimation() { canvas.style.display = 'block'; const count = 300; const size = 2.5; const defaults = { origin: { y: 0.7 }, zIndex: 9999 }; const fire = (particleRatio, opts) => { confetti({ ...defaults, ...opts, particleCount: Math.floor(count * particleRatio), spread: 120, ticks: 150, shapes: ['circle', 'square'], colors: ['#00ffff', '#00ff88', '#ff007f', '#ffff00'] }); }; fire(0.25, { spread: 26, startVelocity: 55, decay: 0.92, scalar: 1.2 }); fire(0.2, { spread: 60, startVelocity: 25, decay: 0.93, scalar: 0.8 }); fire(0.35, { spread: 100, decay: 0.91, scalar: 1.2 }); fire(0.2, { spread: 180, startVelocity: 25, decay: 0.93, scalar: 0.8 }); setTimeout(() => { canvas.style.display = 'none'; }, 2000); } function playSound() { const context = new (window.AudioContext || window.webkitAudioContext)(); const oscillator = context.createOscillator(); const gainNode = context.createGain(); oscillator.type = 'sine'; oscillator.frequency.value = 440 + (Math.random() * 200); oscillator.connect(gainNode); gainNode.connect(context.destination); oscillator.start(); gainNode.gain.setValueAtTime(1, context.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.1); oscillator.stop(context.currentTime + 0.1); } function updateScores() { xScoreDisplay.textContent = scores.X; oScoreDisplay.textContent = scores.O; drawScoreDisplay.textContent = scores.Draw; } document.getElementById('reset').addEventListener('click', () => { gameBoard = Array(9).fill(''); currentPlayer = 'X'; gameActive = true; statusElement.textContent = `Player 🟢 ${currentPlayer}'s turn`; createBoard(); }); createBoard(); </script> </body> </html> ```
Drag to resize
Here's a special and spicy Tic Tac Toe game with some extra features like a scoreboard, a reset button, and a spicy twist: the cells change color when you hover over them, and there's a fun confetti effect when someone wins! ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spicy Tic Tac Toe</title> <script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.4.0/dist/confetti.browser.min.js"></script> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; background-color: #f0f0f0; } h1 { color: #333; } .game-container { display: flex; flex-direction: column; align-items: center; } .scoreboard { display: flex; justify-content: space-around; width: 300px; margin-bottom: 20px; font-size: 20px; } .board { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); gap: 5px; margin-bottom: 20px; } .cell { width: 100px; height: 100px; background-color: #fff; border: 2px solid #333; display: flex; justify-content: center; align-items: center; font-size: 48px; cursor: pointer; transition: background-color 0.3s; } .cell:hover { background-color: #ffcccb; } .reset-btn { padding: 10px 20px; font-size: 16px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; } .reset-btn:hover { background-color: #45a049; } .player-turn { margin-top: 20px; font-size: 20px; font-weight: bold; } </style> </head> <body> <h1>Spicy Tic Tac Toe</h1> <div class="game-container"> <div class="scoreboard"> <div>Player X: <span id="score-x">0</span></div> <div>Player O: <span id="score-o">0</span></div> </div> <div class="board" id="board"> <div class="cell" data-index="0"></div> <div class="cell" data-index="1"></div> <div class="cell" data-index="2"></div> <div class="cell" data-index="3"></div> <div class="cell" data-index="4"></div> <div class="cell" data-index="5"></div> <div class="cell" data-index="6"></div> <div class="cell" data-index="7"></div> <div class="cell" data-index="8"></div> </div> <button class="reset-btn" id="reset-btn">Reset Game</button> <div class="player-turn" id="player-turn">Player X's turn</div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const board = document.getElementById('board'); const cells = document.querySelectorAll('.cell'); const resetBtn = document.getElementById('reset-btn'); const playerTurn = document.getElementById('player-turn'); const scoreX = document.getElementById('score-x'); const scoreO = document.getElementById('score-o'); let currentPlayer = 'X'; let gameState = ['', '', '', '', '', '', '', '', '']; let gameActive = true; let scores = { X: 0, O: 0 }; const winningConditions = [ [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 ]; function handleCellClick(e) { const clickedCell = e.target; const clickedCellIndex = parseInt(clickedCell.getAttribute('data-index')); if (gameState[clickedCellIndex] !== '' || !gameActive) { return; } gameState[clickedCellIndex] = currentPlayer; clickedCell.textContent = currentPlayer; checkResult(); } function checkResult() { let roundWon = false; for (let i = 0; i < winningConditions.length; i++) { const [a, b, c] = winningConditions[i]; if (gameState[a] === '' || gameState[b] === '' || gameState[c] === '') { continue; } if (gameState[a] === gameState[b] && gameState[b] === gameState[c]) { roundWon = true; break; } } if (roundWon) { scores[currentPlayer]++; updateScoreboard(); gameActive = false; confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); playerTurn.textContent = `Player ${currentPlayer} wins!`; return; } if (!gameState.includes('')) { gameActive = false; playerTurn.textContent = 'Game ended in a draw!'; return; } currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; playerTurn.textContent = `Player ${currentPlayer}'s turn`; } function updateScoreboard() { scoreX.textContent = scores.X; scoreO.textContent = scores.O; } function resetGame() { currentPlayer = 'X'; gameState = ['', '', '', '', '', '', '', '', '']; gameActive = true; playerTurn.textContent = `Player ${currentPlayer}'s turn`; cells.forEach(cell => { cell.textContent = ''; }); } cells.forEach(cell => { cell.addEventListener('click', handleCellClick); }); resetBtn.addEventListener('click', resetGame); }); </script> </body> </html> ``` This Tic Tac Toe game includes: 1. A scoreboard to keep track of the scores. 2. A reset button to restart the game. 3. A spicy twist with cells changing color on hover. 4. A fun confetti effect when someone wins. 5. A display showing whose turn it is. Enjoy the game!
Drag to resize
Here's a spicy Tic Tac Toe game with special effects, animations, and some extra features: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spicy Tic Tac Toe</title> <style> body { font-family: 'Arial', sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; overflow: hidden; } h1 { color: #ff6b6b; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); margin-bottom: 20px; font-size: 2.5rem; } .game-container { position: relative; perspective: 1000px; } .board { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); gap: 10px; background-color: #fff; padding: 20px; border-radius: 15px; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); transform-style: preserve-3d; transition: transform 0.5s; } .cell { width: 100px; height: 100px; background-color: #f0f0f0; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 3rem; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .cell:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); background-color: #e0e0e0; } .cell.x { color: #ff6b6b; } .cell.o { color: #48dbfb; } .winning-cell { animation: pulse 1s infinite; background-color: rgba(255, 215, 0, 0.3); } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .controls { margin-top: 20px; display: flex; gap: 10px; } button { padding: 10px 20px; border: none; border-radius: 5px; background-color: #ff6b6b; color: white; font-weight: bold; cursor: pointer; transition: all 0.3s; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } button:hover { transform: translateY(-2px); box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); background-color: #ff5252; } .scoreboard { display: flex; justify-content: space-between; width: 340px; margin-bottom: 20px; background-color: white; padding: 15px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .player { text-align: center; } .player.active { font-weight: bold; color: #ff6b6b; } .confetti { position: absolute; width: 10px; height: 10px; background-color: #f00; opacity: 0; } .theme-toggle { position: absolute; top: 20px; right: 20px; background: none; border: none; font-size: 1.5rem; cursor: pointer; } .dark-mode { background: linear-gradient(135deg, #2c3e50 0%, #1a1a2e 100%) !important; color: white; } .dark-mode .board, .dark-mode .scoreboard { background-color: #34495e; color: white; } .dark-mode .cell { background-color: #2c3e50; color: white; } .dark-mode .cell:hover { background-color: #3d5166; } .dark-mode h1 { color: #f39c12; } .dark-mode button { background-color: #f39c12; } .dark-mode button:hover { background-color: #e67e22; } .emoji-mode .cell.x::before { content: "🔥"; } .emoji-mode .cell.o::before { content: "💧"; } .emoji-mode .cell.x, .emoji-mode .cell.o { font-size: 2.5rem; } </style> </head> <body> <button class="theme-toggle">🌓</button> <h1>Spicy Tic Tac Toe</h1> <div class="scoreboard"> <div class="player" id="player-x"> <h2>Player X</h2> <p>Wins: <span id="score-x">0</span></p> </div> <div class="player" id="player-o"> <h2>Player O</h2> <p>Wins: <span id="score-o">0</span></p> </div> </div> <div class="game-container"> <div class="board" id="board"></div> </div> <div class="controls"> <button id="reset">Reset Game</button> <button id="new-game">New Game</button> <button id="emoji-mode">Emoji Mode</button> </div> <script> document.addEventListener('DOMContentLoaded', () => { const board = document.getElementById('board'); const cells = []; let currentPlayer = 'X'; let gameActive = true; let scores = { X: 0, O: 0 }; let emojiMode = false; // Create board cells for (let i = 0; i < 9; i++) { const cell = document.createElement('div'); cell.classList.add('cell'); cell.dataset.index = i; cell.addEventListener('click', handleCellClick); board.appendChild(cell); cells.push(cell); } // Theme toggle const themeToggle = document.querySelector('.theme-toggle'); themeToggle.addEventListener('click', () => { document.body.classList.toggle('dark-mode'); themeToggle.textContent = document.body.classList.contains('dark-mode') ? '🌞' : '🌓'; }); // Emoji mode toggle const emojiModeBtn = document.getElementById('emoji-mode'); emojiModeBtn.addEventListener('click', () => { emojiMode = !emojiMode; board.classList.toggle('emoji-mode'); emojiModeBtn.textContent = emojiMode ? 'Text Mode' : 'Emoji Mode'; updateBoardDisplay(); }); // Reset game document.getElementById('reset').addEventListener('click', resetGame); // New game (reset scores) document.getElementById('new-game').addEventListener('click', () => { scores = { X: 0, O: 0 }; updateScores(); resetGame(); }); function handleCellClick(e) { const cell = e.target; const index = cell.dataset.index; if (cell.textContent !== '' || !gameActive) return; cell.textContent = currentPlayer; cell.classList.add(currentPlayer.toLowerCase()); if (checkWin()) { gameActive = false; scores[currentPlayer]++; updateScores(); highlightWinningCells(); createConfetti(); setTimeout(resetGame, 2000); return; } if (checkDraw()) { gameActive = false; setTimeout(resetGame, 1500); return; } currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; updatePlayerTurn(); } function checkWin() { const winPatterns = [ [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 ]; return winPatterns.some(pattern => { const [a, b, c] = pattern; return cells[a].textContent !== '' && cells[a].textContent === cells[b].textContent && cells[b].textContent === cells[c].textContent; }); } function checkDraw() { return [...cells].every(cell => cell.textContent !== ''); } function highlightWinningCells() { const winPatterns = [ [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 ]; const winningPattern = winPatterns.find(pattern => { const [a, b, c] = pattern; return cells[a].textContent !== '' && cells[a].textContent === cells[b].textContent && cells[b].textContent === cells[c].textContent; }); if (winningPattern) { winningPattern.forEach(index => { cells[index].classList.add('winning-cell'); }); } } function resetGame() { cells.forEach(cell => { cell.textContent = ''; cell.className = 'cell'; }); gameActive = true; updatePlayerTurn(); } function updatePlayerTurn() { document.getElementById('player-x').classList.toggle('active', currentPlayer === 'X'); document.getElementById('player-o').classList.toggle('active', currentPlayer === 'O'); } function updateScores() { document.getElementById('score-x').textContent = scores.X; document.getElementById('score-o').textContent = scores.O; } function updateBoardDisplay() { cells.forEach(cell => { if (cell.textContent === 'X') { cell.classList.add('x'); } else if (cell.textContent === 'O') { cell.classList.add('o'); } }); } function createConfetti() { const colors = ['#ff6b6b', '#48dbfb', '#feca57', '#1dd1a1', '#5f27cd']; for (let i = 0; i < 100; i++) { const confetti = document.createElement('div'); confetti.classList.add('confetti'); confetti.style.left = Math.random() * 100 + 'vw'; confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; confetti.style.opacity = '1'; document.body.appendChild(confetti); const animation = confetti.animate([ { transform: 'translateY(-100vh) rotate(0deg)', opacity: 1 }, { transform: `translateY(${Math.random() * 100 + 100}vh) rotate(${Math.random() * 360}deg)`, opacity: 0 } ], { duration: Math.random() * 3000 + 2000, easing: 'cubic-bezier(0.1, 0.8, 0.3, 1)' }); animation.onfinish = () => confetti.remove(); } } // Initialize updatePlayerTurn(); }); </script> </body> </html> ``` This spicy Tic Tac Toe game includes: 1. **Visual Enhancements**: - Smooth animations and hover effects - Winning cells pulse with a golden glow - Confetti celebration when someone wins - 3D perspective on the game board 2. **Special Features**: - Dark/light mode toggle - Emoji mode (🔥 vs 💧 instead of X and O) - Score tracking for multiple games - Visual indication of whose turn it is 3. **Gameplay**: - Classic Tic Tac Toe rules - Automatic win detection - Draw detection - Reset and new game options The game is fully responsive and works on both desktop and mobile devices. The colorful design and interactive elements make it more engaging than a standard Tic Tac Toe game.
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>🌶️ Spicy Tic Tac Toe 🌶️</title> <style> :root { --spice: 5; } body { background: linear-gradient(135deg, #fff8e1, #ffe0b2); filter: hue-rotate(calc((var(--spice) - 5) * 10deg)); font-family: sans-serif; text-align: center; margin: 0; padding: 0; } .container { max-width: 400px; margin: 40px auto; padding: 20px; background: rgba(255,255,255,0.9); border-radius: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } h1 { margin-bottom: 10px; } .scoreboard { margin-bottom: 10px; font-size: 18px; } #board { display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); gap: 5px; margin-bottom: 10px; } .cell { width: 100px; height: 100px; font-size: 2.5rem; background: #fff; border: 2px solid #333; cursor: pointer; display: flex; align-items: center; justify-content: center; user-select: none; transition: background 0.2s; } .cell:hover { background: #f0f0f0; } .spicyLine { animation: fiery 0.5s infinite alternate; } @keyframes fiery { 0% { box-shadow: 0 0 10px 2px rgba(255,69,0,0.7); } 100% { box-shadow: 0 0 20px 4px rgba(255,215,0,0.9); } } .controls { margin-top: 10px; } label { font-size: 14px; } #message { margin-top: 10px; font-size: 20px; min-height: 24px; } button { padding: 8px 16px; font-size: 16px; cursor: pointer; margin-top: 5px; } input[type="range"] { width: 150px; margin-top: 5px; } </style> </head> <body> <div class="container"> <h1>🌶️ Spicy Tic Tac Toe 🌶️</h1> <div class="scoreboard"> X: <span id="x-score">0</span> | O: <span id="o-score">0</span> | Draws: <span id="draw-score">0</span> </div> <div id="board"></div> <div id="message"></div> <div class="controls"> <button id="reset">New Game</button> <div style="margin-top:10px;"> <label>Spice Level: <span id="spice-val">5</span></label><br> <input type="range" id="spice" min="0" max="10" value="5"> </div> </div> </div> <script> const boardElem = document.getElementById('board'); const messageElem = document.getElementById('message'); const xScoreElem = document.getElementById('x-score'); const oScoreElem = document.getElementById('o-score'); const drawScoreElem = document.getElementById('draw-score'); const resetBtn = document.getElementById('reset'); const spiceSlider = document.getElementById('spice'); const spiceVal = document.getElementById('spice-val'); let board, currentPlayer, scores; const winningCombos = [ [0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6] ]; function init() { board = Array(9).fill(''); currentPlayer = 'X'; scores = { X:0, O:0, Draws:0 }; xScoreElem.textContent = scores.X; oScoreElem.textContent = scores.O; drawScoreElem.textContent = scores.Draws; spiceSlider.value = 5; spiceVal.textContent = 5; updateSpice(5); renderBoard(); messageElem.textContent = "Player X's turn"; } function renderBoard() { boardElem.innerHTML = ''; board.forEach((cell, idx) => { const cellElem = document.createElement('div'); cellElem.classList.add('cell'); cellElem.dataset.index = idx; cellElem.textContent = cell; cellElem.addEventListener('click', onCellClick); boardElem.appendChild(cellElem); }); } function onCellClick(e) { const idx = e.target.dataset.index; if (board[idx] || checkWin()) return; board[idx] = currentPlayer; e.target.textContent = currentPlayer; if (checkWin()) { endGame(`${currentPlayer} wins!`); highlightWin(); scores[currentPlayer]++; updateScores(); } else if (board.every(c => c)) { endGame("It's a draw!"); scores.Draws++; updateScores(); } else { currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; messageElem.textContent = `${currentPlayer}'s turn`; } } function checkWin() { return winningCombos.some(combo => combo.every(i => board[i] === currentPlayer) ); } function highlightWin() { winningCombos.forEach(combo => { if (combo.every(i => board[i] === currentPlayer)) { combo.forEach(i => { boardElem.children[i].classList.add('spicyLine'); }); } }); } function endGame(msg) { messageElem.textContent = msg + ' 🌶️🔥'; } function updateScores() { xScoreElem.textContent = scores.X; oScoreElem.textContent = scores.O; drawScoreElem.textContent = scores.Draws; } resetBtn.addEventListener('click', () => { board.fill(''); document.querySelectorAll('.cell').forEach(c => { c.textContent = ''; c.classList.remove('spicyLine'); }); currentPlayer = 'X'; messageElem.textContent = "Player X's turn"; }); spiceSlider.addEventListener('input', (e) => { const val = e.target.value; spiceVal.textContent = val; updateSpice(val); }); function updateSpice(val) { document.documentElement.style.setProperty('--spice', val); } init(); </script> </body> </html> ```
Drag to resize
Here's a simple implementation of a Tic Tac Toe game in HTML, CSS, and JavaScript. To make it more special and spicy, I've added a few features such as: - A score tracker - A win/loss counter - A reset button - A spicy mode that randomizes the player's symbol (X or O) for each move ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tic Tac Toe</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" /> <style> body { font-family: Arial, sans-serif; text-align: center; } #game-board { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 10px; width: 300px; margin: 40px auto; } .cell { background-color: #f0f0f0; padding: 40px; border: none; border-radius: 10px; cursor: pointer; font-size: 24px; font-weight: bold; } .cell:hover { background-color: #e0e0e0; } #score { margin-bottom: 20px; } #reset-btn { background-color: #4CAF50; color: #fff; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; } #reset-btn:hover { background-color: #3e8e41; } #spicy-mode { margin-top: 20px; } </style> </head> <body> <h1>Tic Tac Toe</h1> <div id="score">Player X: 0, Player O: 0</div> <div id="game-board"> <button class="cell" id="cell-0"></button> <button class="cell" id="cell-1"></button> <button class="cell" id="cell-2"></button> <button class="cell" id="cell-3"></button> <button class="cell" id="cell-4"></button> <button class="cell" id="cell-5"></button> <button class="cell" id="cell-6"></button> <button class="cell" id="cell-7"></button> <button class="cell" id="cell-8"></button> </div> <button id="reset-btn">Reset</button> <div id="spicy-mode"> <input type="checkbox" id="spicy-checkbox"> <label for="spicy-checkbox">Spicy Mode</label> </div> <script> let currentPlayer = 'X'; let gameBoard = ['', '', '', '', '', '', '', '', '']; let score = { X: 0, O: 0 }; let spicyMode = false; const cells = document.querySelectorAll('.cell'); const scoreDiv = document.getElementById('score'); const resetBtn = document.getElementById('reset-btn'); const spicyCheckbox = document.getElementById('spicy-checkbox'); cells.forEach((cell, index) => { cell.addEventListener('click', () => { if (gameBoard[index] === '') { let symbol = currentPlayer; if (spicyMode) { symbol = Math.random() < 0.5 ? 'X' : 'O'; } gameBoard[index] = symbol; cell.textContent = symbol; checkWin(); currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; } }); }); resetBtn.addEventListener('click', () => { resetGame(); }); spicyCheckbox.addEventListener('change', () => { spicyMode = spicyCheckbox.checked; }); function checkWin() { const winConditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; for (let condition of winConditions) { if (gameBoard[condition[0]] !== '' && gameBoard[condition[0]] === gameBoard[condition[1]] && gameBoard[condition[1]] === gameBoard[condition[2]]) { const winner = gameBoard[condition[0]]; score[winner]++; scoreDiv.textContent = `Player X: ${score.X}, Player O: ${score.O}`; alert(`Player ${winner} wins!`); resetGame(); return; } } if (!gameBoard.includes('')) { alert('It\'s a draw!'); resetGame(); } } function resetGame() { currentPlayer = 'X'; gameBoard = ['', '', '', '', '', '', '', '', '']; cells.forEach(cell => cell.textContent = ''); } </script> </body> </html> ``` This code creates a simple Tic Tac Toe game with a score tracker, a reset button, and a spicy mode that randomizes the player's symbol for each move. When a player wins, the score is updated and an alert is displayed. When the game is a draw, an alert is displayed and the game is reset. The game can be reset manually using the reset button. The spicy mode can be toggled using the checkbox.
Drag to resize
# Spicy Tic Tac Toe Game I'll create a Tic Tac Toe game with a spicy twist: after each move, the board rotates 90 degrees clockwise! This adds an extra layer of challenge and strategy to the classic game. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spicy Tic Tac Toe</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; } .container { background-color: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); padding: 30px; width: 100%; max-width: 500px; text-align: center; } h1 { color: #fff; margin-bottom: 20px; font-size: 2.5rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } .spicy-text { color: #ff6b6b; font-weight: bold; animation: spicy 1s infinite alternate; } @keyframes spicy { from { text-shadow: 0 0 5px #ff6b6b; } to { text-shadow: 0 0 20px #ff6b6b, 0 0 30px #ff6b6b; } } .game-info { background-color: rgba(0, 0, 0, 0.2); border-radius: 10px; padding: 15px; margin-bottom: 20px; color: white; font-size: 1.2rem; } .current-player { font-weight: bold; font-size: 1.3rem; text-transform: uppercase; } .player-x { color: #ff6b6b; } .player-o { color: #4ecdc4; } .board-container { perspective: 1000px; margin: 20px auto; } .board { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 10px; width: 300px; height: 300px; margin: 0 auto; transition: transform 0.5s ease; } .cell { background-color: rgba(255, 255, 255, 0.9); border-radius: 10px; display: flex; justify-content: center; align-items: center; font-size: 3rem; font-weight: bold; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .cell:hover { background-color: rgba(255, 255, 255, 1); transform: scale(1.05); } .cell.x { color: #ff6b6b; } .cell.o { color: #4ecdc4; } .controls { margin-top: 20px; } button { background: linear-gradient(to right, #ff6b6b, #ff8e53); color: white; border: none; border-radius: 50px; padding: 12px 30px; font-size: 1.1rem; font-weight: bold; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); } button:hover { transform: translateY(-3px); box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3); } button:active { transform: translateY(1px); } .winning-cell { animation: win-pulse 1s infinite; } @keyframes win-pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(255, 215, 0, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0); } } .message { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center; flex-direction: column; z-index: 100; opacity: 0; pointer-events: none; transition: opacity 0.5s ease; } .message.show { opacity: 1; pointer-events: all; } .message-content { background: linear-gradient(135deg, #1a2a6c, #b21f1f); padding: 40px; border-radius: 20px; text-align: center; max-width: 80%; } .message h2 { color: white; font-size: 2.5rem; margin-bottom: 20px; } .message p { color: white; font-size: 1.5rem; margin-bottom: 30px; } .spicy-rules { background-color: rgba(0, 0, 0, 0.2); border-radius: 10px; padding: 15px; margin-top: 20px; color: white; font-size: 1rem; } .spicy-rules h3 { margin-bottom: 10px; color: #ff6b6b; } </style> </head> <body> <div class="container"> <h1>Tic Tac <span class="spicy-text">SPICY</span> Toe</h1> <div class="game-info"> <p>Current player: <span class="current-player player-x">X</span></p> </div> <div class="board-container"> <div class="board" id="board"> <div class="cell" data-index="0"></div> <div class="cell" data-index="1"></div> <div class="cell" data-index="2"></div> <div class="cell" data-index="3"></div> <div class="cell" data-index="4"></div> <div class="cell" data-index="5"></div> <div class="cell" data-index="6"></div> <div class="cell" data-index="7"></div> <div class="cell" data-index="8"></div> </div> </div> <div class="spicy-rules"> <h3>Spicy Rule:</h3> <p>After each move, the board rotates 90° clockwise!</p> </div> <div class="controls"> <button id="reset">New Game</button> </div> </div> <div class="message" id="message"> <div class="message-content"> <h2 id="message-title">Game Over!</h2> <p id="message-text"></p> <button id="play-again">Play Again</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const board = document.getElementById('board'); const cells = document.querySelectorAll('.cell'); const gameInfo = document.querySelector('.game-info'); const currentPlayerEl = document.querySelector('.current-player'); const resetBtn = document.getElementById('reset'); const message = document.getElementById('message'); const messageTitle = document.getElementById('message-title'); const messageText = document.getElementById('message-text'); const playAgainBtn = document.getElementById('play-again'); let currentPlayer = 'X'; let gameState = ['', '', '', '', '', '', '', '', '']; let gameActive = true; const winningConditions = [ [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 ]; // Handle cell click const handleCellClick = (e) => { const cell = e.target; const index = parseInt(cell.getAttribute('data-index')); // Check if cell is already played or game is inactive if (gameState[index] !== '' || !gameActive) return; // Update game state and UI gameState[index] = currentPlayer; cell.textContent = currentPlayer; cell.classList.add(currentPlayer.toLowerCase()); // Check for win or draw if (checkWin()) { endGame(false); return; } else if (checkDraw()) { endGame(true); return; } // Rotate the board rotateBoard(); // Switch player currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; updateCurrentPlayer(); }; // Rotate the board 90 degrees clockwise const rotateBoard = () => { // Rotate the game state const rotatedState = [ gameState[6], gameState[3], gameState[0], gameState[7], gameState[4], gameState[1], gameState[8], gameState[5], gameState[2] ]; gameState = rotatedState; // Update UI updateBoardUI(); // Add visual rotation effect board.style.transform = 'rotate(90deg)'; setTimeout(() => { board.style.transform = 'rotate(0deg)'; }, 500); }; // Update board UI based on game state const updateBoardUI = () => { cells.forEach((cell, index) => { cell.textContent = gameState[index]; cell.className = 'cell'; if (gameState[index] === 'X') { cell.classList.add('x'); } else if (gameState[index] === 'O') { cell.classList.add('o'); } }); }; // Update current player display const updateCurrentPlayer = () => { currentPlayerEl.textContent = currentPlayer; currentPlayerEl.className = `current-player player-${currentPlayer.toLowerCase()}`; }; // Check for win const checkWin = () => { for (let i = 0; i < winningConditions.length; i++) { const [a, b, c] = winningConditions[i]; if ( gameState[a] !== '' && gameState[a] === gameState[b] && gameState[a] === gameState[c] ) { // Highlight winning cells cells[a].classList.add('winning-cell'); cells[b].classList.add('winning-cell'); cells[c].classList.add('winning-cell'); return true; } } return false; }; // Check for draw const checkDraw = () => { return !gameState.includes(''); }; // End the game const endGame = (isDraw) => { gameActive = false; if (isDraw) { messageTitle.textContent = "It's a Draw!"; messageText.textContent = "The game ended in a tie!"; } else { messageTitle.textContent = `Player ${currentPlayer} Wins!`; messageText.textContent = `Congratulations to Player ${currentPlayer}!`; } setTimeout(() => { message.classList.add('show'); }, 1000); }; // Reset the game const resetGame = () => { gameState = ['', '', '', '', '', '', '', '', '']; currentPlayer = 'X'; gameActive = true; updateBoardUI(); updateCurrentPlayer(); // Remove winning highlights cells.forEach(cell => { cell.classList.remove('winning-cell'); }); // Hide message message.classList.remove('show'); }; // Event listeners cells.forEach(cell => { cell.addEventListener('click', handleCellClick); }); resetBtn.addEventListener('click', resetGame); playAgainBtn.addEventListener('click', resetGame); // Initialize game updateCurrentPlayer(); }); </script> </body> </html> ``` ## Spicy Features Added: 1. **Board Rotation**: After each move, the board rotates 90 degrees clockwise! This adds a strategic challenge as players need to think about how their moves will shift. 2. **Modern Design**: Gradient background with glass-morphism UI elements for a sleek, modern look. 3. **Visual Effects**: - Smooth animations for board rotation - Winning cells pulse with a golden glow - "Spicy" text in the title animates with a fiery glow - Hover effects on cells and buttons 4. **Responsive Design**: Works well on both desktop and mobile devices. 5. **Game State Management**: - Clear visual indication of current player - Win/draw detection with animations - Easy reset functionality 6. **Spicy Theme**: Red and orange color scheme with gradient effects to emphasize the "spicy" nature of the game. The game is fully functional - just click on any cell to place your mark (X goes first). After each move, the board rotates, changing the positions of all existing marks. Try it out and see how this twist changes your strategy!
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>🌶️ Spicy Tic Tac Toe 🌶️</title> <style> @import url('https://fonts.googleapis.com/css2?family=Fredoka+One:wght@400&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Fredoka One', cursive; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; } .game-container { text-align: center; background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 20px; padding: 30px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); } h1 { color: #fff; font-size: 2.5rem; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); animation: glow 2s ease-in-out infinite alternate; } @keyframes glow { from { text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3), 0 0 10px rgba(255, 255, 255, 0.5); } to { text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 255, 255, 0.8); } } .score-board { display: flex; justify-content: space-between; margin-bottom: 20px; gap: 20px; } .score { background: rgba(255, 255, 255, 0.2); padding: 10px 20px; border-radius: 15px; color: #fff; font-size: 1.2rem; min-width: 120px; } .current-player { color: #fff; font-size: 1.3rem; margin-bottom: 20px; animation: bounce 1s infinite; } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-10px); } 60% { transform: translateY(-5px); } } .game-board { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 10px; max-width: 300px; margin: 0 auto 20px; } .cell { width: 90px; height: 90px; background: rgba(255, 255, 255, 0.2); border: 3px solid rgba(255, 255, 255, 0.3); border-radius: 15px; font-size: 2rem; color: #fff; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden; } .cell:hover { transform: scale(1.1); background: rgba(255, 255, 255, 0.3); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); } .cell.winner { animation: winner-flash 1s infinite; background: rgba(255, 215, 0, 0.5); } @keyframes winner-flash { 0%, 50%, 100% { background: rgba(255, 215, 0, 0.5); } 25%, 75% { background: rgba(255, 255, 255, 0.5); } } .cell.clicked { animation: pop 0.5s ease; } @keyframes pop { 0% { transform: scale(1); } 50% { transform: scale(1.3); } 100% { transform: scale(1); } } .controls { display: flex; gap: 15px; justify-content: center; flex-wrap: wrap; } button { padding: 12px 24px; font-family: 'Fredoka One', cursive; font-size: 1rem; border: none; border-radius: 25px; cursor: pointer; transition: all 0.3s ease; text-transform: uppercase; letter-spacing: 1px; } .reset-btn { background: linear-gradient(45deg, #ff6b6b, #feca57); color: white; } .reset-btn:hover { transform: translateY(-3px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); } .mode-btn { background: linear-gradient(45deg, #48dbfb, #0abde3); color: white; } .mode-btn:hover { transform: translateY(-3px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); } .firework { position: absolute; width: 4px; height: 4px; border-radius: 50%; animation: firework 1s ease-out forwards; } @keyframes firework { 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(-100px); opacity: 0; } } .game-mode { color: #fff; margin-bottom: 15px; font-size: 1.1rem; } .ai-thinking { color: #feca57; animation: thinking 1.5s infinite; } @keyframes thinking { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } } </style> </head> <body> <div class="game-container"> <h1>🌶️ Spicy Tic Tac Toe 🌶️</h1> <div class="score-board"> <div class="score"> 🔥 Player: <span id="playerScore">0</span> </div> <div class="score"> 🤖 AI: <span id="aiScore">0</span> </div> </div> <div class="game-mode" id="gameMode">🎮 Player vs AI Mode</div> <div class="current-player" id="currentPlayer">Your turn! 🔥</div> <div class="game-board" id="gameBoard"></div> <div class="controls"> <button class="reset-btn" onclick="resetGame()">🔄 New Game</button> <button class="mode-btn" onclick="toggleMode()">👥 Switch Mode</button> </div> </div> <script> let board = ['', '', '', '', '', '', '', '', '']; let currentPlayer = 'X'; let gameActive = true; let isAIMode = true; let playerScore = 0; let aiScore = 0; let isAIThinking = false; const winningConditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; function initializeGame() { const gameBoard = document.getElementById('gameBoard'); gameBoard.innerHTML = ''; for (let i = 0; i < 9; i++) { const cell = document.createElement('div'); cell.classList.add('cell'); cell.setAttribute('data-index', i); cell.addEventListener('click', () => handleCellClick(i)); gameBoard.appendChild(cell); } updateDisplay(); } function handleCellClick(index) { if (board[index] !== '' || !gameActive || isAIThinking) return; makeMove(index, currentPlayer); if (gameActive && isAIMode && currentPlayer === 'O') { isAIThinking = true; updateCurrentPlayerDisplay(); setTimeout(() => { aiMove(); isAIThinking = false; updateCurrentPlayerDisplay(); }, 800); } } function makeMove(index, player) { board[index] = player; const cell = document.querySelector(`[data-index="${index}"]`); cell.textContent = player === 'X' ? '🔥' : '❄️'; cell.classList.add('clicked'); createFirework(cell); if (checkWinner()) { handleWin(); } else if (board.every(cell => cell !== '')) { handleDraw(); } else { currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; updateCurrentPlayerDisplay(); } } function aiMove() { if (!gameActive) return; // AI strategy: try to win, block player, or take center/corners let bestMove = findBestMove(); makeMove(bestMove, 'O'); } function findBestMove() { // Try to win for (let i = 0; i < 9; i++) { if (board[i] === '') { board[i] = 'O'; if (checkWinnerForPlayer('O')) { board[i] = ''; return i; } board[i] = ''; } } // Try to block player for (let i = 0; i < 9; i++) { if (board[i] === '') { board[i] = 'X'; if (checkWinnerForPlayer('X')) { board[i] = ''; return i; } board[i] = ''; } } // Take center if available if (board[4] === '') return 4; // Take corners const corners = [0, 2, 6, 8]; for (let corner of corners) { if (board[corner] === '') return corner; } // Take any available spot for (let i = 0; i < 9; i++) { if (board[i] === '') return i; } } function checkWinner() { return winningConditions.some(condition => { const [a, b, c] = condition; if (board[a] && board[a] === board[b] && board[a] === board[c]) { highlightWinningCells(condition); return true; } return false; }); } function checkWinnerForPlayer(player) { return winningConditions.some(condition => { const [a, b, c] = condition; return board[a] === player && board[b] === player && board[c] === player; }); } function highlightWinningCells(condition) { condition.forEach(index => { document.querySelector(`[data-index="${index}"]`).classList.add('winner'); }); } function handleWin() { gameActive = false; const winner = currentPlayer === 'X' ? 'Player' : 'AI'; if (currentPlayer === 'X') { playerScore++; document.getElementById('currentPlayer').textContent = '🎉 You Win! Amazing! 🎉'; } else { aiScore++; document.getElementById('currentPlayer').textContent = '🤖 AI Wins! Try again! 🤖'; } updateScores(); createCelebration(); } function handleDraw() { gameActive = false; document.getElementById('currentPlayer').textContent = '🤝 It\'s a Draw! 🤝'; } function createFirework(element) { const colors = ['#ff6b6b', '#feca57', '#48dbfb', '#ff9ff3', '#54a0ff']; for (let i = 0; i < 5; i++) { const firework = document.createElement('div'); firework.classList.add('firework'); firework.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; firework.style.left = Math.random() * 50 + 25 + '%'; firework.style.animationDelay = Math.random() * 0.5 + 's'; element.appendChild(firework); setTimeout(() => { if (firework.parentNode) { firework.parentNode.removeChild(firework); } }, 1000); } } function createCelebration() { const container = document.querySelector('.game-container'); for (let i = 0; i < 20; i++) { const firework = document.createElement('div'); firework.classList.add('firework'); firework.style.backgroundColor = `hsl(${Math.random() * 360}, 70%, 60%)`; firework.style.position = 'absolute'; firework.style.left = Math.random() * 100 + '%'; firework.style.top = Math.random() * 100 + '%'; firework.style.animationDuration = Math.random() * 2 + 1 + 's'; container.appendChild(firework); setTimeout(() => { if (firework.parentNode) { firework.parentNode.removeChild(firework); } }, 3000); } } function updateCurrentPlayerDisplay() { const currentPlayerElement = document.getElementById('currentPlayer'); if (!gameActive) return; if (isAIThinking) { currentPlayerElement.textContent = '🤖 AI is thinking... 🤖'; currentPlayerElement.classList.add('ai-thinking'); } else { currentPlayerElement.classList.remove('ai-thinking'); if (isAIMode) { currentPlayerElement.textContent = currentPlayer === 'X' ? 'Your turn! 🔥' : 'AI\'s turn! 🤖'; } else { currentPlayerElement.textContent = currentPlayer === 'X' ? 'Player 1\'s turn! 🔥' : 'Player 2\'s turn! ❄️'; } } } function updateDisplay() { updateCurrentPlayerDisplay(); updateGameMode(); } function updateGameMode() { document.getElementById('gameMode').textContent = isAIMode ? '🎮 Player vs AI Mode' : '👥 Two Player Mode'; } function updateScores() { document.getElementById('playerScore').textContent = playerScore; document.getElementById('aiScore').textContent = aiScore; } function resetGame() { board = ['', '', '', '', '', '', '', '', '']; currentPlayer = 'X'; gameActive = true; isAIThinking = false; document.querySelectorAll('.cell').forEach(cell => { cell.textContent = ''; cell.classList.remove('winner', 'clicked'); }); updateDisplay(); } function toggleMode() { isAIMode = !isAIMode; resetGame(); // Reset scores when changing modes playerScore = 0; aiScore = 0; updateScores(); updateDisplay(); } // Initialize the game initializeGame(); </script> </body> </html> ``` This spicy Tic Tac Toe game features: 🌶️ **Special Features:** - **Visual Effects**: Glowing animations, fireworks on moves, celebration animations on wins - **Smart AI**: AI that tries to win, blocks your moves, and plays strategically - **Two Game Modes**: Player vs AI or Two Player mode - **Score Tracking**: Keeps track of wins for both players/AI - **Responsive Design**: Beautiful glassmorphism design with gradients - **Sound-like Feedback**: Visual bouncing and scaling animations - **Special Emojis**: Fire (🔥) for Player 1/Human, Snowflake (❄️) for Player 2/AI - **Thinking Animation**: Shows when AI is "thinking" - **Winner Highlighting**: Winning cells flash with golden animation 🎮 **Controls:** - Click cells to make moves - "New Game" button to restart - "Switch Mode" button to toggle between AI and two-player modes The game has a modern, engaging interface with smooth animations and a challenging AI opponent that makes strategic moves!
Drag to resize