Skip to content

Commit

Permalink
Tic Tac Toe JS vanilla made as practice, 2P mode & Vs cpu mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Isa696 committed Dec 1, 2023
0 parents commit 890822f
Show file tree
Hide file tree
Showing 3 changed files with 321 additions and 0 deletions.
29 changes: 29 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Ta Te Ti</title>
</head>
<body>
<header>
<div class="checkbox-wrapper-25" >
<input type="checkbox" >
</div>
</header>
<h1>Ta Te Ti</h1>

<div id="status">Jugaror X turno</div>

<div id="board"></div>

<div class="reset-container">
<button class="btn-reset">
Reset
</button>
</div>

<script src="main.js"></script>
</body>
</html>
128 changes: 128 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
document.addEventListener('DOMContentLoaded', () => {
const gameModeCheckbox = document.querySelector('.checkbox-wrapper-25 input');
const gameModeButton = document.getElementById('game-mode');

const board = document.getElementById('board');
const status = document.getElementById('status');
const cells = [];

let currentPlayer = 'X';
let winner = null;
let singlePlayerMode = false;

function startSinglePlayerGame() {
singlePlayerMode = true;
resetGame();
}

function resetGame() {
currentPlayer = 'X';
winner = null;

// Limpiar el tablero y reiniciar las celdas
cells.forEach(cell => {
cell.textContent = '';
cell.classList.remove('cell-winner');
});

status.textContent = singlePlayerMode ? 'Tu turno "X"' : 'Turno "X"';

// Si es el modo de un solo jugador y es el turno de la CPU, que realice su movimiento
if (singlePlayerMode && currentPlayer === 'O') {
makeCPUMove();
}
}

function handleCellClick(event) {
const clickedCell = event.target;
const index = clickedCell.dataset.index;

// Check if the cell is already taken or if there is a winner
if (!cells[index].textContent && !winner) {
cells[index].textContent = currentPlayer;

// Check for a winner after each move
if (checkWinner()) {
status.textContent = `Jugador ${winner} Gana!`;
} else if (isBoardFull()) {
status.textContent = "Es Empate!";
} else {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
status.textContent = singlePlayerMode ? `Turno "${currentPlayer}"` : `Turno "${currentPlayer}"`;

if (singlePlayerMode && currentPlayer === 'O') {
// Es el turno de la CPU en el modo de un solo jugador
setTimeout(() => {
makeCPUMove();
}, 1000);
}
}
}
}

function makeCPUMove() {
// Filtra las celdas disponibles
const availableCells = cells.filter(cell => !cell.textContent);

if (availableCells.length > 0) {
// Elige una celda aleatoria para la CPU
const randomIndex = Math.floor(Math.random() * availableCells.length);
const selectedCell = availableCells[randomIndex];

// Simula el clic en la celda seleccionada por la CPU
selectedCell.click();
}
}

function checkWinner() {
const winningCombos = [
[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
];

for (const combo of winningCombos) {
const [a, b, c] = combo;
if (cells[a].textContent && cells[a].textContent === cells[b].textContent && cells[a].textContent === cells[c].textContent) {
winner = cells[a].textContent;
highlightWinnerCells(combo);
return true;
}
}

return false;
}

function isBoardFull() {
return cells.every(cell => cell.textContent);
}

function highlightWinnerCells(cellsToHighlight) {
cellsToHighlight.forEach(index => {
cells[index].classList.add('cell-winner');
});
}

// Inicializar el tablero de juego
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);
}

// Agregar evento de cambio al checkbox
gameModeCheckbox.addEventListener('change', function () {
singlePlayerMode = this.checked;
resetGame();
});

// Agregar evento de clic al botón de reinicio
const btnReset = document.querySelector('.btn-reset');
btnReset.addEventListener('click', resetGame);

// Agregar evento de clic al botón de modo de juego
gameModeButton.addEventListener('click', startSinglePlayerGame);
});
164 changes: 164 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
* {
padding: 0;
margin: 0;
font-family: 'Itim', cursive;
}

body {
font-family: 'Arial', sans-serif;
text-align: center;
background-color: #ffffff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='600' viewBox='0 0 900 600'%3E%3Cg %3E%3Cpath fill='%232E163B' d='M306.9 210.2c-1.2-22.8-13.5-42.7-40.8-41.1c-18.3 1.1-35.9 3.6-47.5 20.1c-5.2 7.4-10.6 15.6-11.4 24.9c-0.5 5.8 0.2 12 1.2 17.7c9 49.6 85.3 46.7 96.4 0.2C306.6 224.9 307.3 217.4 306.9 210.2z'/%3E%3Cpath fill='%2338194a' d='M137.2 481.3c-13.2-9.9-31.2-13.3-48.5-3.2c-12.6 7.3-19.1 17.4-21.1 28.2c-0.7 2.4-1.2 4.7-1.5 7c-8.2 35.4 33.7 78.9 72.6 48.6C167.6 539.3 164.4 501.6 137.2 481.3z'/%3E%3Cg fill='%23411c59' %3E%3Cpath d='M547.9 588.3c-7.1-34.2-61.6-52.7-87.5-16.9c-11.2 11.3-12.7 26.3-7.6 39.7c1.8 7.5 5.5 13.9 10.4 19.1c19.4 20.3 53.4 26.2 72.8 1.9C545.9 619.7 553.9 604.2 547.9 588.3z'/%3E%3Cpath d='M547.9-11.7c-7.1-34.2-61.6-52.7-87.5-16.9c-11.2 11.3-12.7 26.3-7.6 39.7c1.8 7.5 5.5 13.9 10.4 19.1c19.4 20.3 53.4 26.2 72.8 1.9C545.9 19.7 553.9 4.2 547.9-11.7z'/%3E%3C/g%3E%3Cpath fill='%234b1e69' d='M849.7 498c-22.3 1.3-43.2 7.5-52.7 29.5c-3.3 7.7-7.3 15.7-7 24.3c2 55.6 86.1 63.4 98.8 10.1C890.6 554.6 877.3 496.4 849.7 498z'/%3E%3Cpath fill='%23532079' d='M762 291.1c-8.2-6.1-19.1-1.9-27.3 2.2c-7.4 3.7-14.4 8.2-21.6 12.1c-6.6 3.6-13.7 7-19.8 11.5c-18.3 13.5-2.5 45.1 10.6 56.4c17 14.6 41.6 15.9 59.6 2.1C794.1 351.8 790.7 312.4 762 291.1z'/%3E%3Cpath fill='%235c218a' d='M863.3 170.3c-4.5-15.7-17.9-28.8-33.4-34.4c-16.2-5.8-38.4-2.9-51.8 8.1c-14.9 12.2-14.5 31.7-11.4 49c9.6 53.9 84.3 47.7 97-1.3C865.6 184.4 865.3 177.1 863.3 170.3z'/%3E%3Cpath fill='%2363219c' d='M598.4 86.1c-10.2 15.5-9.3 34.2-0.9 50.4c2.6 5 6.2 9.5 10.4 13.2c14.2 12.6 35.5 17.1 53.2 9.5c14.3-6.1 23.9-19.8 26.7-34.7C707.4 75.6 629.7 38.5 598.4 86.1z'/%3E%3Cpath fill='%236b21ae' d='M509.8 413.3c-17.3 22.6-11.8 59 17.5 75.3c22.6 12.6 52.2 1.7 63.8-20.9c21.4-42-9.2-85-56.5-71C523.8 399.9 515.6 405.8 509.8 413.3z'/%3E%3Cpath fill='%237120c1' d='M607.4 232.3c-0.5-0.4-1-0.8-1.4-1.2c-16.5-12.8-30.2-22.1-50.3-8.4c-15.5 10.6-29 30.3-31.4 49.1c-4.2 33.6 30.6 46.9 58.6 40.6C619.6 304.2 640.6 259.5 607.4 232.3z'/%3E%3Cpath fill='%23771fd4' d='M410.6 95c-36.5 1.3-74.1 41.8-43.1 74.3c19.8 20.9 54.4 20.7 74.6 0.5c20.5-20.4 18.4-53.1-6.9-68.6C427.7 96.6 419.2 94.7 410.6 95z'/%3E%3Cpath fill='%237c22e3' d='M291.3 23c-0.1-0.1-0.1-0.1-0.2-0.2c-14.2-16.9-38.3-25.6-61.4-12.3c-13.5 7.8-20.5 18.7-22.7 30.2c-5.7 18 1.5 34.2 14.2 44.8c15.4 16.8 40.3 24.1 64.2 5.5c9.6-7.4 15-16.3 17.2-25.4C308.6 48.8 302.7 33.6 291.3 23z'/%3E%3Cpath fill='%23822ee9' d='M419.1 440.6c-16.9-14.5-41.8-21.5-61.7-9.5c-18.3 11.1-1 100.1 32.2 93.5c23.8-4.7 45.3-22.4 48.1-44.3C439.6 466.1 431.5 451.3 419.1 440.6z'/%3E%3Cpath fill='%23883bee' d='M127 227c-12-4.3-25.4-2.1-38.7 11.4C71 255.9 61.4 286.1 80.4 306c21.3 22.3 86.9 27.5 89.6-14.9c0.5-8.9-2.7-17.9-6.5-25.8C155.1 248.3 142.1 232.5 127 227z'/%3E%3Cpath fill='%238f48f3' d='M281.5 407.6c-0.3-0.4-0.7-0.7-1-1c-19.3-17.6-59.1-0.6-78.1 10.3c-23.8 13.7-8.2 41.1 5.4 55.8c16.3 17.6 42.7 25.2 68 5.8C291.3 466.6 295.5 422.7 281.5 407.6z'/%3E%3Cpath fill='%239656f7' d='M137.9 110.2c-10.4-25.7-43.3-32.1-67-23.6C60.1 90.4 50 97.8 45.1 108.6c-21.2 47.3 44.9 81.1 78.5 51c9.5-8.5 17.3-18.9 17.4-32.4C141 120.8 139.9 115.1 137.9 110.2z'/%3E%3Cpath fill='%239d65fa' d='M344.3 284.7c-10 14.9-9.2 34.1-0.9 49.5c3.4 6.3 8.6 13.8 16.1 15.8c7.1 1.9 15.1 0.7 22.1-0.6c15.7-3 45.6-10.5 52.3-26.8C453.5 274.4 375.6 237.9 344.3 284.7z'/%3E%3Cg fill='%23a574fd' %3E%3Cpath d='M-29.2 431.8c23.4 12.4 54.1 1.7 66.1-20.6c9.6-17.8 10.4-40.4-3.3-56.5c-10.5-12.4-44.2-25.8-58.5-11.3c-3 3.1-5.1 7.1-6.9 10.9C-41.1 373.2-55 418.1-29.2 431.8z'/%3E%3Cpath d='M870.8 431.8c23.4 12.4 54.1 1.7 66.1-20.6c9.6-17.8 10.4-40.4-3.3-56.5c-10.5-12.4-44.2-25.8-58.5-11.3c-3 3.1-5.1 7.1-6.9 10.9C858.9 373.2 845 418.1 870.8 431.8z'/%3E%3C/g%3E%3Cpath fill='%23AE84FF' d='M671.4 460.5c-10.7 1.7-20.2 8.3-26.2 22.2c-21.5 49.5 45.4 84.9 79.4 53.3c16.3-15.2 24-31 6.5-48.1c-5.9-5.8-12.3-11-19.1-15.6C699.5 463.7 684.5 458.4 671.4 460.5z'/%3E%3C/g%3E%3C/svg%3E");
background-attachment: fixed;
}

header {
display: flex;
height: 30px;
align-items: center;
justify-content: flex-end;
}

.reset-container {
margin-top: 1rem;
display: flex;
align-items: center;
justify-content: center;
}

#board {
margin: 0 auto;
display: grid;
grid-template-columns: 33% 33% 33%;
grid-template-rows: 33% 33% 33%;
max-width: 300px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0));
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
}

.cell {
border-radius: 6px;
width: 98px;
height: 98px;
font-size: 24px;
border: 2px solid #333;
cursor: pointer;
}

.cell:hover {
background-color: #a7a6a6;
}

#status {
margin-top: 20px;
font-size: 18px;
}

.cell-winner {
background-color: #d2aaff;
}

.checkbox-wrapper-25 input[type="checkbox"] {
background-image: -webkit-linear-gradient(hsla(0, 0%, 0%, .1), hsla(0, 0%, 100%, .1)),
-webkit-linear-gradient(left, #f66 50%, #6cf 50%);
background-size: 100% 100%, 200% 100%;
background-position: 0 0, 15px 0;
border-radius: 25px;
box-shadow: inset 0 1px 4px hsla(0, 0%, 0%, .5),
inset 0 0 10px hsla(0, 0%, 0%, .5),
0 0 0 1px hsla(0, 0%, 0%, .1),
0 -1px 2px 2px hsla(0, 0%, 0%, .25),
0 2px 2px 2px hsla(0, 0%, 100%, .75);
cursor: pointer;
height: 25px;
padding-right: 25px;
width: 75px;
appearance: none;
transition: .25s;
}

.checkbox-wrapper-25 input[type="checkbox"]:after {
background-color: #eee;
background-image: -webkit-linear-gradient(hsla(0, 0%, 100%, .1), hsla(0, 0%, 0%, .1));
border-radius: 25px;
box-shadow: inset 0 1px 1px 1px hsla(0, 0%, 100%, 1),
inset 0 -1px 1px 1px hsla(0, 0%, 0%, .25),
0 1px 3px 1px hsla(0, 0%, 0%, .5),
0 0 2px hsla(0, 0%, 0%, .25);
width: 50px;
height: 25px;
display: block;
content: 'VS';
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}

.checkbox-wrapper-25 input[type="checkbox"]:checked {
background-position: 0 0, 35px 0;
padding-left: 25px;
padding-right: 0;
}

.checkbox-wrapper-25 input[type="checkbox"]:checked:after {
content: 'CPU'; /* Contenido cuando el checkbox está marcado */
}
.btn-reset {
position: relative;
width: 120px;
height: 40px;
background-color: #000;
display: flex;
align-items: center;
color: white;
flex-direction: column;
justify-content: center;
border: none;
padding: 12px;
gap: 12px;
border-radius: 8px;
cursor: pointer;
}

.btn-reset::before {
content: '';
position: absolute;
inset: 0;
left: -4px;
top: -1px;
margin: auto;
width: 128px;
height: 48px;
border-radius: 10px;
background: linear-gradient(-45deg, #e81cff 0%, #40c9ff 100%);
z-index: -10;
pointer-events: none;
transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.btn-reset::after {
content: "";
z-index: -1;
position: absolute;
inset: 0;
background: linear-gradient(-45deg, #fc00ff 0%, #00dbde 100%);
transform: translate3d(0, 0, 0) scale(0.95);
filter: blur(20px);
}

.btn-reset:hover::after {
filter: blur(30px);
}

.btn-reset:hover::before {
transform: rotate(-180deg);
}

.btn-reset:active::before {
scale: 0.7;
}

0 comments on commit 890822f

Please sign in to comment.