Files
myworkspace/TicTacToe-Compare/qwen3.6-27b/index.html

301 lines
6.9 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #1a1a2e;
color: #eee;
font-family: 'Segoe UI', system-ui, sans-serif;
}
h1 {
font-size: 2.4rem;
margin-bottom: 0.5rem;
letter-spacing: 2px;
}
#status {
font-size: 1.2rem;
min-height: 2rem;
margin-bottom: 1rem;
color: #aaa;
}
#board {
display: grid;
grid-template-columns: repeat(3, 110px);
grid-template-rows: repeat(3, 110px);
gap: 6px;
}
.cell {
width: 110px;
height: 110px;
background: #16213e;
border: 2px solid #0f3460;
border-radius: 8px;
font-size: 3rem;
font-weight: bold;
color: #eee;
cursor: pointer;
transition: background 0.15s;
display: flex;
align-items: center;
justify-content: center;
}
.cell:hover { background: #1a2a50; }
.cell.taken { cursor: default; }
.cell.x { color: #e94560; }
.cell.o { color: #53d8fb; }
/* ---- overlays ---- */
.overlay {
position: fixed;
inset: 0;
background: rgba(10, 10, 30, 0.92);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 10;
}
.overlay.hidden { display: none; }
#coin {
width: 120px;
height: 120px;
border-radius: 50%;
background: radial-gradient(circle at 40% 40%, #ffd700, #b8860b);
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
font-weight: 800;
color: #1a1a2e;
margin-bottom: 1.5rem;
}
#coin.flip {
animation: coinFlip 0.8s ease-in-out;
}
@keyframes coinFlip {
0% { transform: scale(1) rotateY(0); }
40% { transform: scale(1.3) rotateY(900deg); }
60% { transform: scale(1.3) rotateY(1800deg); }
100% { transform: scale(1) rotateY(3600deg); }
}
#coin-text {
font-size: 1.5rem;
margin-bottom: 0.6rem;
}
.result-title {
font-size: 2.8rem;
font-weight: 700;
margin-bottom: 1rem;
}
.result-sub {
font-size: 1.2rem;
color: #aaa;
margin-bottom: 1.5rem;
}
button {
padding: 0.7rem 2rem;
font-size: 1.1rem;
border: none;
border-radius: 6px;
background: #e94560;
color: #fff;
cursor: pointer;
transition: background 0.15s;
}
button:hover { background: #c73a52; }
.win-line {
background: #0a3d62 !important;
border-color: #e94560 !important;
}
</style>
</head>
<body>
<h1>Tic-Tac-Toe</h1>
<div id="status"></div>
<div id="board"></div>
<!-- Coin flip overlay -->
<div class="overlay" id="coinOverlay">
<div id="coin">?</div>
<div id="coin-text">Flipping a coin…</div>
</div>
<!-- Game over overlay -->
<div class="overlay hidden" id="endOverlay">
<div class="result-title" id="endTitle"></div>
<div class="result-sub" id="endSub"></div>
<button id="restartBtn">Play Again</button>
</div>
<script>
const WIN_PATTERNS = [
[0,1,2],[3,4,5],[6,7,8],
[0,3,6],[1,4,7],[2,5,8],
[0,4,8],[2,4,6]
];
let board, playerMark, compMark, currentPlayer, gameOver;
const boardEl = document.getElementById('board');
const statusEl = document.getElementById('status');
const coinOverlay = document.getElementById('coinOverlay');
const coinEl = document.getElementById('coin');
const coinText = document.getElementById('coin-text');
const endOverlay = document.getElementById('endOverlay');
const endTitle = document.getElementById('endTitle');
const endSub = document.getElementById('endSub');
// ---------- init ----------
function init() {
board = Array(9).fill(null);
gameOver = false;
endOverlay.classList.add('hidden');
buildBoard();
coinText.textContent = 'Flipping a coin…';
coinEl.textContent = '?';
coinEl.classList.remove('flip');
coinOverlay.classList.remove('hidden');
void coinEl.offsetWidth;
coinEl.classList.add('flip');
setTimeout(() => {
const heads = Math.random() < 0.5;
coinEl.textContent = heads ? 'H' : 'T';
if (heads) {
playerMark = 'X';
compMark = 'O';
currentPlayer = 'player';
coinText.textContent = 'Heads! You go first as X.';
} else {
playerMark = 'O';
compMark = 'X';
currentPlayer = 'computer';
coinText.textContent = 'Tails! Computer goes first as X.';
}
statusEl.textContent = currentPlayer === 'player'
? 'Your turn'
: "Computer's turn";
setTimeout(() => {
coinOverlay.classList.add('hidden');
if (currentPlayer === 'computer') {
setTimeout(compMove, 1000);
}
}, 1400);
}, 850);
}
function buildBoard() {
boardEl.innerHTML = '';
for (let i = 0; i < 9; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.dataset.index = i;
cell.addEventListener('click', () => handleClick(i));
boardEl.appendChild(cell);
}
}
function render() {
const cells = boardEl.querySelectorAll('.cell');
cells.forEach((c, i) => {
c.textContent = board[i] || '';
c.classList.remove('x', 'o', 'taken');
if (board[i]) {
c.classList.add(board[i], 'taken');
}
});
}
function handleClick(i) {
if (gameOver || board[i] || currentPlayer !== 'player') return;
board[i] = playerMark;
render();
if (checkEnd()) return;
currentPlayer = 'computer';
statusEl.textContent = "Computer's turn";
setTimeout(compMove, 600);
}
function compMove() {
if (gameOver) return;
const empties = board.map((v, i) => v === null ? i : -1).filter(i => i !== -1);
if (!empties.length) return;
board[empties[Math.floor(Math.random() * empties.length)]] = compMark;
render();
checkEnd();
}
function checkEnd() {
const winner = checkWinner();
if (winner) {
gameOver = true;
const cells = boardEl.querySelectorAll('.cell');
const line = WIN_PATTERNS.find(p => p.every(i => board[i] === winner));
if (line) line.forEach(i => cells[i].classList.add('win-line'));
const isPlayer = winner === playerMark;
endTitle.textContent = isPlayer ? 'You Win!' : 'Computer Wins!';
endSub.textContent = isPlayer
? 'Great job! Want to play again?'
: 'Better luck next time. Play again?';
setTimeout(() => endOverlay.classList.remove('hidden'), 700);
return true;
}
if (board.every(c => c !== null)) {
gameOver = true;
endTitle.textContent = 'It\'s a Draw!';
endSub.textContent = 'No winner this round. Try again?';
setTimeout(() => endOverlay.classList.remove('hidden'), 700);
return true;
}
if (!gameOver) {
currentPlayer = (currentPlayer === 'player') ? 'computer' : 'player';
statusEl.textContent = currentPlayer === 'player' ? 'Your turn' : "Computer's turn";
}
return false;
}
function checkWinner() {
for (const [a, b, c] of WIN_PATTERNS) {
if (board[a] && board[a] === board[b] && board[a] === board[c]) return board[a];
}
return null;
}
document.getElementById('restartBtn').addEventListener('click', init);
init();
</script>
</body>
</html>