Skip to content

Instantly share code, notes, and snippets.

@nicolechung
Last active January 11, 2019 21:37
Show Gist options
  • Save nicolechung/c84221d73235720dc908c4e9131b6c4c to your computer and use it in GitHub Desktop.
Save nicolechung/c84221d73235720dc908c4e9131b6c4c to your computer and use it in GitHub Desktop.
Tic Tac Toe (HTML, SASS, ES6 Javascript)
<html>
<body>
<h2>Click on a square to start</h2>
<div id="container">
<div id="game-box">
<div data-box="1" class="box"> </div>
<div data-box="2" class="box"> </div>
<div data-box="3" class="box"> </div>
<div data-box="4" class="box"> </div>
<div data-box="5" class="box"> </div>
<div data-box="6" class="box"> </div>
<div data-box="7" class="box"> </div>
<div data-box="8" class="box"> </div>
<div data-box="9" class="box"> </div>
</div>
<div id="won">
<p id="won-message"></p>
<button id="reset">reset</button>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
import './style.scss'
const el = document.getElementById('game-box')
el.addEventListener('click', handleClick);
const button = document.getElementById('reset')
button.addEventListener('click', reset);
let turn = 'x'
let xStyle = 'background-color: #7FDBFF'
let oStyle = 'background-color: #F012BE'
let turnStyle = xStyle
const WIN_LENGTH = 2
let board
function reset() {
board = [
{x:0, y: 0},
{x:1, y: 0},
{x:2, y: 0},
{x:0, y: 1},
{x:1, y: 1},
{x:2, y: 1},
{x:0, y: 2},
{x:1, y: 2},
{x:2, y: 2},
]
const divs = document.getElementsByClassName('box');
for (let i = 0; i < divs.length; i++) {
const div = divs[i]
div.innerHTML = ''
div.style = ''
}
const el = document.getElementById('won-message')
el.innerHTML = 'Start! (click)'
const wonBox = document.getElementById('won')
wonBox.classList.remove("bounceIn")
}
function toggleTurn() {
if (turn === 'x'){
turn = 'o'
turnStyle = oStyle
} else {
turn = 'x'
turnStyle = xStyle
}
}
function handleClick(event) {
const box = event.target.dataset.box
if (score(turn, box)) {
const list = document.querySelectorAll(`[data-box='${box}']`)
const domElement = list[0]
domElement.style = turnStyle
domElement.innerHTML = turn
toggleTurn()
calculateScore()
}
}
function score(turn, box) {
const boxToScore = parseInt(box, 10) - 1
if (!board[boxToScore].turn) {
board[boxToScore]= {
...board[boxToScore],
turn: turn
}
return true
} else {
alert('this box is taken')
return false
}
}
function calculateScore() {
const x = board.filter(item => item.turn === 'x')
const o = board.filter(item => item.turn === 'o')
const xWon = checkPlayerWon(x)
const oWon = checkPlayerWon(o)
if (xWon || oWon) {
let winner = ''
if (xWon) {
winner = 'x'
} else {
winner = 'o'
}
const el = document.getElementById('won-message')
el.innerHTML = winner + ' has won'
const wonBox = document.getElementById('won')
wonBox.classList.add("bounceIn")
setTimeout(reset, 2000)
}
}
function checkPlayerWon(player) {
return checkStraightWins(player, 'x') || checkStraightWins(player, 'y') || checkDiagonalWins(player)
}
function checkStraightWins(player, xy) {
const result = player.filter(item => item[xy] === 0).length > WIN_LENGTH ||
player.filter(item => item[xy] === 1).length > WIN_LENGTH ||
player.filter(item => item[xy] === WIN_LENGTH).length > WIN_LENGTH
return result
}
function checkDiagonalWins(player) {
const diagonal1 = [
{
x:0, y:0
},
{
x:1, y:1
},
{
x:2, y:2
},
]
const diagonal2 = [
{
x:2, y:0
},
{
x:1, y:1
},
{
x:0, y:2
},
]
const diagonal1Compare = arrayCompare(player, diagonal1)
const diagonal2Compare = arrayCompare(player, diagonal2)
const result = diagonal1Compare || diagonal2Compare
return result
}
function arrayCompare(player, win) {
const filtered = player.filter(player_item => {
return win.filter(win_item => {
return player_item.x == win_item.x && player_item.y == win_item.y
}).length > 0
})
return filtered.length > WIN_LENGTH
}
/* start game by resetting / initializing the board */
reset()
h2 {
text-align: center;
font-family: 'Noto Sans', sans-serif;
margin: 30px auto 0;
color: #001f3f;
}
@-webkit-keyframes bounceIn {
from,
20%,
40%,
60%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
20% {
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
60% {
opacity: 1;
-webkit-transform: scale3d(1.03, 1.03, 1.03);
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
-webkit-transform: scale3d(0.97, 0.97, 0.97);
transform: scale3d(0.97, 0.97, 0.97);
}
to {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes bounceIn {
from,
20%,
40%,
60%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
20% {
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
60% {
opacity: 1;
-webkit-transform: scale3d(1.03, 1.03, 1.03);
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
-webkit-transform: scale3d(0.97, 0.97, 0.97);
transform: scale3d(0.97, 0.97, 0.97);
}
to {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
#container {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
font-family: 'Noto Sans', sans-serif;
}
#game-box {
display: flex;
margin: 50px 0;
grid-column-gap: 10px;
width: 180px;
border: 2px solid #001f3f;
flex-wrap: wrap;
& > div {
flex: 1;
min-width: 50px;
height: 50px;
font-size: 40px;
line-height: 39px;
text-align: center;
padding: 0;
cursor: pointer;
border: 2px solid #001f3f;
}
}
#won {
background-color: #FFDC00;
display: block;
width: 230px;
height: 160px;
margin: 0 20px;
text-align: center;
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
&.bounceIn {
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-animation-name: bounceIn;
animation-name: bounceIn;
}
p {
font-size: 22px;
}
}
button {
margin: 30px auto;
padding: 5px 20px 10px;
display: block;
border: none;
background-color: #FF851B;
color: white;
font-size: 14px;
border-radius: 4px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment