Skip to content

Commit 875e198

Browse files
authored
Merge pull request #150 from gurleen3/master
TicTacToe using JS
2 parents 37054a4 + 1575635 commit 875e198

File tree

3 files changed

+263
-0
lines changed

3 files changed

+263
-0
lines changed

TicTacToeGame/gurleen3/index.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<link rel="stylesheet" href="styles.css">
8+
<script src="script.js" defer></script>
9+
<title>Document</title>
10+
</head>
11+
<body>
12+
<div class="board" id="board">
13+
<div class="cell" data-cell></div>
14+
<div class="cell" data-cell></div>
15+
<div class="cell" data-cell></div>
16+
<div class="cell" data-cell></div>
17+
<div class="cell" data-cell></div>
18+
<div class="cell" data-cell></div>
19+
<div class="cell" data-cell></div>
20+
<div class="cell" data-cell></div>
21+
<div class="cell" data-cell></div>
22+
</div>
23+
<div class="winning-message" id="winningMessage">
24+
<div data-winning-message-text></div>
25+
<button id="restartButton">Restart</button>
26+
</div>
27+
</body>
28+
</html>

TicTacToeGame/gurleen3/script.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const X_CLASS = 'x'
2+
const CIRCLE_CLASS = 'circle'
3+
const WINNING_COMBINATIONS = [
4+
[0, 1, 2],
5+
[3, 4, 5],
6+
[6, 7, 8],
7+
[0, 3, 6],
8+
[1, 4, 7],
9+
[2, 5, 8],
10+
[0, 4, 8],
11+
[2, 4, 6]
12+
]
13+
const cellElements = document.querySelectorAll('[data-cell]')
14+
const board = document.getElementById('board')
15+
const winningMessageElement = document.getElementById('winningMessage')
16+
const restartButton = document.getElementById('restartButton')
17+
const winningMessageTextElement = document.querySelector('[data-winning-message-text]')
18+
let circleTurn
19+
20+
startGame()
21+
22+
restartButton.addEventListener('click', startGame)
23+
24+
function startGame() {
25+
circleTurn = false
26+
cellElements.forEach(cell => {
27+
cell.classList.remove(X_CLASS)
28+
cell.classList.remove(CIRCLE_CLASS)
29+
cell.removeEventListener('click', handleClick)
30+
cell.addEventListener('click', handleClick, { once: true })
31+
})
32+
setBoardHoverClass()
33+
winningMessageElement.classList.remove('show')
34+
}
35+
36+
function handleClick(e) {
37+
const cell = e.target
38+
const currentClass = circleTurn ? CIRCLE_CLASS : X_CLASS
39+
placeMark(cell, currentClass)
40+
if (checkWin(currentClass)) {
41+
endGame(false)
42+
} else if (isDraw()) {
43+
endGame(true)
44+
} else {
45+
swapTurns()
46+
setBoardHoverClass()
47+
}
48+
}
49+
50+
function endGame(draw) {
51+
if (draw) {
52+
winningMessageTextElement.innerText = 'Draw!'
53+
} else {
54+
winningMessageTextElement.innerText = `${circleTurn ? "O's" : "X's"} Wins!`
55+
}
56+
winningMessageElement.classList.add('show')
57+
}
58+
59+
function isDraw() {
60+
return [...cellElements].every(cell => {
61+
return cell.classList.contains(X_CLASS) || cell.classList.contains(CIRCLE_CLASS)
62+
})
63+
}
64+
65+
function placeMark(cell, currentClass) {
66+
cell.classList.add(currentClass)
67+
}
68+
69+
function swapTurns() {
70+
circleTurn = !circleTurn
71+
}
72+
73+
function setBoardHoverClass() {
74+
board.classList.remove(X_CLASS)
75+
board.classList.remove(CIRCLE_CLASS)
76+
if (circleTurn) {
77+
board.classList.add(CIRCLE_CLASS)
78+
} else {
79+
board.classList.add(X_CLASS)
80+
}
81+
}
82+
83+
function checkWin(currentClass) {
84+
return WINNING_COMBINATIONS.some(combination => {
85+
return combination.every(index => {
86+
return cellElements[index].classList.contains(currentClass)
87+
})
88+
})
89+
}

TicTacToeGame/gurleen3/styles.css

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
*, *::after, *::before {
2+
box-sizing: border-box;
3+
}
4+
5+
:root {
6+
--cell-size: 100px;
7+
--mark-size: calc(var(--cell-size) * .9);
8+
}
9+
10+
body {
11+
margin: 0;
12+
}
13+
14+
.board {
15+
width: 100vw;
16+
height: 100vh;
17+
display: grid;
18+
justify-content: center;
19+
align-content: center;
20+
justify-items: center;
21+
align-items: center;
22+
grid-template-columns: repeat(3, auto)
23+
}
24+
25+
.cell {
26+
width: var(--cell-size);
27+
height: var(--cell-size);
28+
border: 1px solid black;
29+
display: flex;
30+
justify-content: center;
31+
align-items: center;
32+
position: relative;
33+
cursor: pointer;
34+
}
35+
36+
.cell:first-child,
37+
.cell:nth-child(2),
38+
.cell:nth-child(3) {
39+
border-top: none;
40+
}
41+
42+
.cell:nth-child(3n + 1) {
43+
border-left: none;
44+
}
45+
46+
.cell:nth-child(3n + 3) {
47+
border-right: none;
48+
}
49+
50+
.cell:last-child,
51+
.cell:nth-child(8),
52+
.cell:nth-child(7) {
53+
border-bottom: none;
54+
}
55+
56+
.cell.x,
57+
.cell.circle {
58+
cursor: not-allowed;
59+
}
60+
61+
.cell.x::before,
62+
.cell.x::after,
63+
.cell.circle::before {
64+
background-color: black;
65+
}
66+
67+
.board.x .cell:not(.x):not(.circle):hover::before,
68+
.board.x .cell:not(.x):not(.circle):hover::after,
69+
.board.circle .cell:not(.x):not(.circle):hover::before {
70+
background-color: lightgrey;
71+
}
72+
73+
.cell.x::before,
74+
.cell.x::after,
75+
.board.x .cell:not(.x):not(.circle):hover::before,
76+
.board.x .cell:not(.x):not(.circle):hover::after {
77+
content: '';
78+
position: absolute;
79+
width: calc(var(--mark-size) * .15);
80+
height: var(--mark-size);
81+
}
82+
83+
.cell.x::before,
84+
.board.x .cell:not(.x):not(.circle):hover::before {
85+
transform: rotate(45deg);
86+
}
87+
88+
.cell.x::after,
89+
.board.x .cell:not(.x):not(.circle):hover::after {
90+
transform: rotate(-45deg);
91+
}
92+
93+
.cell.circle::before,
94+
.cell.circle::after,
95+
.board.circle .cell:not(.x):not(.circle):hover::before,
96+
.board.circle .cell:not(.x):not(.circle):hover::after {
97+
content: '';
98+
position: absolute;
99+
border-radius: 50%;
100+
}
101+
102+
.cell.circle::before,
103+
.board.circle .cell:not(.x):not(.circle):hover::before {
104+
width: var(--mark-size);
105+
height: var(--mark-size);
106+
}
107+
108+
.cell.circle::after,
109+
.board.circle .cell:not(.x):not(.circle):hover::after {
110+
width: calc(var(--mark-size) * .7);
111+
height: calc(var(--mark-size) * .7);
112+
background-color: white;
113+
}
114+
115+
.winning-message {
116+
display: none;
117+
position: fixed;
118+
top: 0;
119+
left: 0;
120+
right: 0;
121+
bottom: 0;
122+
background-color: rgba(0, 0, 0, .9);
123+
justify-content: center;
124+
align-items: center;
125+
color: white;
126+
font-size: 5rem;
127+
flex-direction: column;
128+
}
129+
130+
.winning-message button {
131+
font-size: 3rem;
132+
background-color: white;
133+
border: 1px solid black;
134+
padding: .25em .5em;
135+
cursor: pointer;
136+
}
137+
138+
.winning-message button:hover {
139+
background-color: black;
140+
color: white;
141+
border-color: white;
142+
}
143+
144+
.winning-message.show {
145+
display: flex;
146+
}

0 commit comments

Comments
 (0)