From 4a4cd67e466b23f1ac8438c92854488c9a9d8f82 Mon Sep 17 00:00:00 2001
From: Vishnu Prakash <75669541+Visthebeast@users.noreply.github.com>
Date: Sat, 30 Sep 2023 15:54:08 +0530
Subject: [PATCH] Tic-Tac-Toe game
Added a tic-tac-toe game in Frontend Projects
---
Frontend Projects/Tic-Tac-Toe/.gitattributes | 2 +
Frontend Projects/Tic-Tac-Toe/README.md | 2 +
Frontend Projects/Tic-Tac-Toe/index.html | 28 ++++
Frontend Projects/Tic-Tac-Toe/script.js | 103 +++++++++++++
Frontend Projects/Tic-Tac-Toe/style.css | 153 +++++++++++++++++++
5 files changed, 288 insertions(+)
create mode 100644 Frontend Projects/Tic-Tac-Toe/.gitattributes
create mode 100644 Frontend Projects/Tic-Tac-Toe/README.md
create mode 100644 Frontend Projects/Tic-Tac-Toe/index.html
create mode 100644 Frontend Projects/Tic-Tac-Toe/script.js
create mode 100644 Frontend Projects/Tic-Tac-Toe/style.css
diff --git a/Frontend Projects/Tic-Tac-Toe/.gitattributes b/Frontend Projects/Tic-Tac-Toe/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/Frontend Projects/Tic-Tac-Toe/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/Frontend Projects/Tic-Tac-Toe/README.md b/Frontend Projects/Tic-Tac-Toe/README.md
new file mode 100644
index 0000000..4715e4b
--- /dev/null
+++ b/Frontend Projects/Tic-Tac-Toe/README.md
@@ -0,0 +1,2 @@
+# Tic-Tac-Toe
+A very basic tic-tac-toe game
diff --git a/Frontend Projects/Tic-Tac-Toe/index.html b/Frontend Projects/Tic-Tac-Toe/index.html
new file mode 100644
index 0000000..7fde833
--- /dev/null
+++ b/Frontend Projects/Tic-Tac-Toe/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ Tic-Tac-Toe
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Frontend Projects/Tic-Tac-Toe/script.js b/Frontend Projects/Tic-Tac-Toe/script.js
new file mode 100644
index 0000000..d874199
--- /dev/null
+++ b/Frontend Projects/Tic-Tac-Toe/script.js
@@ -0,0 +1,103 @@
+const x_class = 'x'
+const o_class = 'o'
+const winning_Combinations=[
+ //horizontal winning combos
+ [0,1,2], [3,4,5], [6,7,8],
+ //vertical winning combos
+ [0,3,6], [1,4,7], [2,5,8],
+ //diagonal winning combos
+ [0,4,8], [2,4,6]
+]
+const winningMessage = document.getElementById('winning')
+const winningMessageText = document.querySelector('[data-winning-message]')
+const cellElements = document.querySelectorAll('[data-cell]')
+const restartButton = document.getElementById('restartbutton')
+const board = document.getElementById('board')
+let circleTurn
+
+//startgame
+startGame()
+
+restartButton.addEventListener('click', startGame)
+
+function startGame(){
+ circleTurn = false
+ cellElements.forEach(cell => {
+ cell.classList.remove(x_class)
+ cell.classList.remove(o_class)
+ cell.removeEventListener('click', handleClick)
+ cell.addEventListener('click', handleClick, { once: true })
+ })
+ setBoardHoverClass()
+ winningMessage.classList.remove('show')
+}
+//console.log('hello')
+
+function handleClick(e){
+ console.log('clicked')
+ const cell = e.target
+ const currentClass = circleTurn ? o_class : x_class
+ //place mark
+ placeMark(cell,currentClass)
+
+ //when someone wins
+ if(checkWin(currentClass)){
+ console.log(currentClass + ' winner')
+ endGame(false)
+ }
+ else if(isDraw()){
+ endGame(true)
+ }
+ else{
+ //switch turns
+ swapTurns()
+
+ //add hover
+ setBoardHoverClass()
+ }
+
+}
+
+function placeMark(cell,currentClass){
+ cell.classList.add(currentClass)
+}
+
+function setBoardHoverClass(){
+ board.classList.remove(x_class)
+ board.classList.remove(o_class)
+ if(circleTurn){
+ board.classList.add(o_class)
+ }
+ else{
+ board.classList.add(x_class)
+ }
+
+}
+
+function swapTurns(){
+ circleTurn = !circleTurn
+}
+
+function checkWin(currentClass){
+ return winning_Combinations.some(combination => {
+ return combination.every(index =>{
+ return cellElements[index].classList.contains(currentClass)
+ })
+ })
+}
+
+function endGame(draw){
+ if(draw){
+ winningMessageText.innerText = `Draw!!`
+ }
+ else{
+ winningMessageText.innerText = `${circleTurn? "O" : "X"} wins!`
+ }
+ winningMessage.classList.add('show')
+}
+
+function isDraw(){
+ return [...cellElements].every(cell =>{
+ return cell.classList.contains(x_class) || cell.classList.contains(o_class)
+ })
+}
\ No newline at end of file
diff --git a/Frontend Projects/Tic-Tac-Toe/style.css b/Frontend Projects/Tic-Tac-Toe/style.css
new file mode 100644
index 0000000..4e74c82
--- /dev/null
+++ b/Frontend Projects/Tic-Tac-Toe/style.css
@@ -0,0 +1,153 @@
+*, *::after, *::before{
+ box-sizing: border-box;
+}
+
+:root{
+ --cell-size: 100px;
+ --mark-size: calc(var(--cell-size)*.9);
+}
+
+body{
+ margin: 0;
+}
+
+.board{
+ width: 100vw;
+ height: 100vh;
+ display: grid;
+ justify-content: center;
+ align-content: center;
+ justify-items: center;
+ align-items: center;
+ grid-template-columns: repeat(3, auto);
+}
+
+.cell{
+ width: var(--cell-size);
+ height: var(--cell-size);
+ background-color: white;
+ border: 1px solid black ;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+}
+
+.cell.x,
+.cell.o {
+ cursor:not-allowed;
+}
+
+.cell:first-child,
+.cell:nth-child(2),
+.cell:nth-child(3) {
+ border-top: none;
+}
+
+.cell:nth-child(3n + 1) {
+ border-left: none;
+}
+
+.cell:nth-child(3n) {
+ border-right: none;
+}
+
+.cell:nth-child(7),
+.cell:nth-child(8),
+.cell:nth-child(9) {
+ border-bottom: none;
+}
+
+.cell.x::after,
+.cell.x::before {
+ background-color: black;
+}
+
+.cell.o::before {
+ background-color: black;
+}
+
+.board.x .cell:not(.x):not(.o):hover::after,
+.board.x .cell:not(.x):not(.o):hover::before,
+.board.o .cell:not(.x):not(.o):hover::before {
+ background-color: rgb(188, 188, 188) ;
+}
+
+.cell.x::after,
+.cell.x::before,
+.board.x .cell:not(.x):not(.o):hover::before,
+.board.x .cell:not(.x):not(.o):hover::after {
+ content: '';
+ width: calc(var(--mark-size)*.15);
+ height: var(--mark-size);
+ position: absolute;
+}
+
+.cell.x::after,
+.board.x .cell:not(.x):not(.o):hover::after {
+ transform: rotate(45deg);
+}
+
+.cell.x::before,
+.board.x .cell:not(.x):not(.o):hover::before {
+ transform: rotate(-45deg);
+}
+
+
+.cell.o::after,
+.cell.o::before,
+.board.o .cell:not(.x):not(.o):hover::after,
+.board.o .cell:not(.x):not(.o):hover::before {
+ content: '';
+ width: var(--mark-size);
+ height: var(--mark-size);
+ position: absolute;
+ border-radius: 50%;
+}
+
+.cell.o::before,
+.board.o .cell:not(.x):not(.o):hover::before {
+ width: var(--mark-size);
+ height: var(--mark-size);
+}
+
+.cell.o::after,
+.board.o .cell:not(.x):not(.o):hover::after {
+ width: calc(var(--mark-size)*.7);
+ height: calc(var(--mark-size)*.7);
+ background-color: white;
+}
+
+.winning {
+ display: none;
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ background-color: rgba(0,0,0,.9);
+ justify-content: center;
+ align-items: center;color: aliceblue;
+ font-size: 4rem;
+ flex-direction: column;
+}
+
+
+.winning button{
+ font-size: 2rem;
+ background-color: white;
+ border: 2px solid black;
+ padding: .25em .5em ;
+ cursor: pointer;
+ border-radius: 5%;
+}
+
+.winning button:hover {
+ background-color: aliceblue;
+ border-color: aliceblue;
+ color:rgb(31, 148, 161);
+}
+
+.winning.show {
+ display: flex;
+}