Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New tic-tac-toe game added #32

Merged
merged 1 commit into from
Oct 25, 2022
Merged
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
33 changes: 33 additions & 0 deletions tic-tac-toe/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="./style.css">
</head>

<body>
<section>
<h1 class="game--title">Tic Tac Toe</h1>
<div class="game--container">
<div data-cell-index="0" class="cell"></div>
<div data-cell-index="1" class="cell"></div>
<div data-cell-index="2" class="cell"></div>
<div data-cell-index="3" class="cell"></div>
<div data-cell-index="4" class="cell"></div>
<div data-cell-index="5" class="cell"></div>
<div data-cell-index="6" class="cell"></div>
<div data-cell-index="7" class="cell"></div>
<div data-cell-index="8" class="cell"></div>
</div>
<h2 class="game--status"></h2>
<button class="game--restart">Restart Game</button>
</section>
<script src="./script.js"></script>
</body>

</html>
187 changes: 187 additions & 0 deletions tic-tac-toe/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
We store our game status element here to allow us to more easily
use it later on
*/
const statusDisplay = document.querySelector('.game--status');
/*
Here we declare some variables that we will use to track the
game state throught the game.
*/
/*
We will use gameActive to pause the game in case of an end scenario
*/
let gameActive = true;
/*
We will store our current player here, so we know whos turn
*/
let currentPlayer = "X";
/*
We will store our current game state here, the form of empty strings in an array
will allow us to easily track played cells and validate the game state later on
*/
let gameState = ["", "", "", "", "", "", "", "", ""];
/*
Here we have declared some messages we will display to the user during the game.
Since we have some dynamic factors in those messages, namely the current player,
we have declared them as functions, so that the actual message gets created with
current data every time we need it.
*/
const winningMessage = () => `Player ${currentPlayer} has won!`;
const drawMessage = () => `Game ended in a draw!`;
const currentPlayerTurn = () => `It's ${currentPlayer}'s turn`;
/*
We set the inital message to let the players know whose turn it is
*/
statusDisplay.innerHTML = currentPlayerTurn();
function handleCellPlayed() {

}
function handlePlayerChange() {

}
function handleResultValidation() {

}
function handleCellClick() {

}
function handleRestartGame() {

}
/*
And finally we add our event listeners to the actual game cells, as well as our
restart button
*/
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', handleCellClick));
document.querySelector('.game--restart').addEventListener('click', handleRestartGame);

function handleCellClick(clickedCellEvent) {
/*
We will save the clicked html element in a variable for easier further use
*/
const clickedCell = clickedCellEvent.target;
/*
Here we will grab the 'data-cell-index' attribute from the clicked cell to identify where that cell is in our grid.
Please note that the getAttribute will return a string value. Since we need an actual number we will parse it to an
integer(number)
*/
const clickedCellIndex = parseInt(
clickedCell.getAttribute('data-cell-index')
);
/*
Next up we need to check whether the call has already been played,
or if the game is paused. If either of those is true we will simply ignore the click.
*/
if (gameState[clickedCellIndex] !== "" || !gameActive) {
return;
}
/*
If everything if in order we will proceed with the game flow
*/
handleCellPlayed(clickedCell, clickedCellIndex);
handleResultValidation();
}

function handleCellPlayed(clickedCell, clickedCellIndex) {
/*
We update our internal game state to reflect the played move,
as well as update the user interface to reflect the played move
*/
gameState[clickedCellIndex] = currentPlayer;
clickedCell.innerHTML = currentPlayer;
}

const winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
function handleResultValidation() {
let roundWon = false;
for (let i = 0; i <= 7; i++) {
const winCondition = winningConditions[i];
let a = gameState[winCondition[0]];
let b = gameState[winCondition[1]];
let c = gameState[winCondition[2]];
if (a === '' || b === '' || c === '') {
continue;
}
if (a === b && b === c) {
roundWon = true;
break
}
}
if (roundWon) {
statusDisplay.innerHTML = winningMessage();
gameActive = false;
return;
}
}


winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
function handleResultValidation() {
let roundWon = false;
for (let i = 0; i <= 7; i++) {
const winCondition = winningConditions[i];
let a = gameState[winCondition[0]];
let b = gameState[winCondition[1]];
let c = gameState[winCondition[2]];
if (a === '' || b === '' || c === '') {
continue;
}
if (a === b && b === c) {
roundWon = true;
break
}
}
if (roundWon) {
statusDisplay.innerHTML = winningMessage();
gameActive = false;
return;
}
/*
We will check weather there are any values in our game state array
that are still not populated with a player sign
*/
let roundDraw = !gameState.includes("");
if (roundDraw) {
statusDisplay.innerHTML = drawMessage();
gameActive = false;
return;
}
/*
If we get to here we know that the no one won the game yet,
and that there are still moves to be played, so we continue by changing the current player.
*/
handlePlayerChange();
}

function handlePlayerChange() {
currentPlayer = currentPlayer === "X" ? "O" : "X";
statusDisplay.innerHTML = currentPlayerTurn();
}


function handleRestartGame() {
gameActive = true;
currentPlayer = "X";
gameState = ["", "", "", "", "", "", "", "", ""];
statusDisplay.innerHTML = currentPlayerTurn();
document.querySelectorAll('.cell')
.forEach(cell => cell.innerHTML = "");
}
25 changes: 25 additions & 0 deletions tic-tac-toe/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
body {
font-family: "Arial", sans-serif;
}

section {
text-align: center;
}

.game--container {
display: grid;
grid-template-columns: repeat(3, auto);
width: 306px;
margin: 50px auto;
}

.cell {
font-family: "Permanent Marker", cursive;
width: 100px;
height: 100px;
box-shadow: 0 0 0 1px #333333;
border: 1px solid #333333;
cursor: pointer;
line-height: 100px;
font-size: 60px;
}