-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c465096
commit 3fe0076
Showing
3 changed files
with
245 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = ""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |