Neon Tic-Tac-Toe
by AtomicRaven42275 lines7.1 KB
<!--ARCADELAB title: Neon Tic-Tac-Toe description: A polished Tic-Tac-Toe game with a glowing neon theme, featuring local 2-player mode and an AI opponent. libraries: none emoji: ❌ color: purple -->
<!DOCTYPE html>
<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>
<style>
:root {
--bg-color: #0d1117;
--panel-bg: #161b22;
--text-color: #c9d1d9;
--x-color: #ff4a5a;
--o-color: #38bdf8;
--accent-color: #8b5cf6;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
overflow: hidden;
}
.container {
text-align: center;
background: var(--panel-bg);
padding: 30px;
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
border: 1px solid #30363d;
max-width: 400px;
width: 100%;
}
h1 {
font-size: 2rem;
margin-bottom: 20px;
background: linear-gradient(45deg, var(--x-color), var(--o-color));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.controls {
margin-bottom: 20px;
display: flex;
justify-content: center;
gap: 10px;
}
.btn {
background: #21262d;
color: var(--text-color);
border: 1px solid #30363d;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.2s;
}
.btn:hover {
background: #30363d;
border-color: #8b5cf6;
}
.btn.active {
background: var(--accent-color);
color: white;
border-color: var(--accent-color);
}
.status {
font-size: 1.2rem;
margin-bottom: 20px;
height: 30px;
font-weight: 500;
}
.board {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
margin-bottom: 20px;
}
.cell {
aspect-ratio: 1;
background: #21262d;
border: 1px solid #30363d;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
font-weight: bold;
cursor: pointer;
transition: background 0.2s, transform 0.1s;
}
.cell:hover {
background: #30363d;
}
.cell:active {
transform: scale(0.95);
}
.cell.X {
color: var(--x-color);
text-shadow: 0 0 10px rgba(255, 74, 90, 0.5);
}
.cell.O {
color: var(--o-color);
text-shadow: 0 0 10px rgba(56, 189, 248, 0.5);
}
.cell.win {
background: #238636;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>Tic-Tac-Toe</h1>
<div class="controls">
<button id="pvpBtn" class="btn active" onclick="setMode('pvp')">2 Player</button>
<button id="aiBtn" class="btn" onclick="setMode('ai')">vs AI</button>
</div>
<div class="status" id="statusText">X's Turn</div>
<div class="board" id="board">
<div class="cell" onclick="makeMove(this, 0)"></div>
<div class="cell" onclick="makeMove(this, 1)"></div>
<div class="cell" onclick="makeMove(this, 2)"></div>
<div class="cell" onclick="makeMove(this, 3)"></div>
<div class="cell" onclick="makeMove(this, 4)"></div>
<div class="cell" onclick="makeMove(this, 5)"></div>
<div class="cell" onclick="makeMove(this, 6)"></div>
<div class="cell" onclick="makeMove(this, 7)"></div>
<div class="cell" onclick="makeMove(this, 8)"></div>
</div>
<button class="btn" style="width: 100%; padding: 12px;" onclick="resetGame()">Reset Game</button>
</div>
<script>
let board = ['', '', '', '', '', '', '', '', ''];
let currentPlayer = 'X';
let gameActive = true;
let gameMode = 'pvp'; // 'pvp' or 'ai'
const statusText = document.getElementById('statusText');
const cells = document.querySelectorAll('.cell');
const winPatterns = [, [3, 4, 5], [6, 7, 8], // Rows, [1, 4, 7], [2, 5, 8], // Columns, [2, 4, 6] // Diagonals
];
function setMode(mode) {
gameMode = mode;
document.getElementById('pvpBtn').classList.toggle('active', mode === 'pvp');
document.getElementById('aiBtn').classList.toggle('active', mode === 'ai');
resetGame();
}
function makeMove(cell, index) {
if (board[index] !== '' || !gameActive) return;
board[index] = currentPlayer;
cell.innerText = currentPlayer;
cell.classList.add(currentPlayer);
checkResult();
if (gameActive && gameMode === 'ai' && currentPlayer === 'O') {
gameActive = false; // Temporarily disable player inputs during AI turn
setTimeout(aiMove, 400);
}
}
function aiMove() {
// 1. Try to win or block
let move = findBestMove('O') ?? findBestMove('X');
// 2. Take center if available
if (move === null && board[4] === '') move = 4;
// 3. Take random empty spot
if (move === null) {
const emptyCells = board.map((val, idx) => val === '' ? idx : null).filter(val => val !== null);
move = emptyCells[Math.floor(Math.random() * emptyCells.length)];
}
if (move !== null) {
board[move] = 'O';
cells[move].innerText = 'O';
cells[move].classList.add('O');
gameActive = true;
checkResult();
}
}
function findBestMove(player) {
for (let pattern of winPatterns) {
const values = pattern.map(idx => board[idx]);
const playerCount = values.filter(v => v === player).length;
const emptyCount = values.filter(v => v === '').length;
if (playerCount === 2 && emptyCount === 1) {
return pattern[values.indexOf('')];
}
}
return null;
}
function checkResult() {
let roundWon = false;
let winningPattern = [];
for (let pattern of winPatterns) {
const [a, b, c] = pattern;
if (board[a] && board[a] === board[b] && board[a] === board[c]) {
roundWon = true;
winningPattern = pattern;
break;
}
}
if (roundWon) {
statusText.innerText = `${currentPlayer} Wins! 🎉`;
winningPattern.forEach(idx => cells[idx].classList.add('win'));
gameActive = false;
return;
}
if (!board.includes('')) {
statusText.innerText = "It's a Draw! 🤝";
gameActive = false;
return;
}
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
statusText.innerText = `${currentPlayer}'s Turn`;
}
function resetGame() {
board = ['', '', '', '', '', '', '', '', ''];
currentPlayer = 'X';
gameActive = true;
statusText.innerText = "X's Turn";
cells.forEach(cell => {
cell.innerText = '';
cell.className = 'cell';
});
}
</script>
</body>
</html>
Game Source: Neon Tic-Tac-Toe
Creator: AtomicRaven42
Libraries: none
Complexity: complex (275 lines, 7.1 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: neon-tic-tac-toe-atomicraven42" to link back to the original. Then publish at arcadelab.ai/publish.