|
3 | 3 |
|
4 | 4 | function getProjectHTML(projectName) { |
5 | 5 | const projects = { |
| 6 | + 'tic-tac-toe': getTicTacToeHTML(), |
6 | 7 | 'rock-paper-scissor': getRockPaperScissorHTML(), |
7 | 8 | 'dice-rolling': getDiceRollingHTML(), |
8 | 9 | 'coin-flip': getCoinFlipHTML(), |
@@ -34,6 +35,7 @@ function getProjectHTML(projectName) { |
34 | 35 |
|
35 | 36 | function initializeProject(projectName) { |
36 | 37 | const initializers = { |
| 38 | + 'tic-tac-toe': initTicTacToe, |
37 | 39 | 'rock-paper-scissor': initRockPaperScissor, |
38 | 40 | 'dice-rolling': initDiceRolling, |
39 | 41 | 'coin-flip': initCoinFlip, |
@@ -297,6 +299,186 @@ function initRockPaperScissor() { |
297 | 299 | } |
298 | 300 | } |
299 | 301 |
|
| 302 | +// ============================================ |
| 303 | +// Tic Tac Toe |
| 304 | +// ============================================ |
| 305 | + |
| 306 | +function getTicTacToeHTML() { |
| 307 | + return ` |
| 308 | + <div class="project-content"> |
| 309 | + <h2>🧩 Tic-Tac-Toe</h2> |
| 310 | + <div class="ttt-mode-buttons"> |
| 311 | + <button id="pvpMode" class="mode-btn active-mode"> |
| 312 | + 👥 2 Players |
| 313 | + </button> |
| 314 | +
|
| 315 | + <button id="aiMode" class="mode-btn"> |
| 316 | + you vs Computer |
| 317 | + </button> |
| 318 | + </div> |
| 319 | + <div class="game-container"> |
| 320 | + <div class="tic-tac-toe-board" id="ticTacToeBoard"> |
| 321 | + <button class="cell" data-cell="0"></button> |
| 322 | + <button class="cell" data-cell="1"></button> |
| 323 | + <button class="cell" data-cell="2"></button> |
| 324 | + <button class="cell" data-cell="3"></button> |
| 325 | + <button class="cell" data-cell="4"></button> |
| 326 | + <button class="cell" data-cell="5"></button> |
| 327 | + <button class="cell" data-cell="6"></button> |
| 328 | + <button class="cell" data-cell="7"></button> |
| 329 | + <button class="cell" data-cell="8"></button> |
| 330 | + </div> |
| 331 | +
|
| 332 | + <p id="ticTacToeStatus">Player X's turn</p> |
| 333 | +
|
| 334 | + <button id="restartTicTacToe" class="game-btn"> |
| 335 | + 🔄 Restart Game |
| 336 | + </button> |
| 337 | + </div> |
| 338 | + </div> |
| 339 | + `; |
| 340 | +} |
| 341 | + |
| 342 | +function initTicTacToe() { |
| 343 | + const cells = document.querySelectorAll('.cell'); |
| 344 | + const statusText = document.getElementById('ticTacToeStatus'); |
| 345 | + const restartBtn = document.getElementById('restartTicTacToe'); |
| 346 | + const twoPlayerBtn = document.getElementById('twoPlayerMode'); |
| 347 | + const computerBtn = document.getElementById('computerMode'); |
| 348 | + |
| 349 | + let vsComputer = false; |
| 350 | + let currentPlayer = 'X'; |
| 351 | + let board = ['', '', '', '', '', '', '', '', '']; |
| 352 | + let gameActive = true; |
| 353 | + |
| 354 | + |
| 355 | + |
| 356 | + const pvpBtn = document.getElementById('pvpMode'); |
| 357 | + const aiBtn = document.getElementById('aiMode'); |
| 358 | + |
| 359 | + pvpBtn.addEventListener('click', () => { |
| 360 | + vsComputer = false; |
| 361 | + |
| 362 | + pvpBtn.classList.add('active-mode'); |
| 363 | + aiBtn.classList.remove('active-mode'); |
| 364 | + |
| 365 | + resetGame(); |
| 366 | + statusText.textContent = "2 Player Mode"; |
| 367 | + }); |
| 368 | + |
| 369 | + aiBtn.addEventListener('click', () => { |
| 370 | + vsComputer = true; |
| 371 | + |
| 372 | + aiBtn.classList.add('active-mode'); |
| 373 | + pvpBtn.classList.remove('active-mode'); |
| 374 | + |
| 375 | + resetGame(); |
| 376 | + statusText.textContent = "Playing vs Computer"; |
| 377 | + }); |
| 378 | + |
| 379 | + const winningCombinations = [ |
| 380 | + [0,1,2], |
| 381 | + [3,4,5], |
| 382 | + [6,7,8], |
| 383 | + [0,3,6], |
| 384 | + [1,4,7], |
| 385 | + [2,5,8], |
| 386 | + [0,4,8], |
| 387 | + [2,4,6] |
| 388 | + ]; |
| 389 | + |
| 390 | + function checkWinner() { |
| 391 | + for (let combo of winningCombinations) { |
| 392 | + const [a, b, c] = combo; |
| 393 | + |
| 394 | + if ( |
| 395 | + board[a] && |
| 396 | + board[a] === board[b] && |
| 397 | + board[a] === board[c] |
| 398 | + ) { |
| 399 | + statusText.textContent = `🎉 Player ${board[a]} wins!`; |
| 400 | + gameActive = false; |
| 401 | + return; |
| 402 | + } |
| 403 | + } |
| 404 | + |
| 405 | + if (!board.includes('')) { |
| 406 | + statusText.textContent = "🤝 It's a draw!"; |
| 407 | + gameActive = false; |
| 408 | + } |
| 409 | + } |
| 410 | + |
| 411 | + cells.forEach(cell => { |
| 412 | + cell.addEventListener('click', () => { |
| 413 | + const index = cell.dataset.cell; |
| 414 | + |
| 415 | + if (board[index] || !gameActive) return; |
| 416 | + |
| 417 | + board[index] = currentPlayer; |
| 418 | + cell.textContent = currentPlayer; |
| 419 | + |
| 420 | + checkWinner(); |
| 421 | + |
| 422 | + if (vsComputer && gameActive && currentPlayer === 'X') { |
| 423 | + currentPlayer = 'O'; |
| 424 | + statusText.textContent = "Computer's turn"; |
| 425 | + |
| 426 | + setTimeout(() => { |
| 427 | + computerMove(); |
| 428 | + }, 500); |
| 429 | + |
| 430 | + return; |
| 431 | + } |
| 432 | + |
| 433 | + if (gameActive) { |
| 434 | + currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; |
| 435 | + statusText.textContent = `Player ${currentPlayer}'s turn`; |
| 436 | + } |
| 437 | + }); |
| 438 | + }); |
| 439 | + |
| 440 | + function resetGame() { |
| 441 | + board = ['', '', '', '', '', '', '', '', '']; |
| 442 | + gameActive = true; |
| 443 | + currentPlayer = 'X'; |
| 444 | + |
| 445 | + cells.forEach(cell => { |
| 446 | + cell.textContent = ''; |
| 447 | + }); |
| 448 | + |
| 449 | + statusText.textContent = "Player X's turn"; |
| 450 | +} |
| 451 | + |
| 452 | +function computerMove() { |
| 453 | + let emptyCells = []; |
| 454 | + |
| 455 | + board.forEach((cell, index) => { |
| 456 | + if (cell === '') { |
| 457 | + emptyCells.push(index); |
| 458 | + } |
| 459 | + }); |
| 460 | + |
| 461 | + if (emptyCells.length === 0) return; |
| 462 | + |
| 463 | + const randomIndex = |
| 464 | + emptyCells[Math.floor(Math.random() * emptyCells.length)]; |
| 465 | + |
| 466 | + board[randomIndex] = 'O'; |
| 467 | + cells[randomIndex].textContent = 'O'; |
| 468 | + |
| 469 | + checkWinner(); |
| 470 | + |
| 471 | + if (gameActive) { |
| 472 | + currentPlayer = 'X'; |
| 473 | + statusText.textContent = "Player X's turn"; |
| 474 | + } |
| 475 | +} |
| 476 | + |
| 477 | +restartBtn.addEventListener('click', resetGame); |
| 478 | +} |
| 479 | + |
| 480 | + |
| 481 | + |
300 | 482 | // ============================================ |
301 | 483 | // DICE ROLLING |
302 | 484 | // ============================================ |
|
0 commit comments