Skip to content
This repository was archived by the owner on Jun 21, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions game.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const boardElem = document.getElementById('board');
const newGameBtn = document.getElementById('newGameBtn');
const modeSelect = document.getElementById('modeSelect');

let board = Array(9).fill(null);
let currentPlayer = 'X';
let gameActive = true;
let mode = '2p';

function renderBoard() {
boardElem.innerHTML = '';
board.forEach((cell, idx) => {
const cellElem = document.createElement('div');
cellElem.className = 'cell';
cellElem.textContent = cell || '';
cellElem.addEventListener('click', () => handleCellClick(idx));
boardElem.appendChild(cellElem);
});
}

function handleCellClick(idx) {
if (!gameActive || board[idx]) return;
board[idx] = currentPlayer;
renderBoard();
if (checkWin(currentPlayer)) {
setTimeout(() => alert(`${currentPlayer} wins!`), 100);
gameActive = false;
return;
}
if (board.every(cell => cell)) {
setTimeout(() => alert('Draw!'), 100);
gameActive = false;
return;
}
if (mode === 'ai' && currentPlayer === 'X') {
currentPlayer = 'O';
setTimeout(aiMove, 400);
} else {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
}
}

function aiMove() {
// Simple AI: pick random empty cell
const empty = board.map((cell, i) => cell ? null : i).filter(i => i !== null);
if (empty.length === 0) return;
const move = empty[Math.floor(Math.random() * empty.length)];
board[move] = 'O';
renderBoard();
if (checkWin('O')) {
setTimeout(() => alert('O wins!'), 100);
gameActive = false;
return;
}
if (board.every(cell => cell)) {
setTimeout(() => alert('Draw!'), 100);
gameActive = false;
return;
}
currentPlayer = 'X';
}

function checkWin(player) {
const wins = [
[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
];
return wins.some(line => line.every(i => board[i] === player));
}

function newGame() {
board = Array(9).fill(null);
currentPlayer = 'X';
gameActive = true;
renderBoard();
if (mode === 'ai' && currentPlayer === 'O') {
setTimeout(aiMove, 400);
}
}

newGameBtn.addEventListener('click', newGame);
modeSelect.addEventListener('change', e => {
mode = e.target.value;
newGame();
});

// Initial render
renderBoard();
21 changes: 21 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!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 - Brno Scrum Workshop</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="banner">Brno scrum workshop</div>
<div class="controls">
<button id="newGameBtn">New Game</button>
<select id="modeSelect">
<option value="2p">Two Players</option>
<option value="ai">Play vs AI</option>
</select>
</div>
<div class="board" id="board"></div>
<script src="game.js"></script>
</body>
</html>
80 changes: 80 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
body {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: url('https://cdn.pixabay.com/photo/2017/01/06/19/15/cat-1958376_1280.png') no-repeat center center fixed;
background-size: cover;
}

.banner {
background: rgba(255, 255, 255, 0.85);
text-align: center;
font-size: 2.2rem;
font-weight: bold;
padding: 1rem 0;
margin-bottom: 1.5rem;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.controls {
display: flex;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
}

#newGameBtn, #modeSelect {
font-size: 1rem;
padding: 0.5rem 1rem;
border-radius: 5px;
border: 1px solid #888;
background: #fff;
cursor: pointer;
}

.board {
display: grid;
grid-template-columns: repeat(3, 80px);
grid-template-rows: repeat(3, 80px);
gap: 10px;
justify-content: center;
margin: 0 auto;
background: rgba(255,255,255,0.7);
border-radius: 12px;
padding: 20px;
width: max-content;
}

.cell {
width: 80px;
height: 80px;
background: #f9f9f9;
border: 2px solid #333;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
font-weight: bold;
cursor: pointer;
transition: background 0.2s;
}

.cell:hover {
background: #e0e0e0;
}

@media (max-width: 600px) {
.board {
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(3, 50px);
padding: 10px;
}
.cell {
width: 50px;
height: 50px;
font-size: 1.5rem;
}
.banner {
font-size: 1.2rem;
}
}