From fa9ac9ad54271e641a12e0d78e57474b50ef966b Mon Sep 17 00:00:00 2001 From: Frankie Date: Mon, 29 Nov 2021 18:30:51 +0800 Subject: [PATCH 1/9] created modal for game details selection --- index.html | 33 +++++++++++++++-- script.js | 46 ++++++++++++++++++++++++ styles.css | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 180 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 25a06fd..ee611f8 100644 --- a/index.html +++ b/index.html @@ -6,8 +6,37 @@ -

SWE101! 🚀

- +

🃏 Match Game 🃏

+ diff --git a/script.js b/script.js index e2d0297..a8df1cc 100644 --- a/script.js +++ b/script.js @@ -1 +1,47 @@ // Please implement exercise logic here + +// ### DOM SELECTORS ### +const modal = document.querySelector(".modal"); +const modalContainer = document.querySelector(".modal-container"); +const content = document.querySelector(".content"); +const formPlayerName = document.querySelector("#form-player-name"); +const formGridSize = document.querySelector("#form-grid-size"); +const formTimeSelection = document.querySelector( + "#form-time-selection" +); +const formSubmitBtn = document.querySelector(".form-submit"); + +// ### GLOBAL VARIABLES ### +let deck +let playerName +let gridSize +let timer +let board = [] +let winCounter = 0 +let numOfGames = 0 + +// DOM ELEMENTS + + +// ### INITIALISE GAME PROPER ### +const initGame = () => { + if (formPlayerName.value.length < 1) { + alert('Please input your name') + } + else { + // Assignment of variables + playerName = formPlayerName.value + gridSize = formGridSize.value + timer = formTimeSelection.value + + // Hide modal + modal.classList.add("hide"); + modalContainer.classList.add("hide"); + + //other functionalities + alert(playerName) + } +} + +// ### EVENT LISTENERS ### +formSubmitBtn.addEventListener("click", initGame); diff --git a/styles.css b/styles.css index 04e7110..bfca64b 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,105 @@ +@import url("https://fonts.googleapis.com/css2?family=Odibee+Sans&family=Poppins&display=swap"); body { - background-color: pink; + background-image: url("https://www.publicdomainpictures.net/pictures/20000/velka/background-of-playing-cards.jpg"); + background-size: cover; + background-position: bottom center; + background-repeat: no-repeat; + display: flex; + flex-direction: column; + box-sizing: border-box; + align-items: center; + height: 97.8vh; +} + +.hide { + height: 0; + display: none; +} + +.modal { + display: flex; + justify-content: center; + align-items: center; + font-size: 1.1rem; + transition: all 1s ease; +} +.modal .modal-container { + width: 500px; + padding: 15px 10px; + margin-top: 100px; + background-color: #a2a2a1; + background-image: url("https://media.istockphoto.com/photos/green-casino-background-picture-id842444492?k=20&m=842444492&s=170667a&w=0&h=D88I7VvqcL_SyCn_lPRUSJo5L-izvzQYaCJqpSzHZ_g="); + background-size: cover; + background-position: center center; + background-repeat: no-repeat; + border: 3px solid #b60014; +} +.modal .modal-container .modal-title { + font-size: 1.65rem; + text-align: center; + padding: 0 10px 20px 10px; + font-family: "Odibee Sans"; + color: #fcf6f5; + text-transform: uppercase; + text-align: center; + letter-spacing: 0.5rem; + vertical-align: text-bottom; +} +.modal .modal-container .form-container { + display: flex; + flex-direction: column; + padding: 0 5%; +} +.modal .modal-container .form-container .form-item { + width: 100%; + display: flex; + margin-right: -5px; + margin-bottom: 5px; +} +.modal .modal-container .form-container .form-item .label { + display: inline-block; + width: 50%; + vertical-align: bottom; + font-family: "Poppins"; + color: #f5f5f5; +} +.modal .modal-container .form-container .form-item #form-player-name, +.modal .modal-container .form-container .form-item #form-time-selection, +.modal .modal-container .form-container .form-item #form-grid-size { + font-size: 1.3rem; + width: 50%; + border: 2px solid black; + font-family: "Poppins"; + margin: 2px 0; + background-color: #a2a2a1; + border: 2px solid #b60014; +} +.modal .modal-container .form-container .form-submit { + font-size: 1rem; + margin-top: 20px; + margin-bottom: 5px; + padding: 12px; + align-self: center; + border-radius: 10px; + display: inline-block; + border-color: #7c7c7c; + + background-image: linear-gradient( + 180deg, + #c7c7c7 0%, + #e6e6e6 47%, + #c7c7c7 53%, + #b3b3b3 100% + ); +} +.modal .modal-container .form-container .form-submit:hover { + transform: scale(0.98); + color: #b60014; + text-shadow: rgba(211, 62, 79, 0.701) 0 -1px 0, #f0d1d1 0 2px 1px, + #99ddff 0 0 5px, rgba(0, 128, 255, 0.6) 0 0 20px; + box-shadow: inset #c72929 0 0px 0px 4px, + inset rgba(193, 10, 10, 0.816) 0 -1px 5px 4px, + inset rgba(23, 27, 28, 0.7) 0 -1px 0px 7px, + inset rgba(255, 255, 255, 0.7) 0 2px 1px 7px, + rgba(243, 30, 30, 0.8) 0 0px 3px 2px; } From 6cf3671a78c47aa3add2d33cc58e058bfe2bc5be Mon Sep 17 00:00:00 2001 From: Frankie Date: Mon, 29 Nov 2021 21:45:20 +0800 Subject: [PATCH 2/9] added reset functionalities --- index.html | 26 ++++++++++- script.js | 131 +++++++++++++++++++++++++++++++++++++++++++++-------- styles.css | 15 ++++-- 3 files changed, 149 insertions(+), 23 deletions(-) diff --git a/index.html b/index.html index ee611f8..383cfc7 100644 --- a/index.html +++ b/index.html @@ -10,11 +10,13 @@

🃏 Match Game 🃏

+ +
+
+
+
+
+
+
+ +
+
+
+ +
+
Find the Pairs
+
+ +
diff --git a/script.js b/script.js index a8df1cc..984164d 100644 --- a/script.js +++ b/script.js @@ -1,26 +1,113 @@ // Please implement exercise logic here - // ### DOM SELECTORS ### -const modal = document.querySelector(".modal"); -const modalContainer = document.querySelector(".modal-container"); -const content = document.querySelector(".content"); -const formPlayerName = document.querySelector("#form-player-name"); -const formGridSize = document.querySelector("#form-grid-size"); + +// from modal +const modal = document.querySelector(".modal") +const modalContainer = document.querySelector(".modal-container") +const content = document.querySelector(".content") +const formPlayerName = document.querySelector("#form-player-name") +const formGridSize = document.querySelector("#form-grid-size") const formTimeSelection = document.querySelector( "#form-time-selection" -); -const formSubmitBtn = document.querySelector(".form-submit"); +) +const formSubmitBtn = document.querySelector(".form-submit") + +// from main container +const container = document.getElementById("main-container") +const playerMessage = document.getElementById("game-title") +const playerWinMessage = document.getElementById("player-wins") +const playerWinRate = document.getElementById("player-win-rate") +const playerTimer = document.getElementById("player-timer") +const outputMessage = document.getElementById("output-message") +const resetBoard = document.getElementById("reset") +const resetGame = document.getElementById("total-reset") // ### GLOBAL VARIABLES ### -let deck let playerName let gridSize let timer +let firstCard = null +let firstCardElement = null +let deck =[] let board = [] +let canClick = true +let matchedPairs = 0 +let totalPairs = 0 let winCounter = 0 let numOfGames = 0 -// DOM ELEMENTS +// ### CARD FUNCTIONS ### +// Get a random index ranging from 0 (inclusive) to max (exclusive). +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +const generateCard = (cardRank, suit) => { + const symbols = ['♥', '♦', '♣', '♠']; + let cardName = ''; + switch (cardRank) { + case 1: + cardName = 'A'; + break; + case 11: + cardName = 'J'; + break; + case 12: + cardName = 'Q'; + break; + case 13: + cardName = 'K'; + break; + default: + cardName = cardRank; + } + + const card = { + suit: symbols[suit], + name: cardName, + colour: suit < 2 ? 'red' : 'black', + rank: cardRank, + }; + return card; +}; + +// generate the deck for gameplay +const makeDeck = () => { + const tempDeck = []; + for (let i = 1; i <= 13; i += 1){ + for (let j = 0; j < 4; j += 1){ + // generates cards and inserts randomly to get a 52-card deck + tempDeck.splice(getRandomIndex(tempDeck.length + 1), 0, generateCard(i, j)); + } + } + + // get random cards from the tempdeck and insert 2 of it randomly into deck + for (let k = 0; k < totalPairs; k += 1) { + const randCard = tempDeck.pop(); + deck.splice(getRandomIndex(deck.length + 1), 0, randCard); + deck.splice(getRandomIndex(deck.length + 1), 0, randCard); + } +}; + +// ### HELPER FUNCTIONS ### +//win rate calculator +const winRate = (numberOfWins,numberOfGames) => { + return (numberOfWins/numberOfGames)*100 +} + +//display output message +const printMessage = message => { + outputMessage.innerHTML = message +} + +//reset game +const resetGameFunction = () => { + if (confirm("Reset Game? Your data will be erased.")) { + window.location = window.location; + } else { + alert('Game reset fail.') + } +} + +//reset board // ### INITIALISE GAME PROPER ### @@ -33,15 +120,21 @@ const initGame = () => { playerName = formPlayerName.value gridSize = formGridSize.value timer = formTimeSelection.value - - // Hide modal - modal.classList.add("hide"); - modalContainer.classList.add("hide"); - - //other functionalities - alert(playerName) - } + + // Change texts based on inputs + playerMessage.textContent=`${playerName}'s Match Game!` + playerWinMessage.textContent =`Total Wins: ${winCounter}` + winCounter =1 + numOfGames = 1 + playerWinRate.textContent = `Win Rate: ${winRate(winCounter,numOfGames)}%` + playerTimer.textContent = `Timer: ${timer}:00` + // Hide modal & unhide container + modal.classList.add("hide") + modalContainer.classList.add("hide") + container.classList.remove("hide") +} } // ### EVENT LISTENERS ### -formSubmitBtn.addEventListener("click", initGame); +formSubmitBtn.addEventListener("click", initGame) +resetGame.addEventListener("click",resetGameFunction) diff --git a/styles.css b/styles.css index bfca64b..db3fd81 100644 --- a/styles.css +++ b/styles.css @@ -1,8 +1,8 @@ @import url("https://fonts.googleapis.com/css2?family=Odibee+Sans&family=Poppins&display=swap"); body { - background-image: url("https://www.publicdomainpictures.net/pictures/20000/velka/background-of-playing-cards.jpg"); + background-image: url("https://media.istockphoto.com/photos/green-felt-and-playing-chips-abstract-background-picture-id672556284?k=20&m=672556284&s=612x612&w=0&h=Eh62_3jBb3TdkEkWz8G4oonuEAdqPrneAbYjibj3lhk="); background-size: cover; - background-position: bottom center; + background-position: center center; background-repeat: no-repeat; display: flex; flex-direction: column; @@ -16,6 +16,11 @@ body { display: none; } +#header { + margin-top: 30px; + color: #f5f5f5; +} + .modal { display: flex; justify-content: center; @@ -26,7 +31,7 @@ body { .modal .modal-container { width: 500px; padding: 15px 10px; - margin-top: 100px; + margin-top: 80px; background-color: #a2a2a1; background-image: url("https://media.istockphoto.com/photos/green-casino-background-picture-id842444492?k=20&m=842444492&s=170667a&w=0&h=D88I7VvqcL_SyCn_lPRUSJo5L-izvzQYaCJqpSzHZ_g="); background-size: cover; @@ -103,3 +108,7 @@ body { inset rgba(255, 255, 255, 0.7) 0 2px 1px 7px, rgba(243, 30, 30, 0.8) 0 0px 3px 2px; } + +#game-title { + text-transform: capitalize; +} From ae11fdf8480a22d8544f1d4d2397ad79fa9d89bd Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 01:30:10 +0800 Subject: [PATCH 3/9] completed full match game --- index.html | 11 ++- script.js | 198 ++++++++++++++++++++++++++++++++++++++++++++++++----- styles.css | 92 ++++++++++++++++++++++++- 3 files changed, 275 insertions(+), 26 deletions(-) diff --git a/index.html b/index.html index 383cfc7..8d4f64e 100644 --- a/index.html +++ b/index.html @@ -18,12 +18,11 @@

🃏 Match Game 🃏

- - -
@@ -50,13 +49,13 @@

🃏 Match Game 🃏

-
+
-
Find the Pairs
+
Find the Pairs.
- +
diff --git a/script.js b/script.js index 984164d..1a56d63 100644 --- a/script.js +++ b/script.js @@ -1,12 +1,11 @@ // Please implement exercise logic here // ### DOM SELECTORS ### - // from modal const modal = document.querySelector(".modal") const modalContainer = document.querySelector(".modal-container") const content = document.querySelector(".content") const formPlayerName = document.querySelector("#form-player-name") -const formGridSize = document.querySelector("#form-grid-size") +const formBoardSize = document.querySelector("#form-board-size") const formTimeSelection = document.querySelector( "#form-time-selection" ) @@ -18,13 +17,14 @@ const playerMessage = document.getElementById("game-title") const playerWinMessage = document.getElementById("player-wins") const playerWinRate = document.getElementById("player-win-rate") const playerTimer = document.getElementById("player-timer") +const boardElement = document.getElementsByClassName("board-container")[0] const outputMessage = document.getElementById("output-message") const resetBoard = document.getElementById("reset") const resetGame = document.getElementById("total-reset") // ### GLOBAL VARIABLES ### let playerName -let gridSize +let boardSize let timer let firstCard = null let firstCardElement = null @@ -34,7 +34,7 @@ let canClick = true let matchedPairs = 0 let totalPairs = 0 let winCounter = 0 -let numOfGames = 0 +let numOfGames = -1 // ### CARD FUNCTIONS ### // Get a random index ranging from 0 (inclusive) to max (exclusive). @@ -90,7 +90,12 @@ const makeDeck = () => { // ### HELPER FUNCTIONS ### //win rate calculator const winRate = (numberOfWins,numberOfGames) => { - return (numberOfWins/numberOfGames)*100 + if (numberOfGames == 0) { + return 0 + } + else { + return ((numberOfWins/numberOfGames)*100).toFixed(2) + } } //display output message @@ -108,33 +113,192 @@ const resetGameFunction = () => { } //reset board +const resetBoardFunction = () => { + board = []; + firstCard = null; + firstCardElement = null; + deck = []; + canClick = true; + totalPairs = 0; + matchedPairs = 0; +} +// Create the appearance of a card by adding name and suit to the existing face-down cards +const createCardUI = (card, cardElement) => { + const suit = document.createElement('div'); + suit.classList.add('suit', card.colour); + suit.innerText = card.suit; -// ### INITIALISE GAME PROPER ### -const initGame = () => { - if (formPlayerName.value.length < 1) { - alert('Please input your name') + const name = document.createElement('div'); + name.classList.add('name', card.colour); + name.innerText = card.name; + + cardElement.appendChild(name); + cardElement.appendChild(suit); + cardElement.classList.add('face-up'); +}; + +const setUIEffects = (clickedCard, cardElement) => { + const match = clickedCard.name === firstCard.name && clickedCard.suit === firstCard.suit; + if (match) { + matchedPairs += 1; + let message = `It's a match!`; + cardElement.classList.add('match'); + firstCardElement.classList.add('match'); + if (matchedPairs === totalPairs) { + // This means user won, clear timer + winCounter +=1 + message += '
You win!!!'; + clearInterval(timer); + } + printMessage(message); + } else { + cardElement.classList.add('no-match'); + firstCardElement.classList.add('no-match'); + printMessage(`No match! Try again.`); } - else { + + setTimeout(() => { + // The effects set above last for 1 sec and will be removed here + cardElement.classList.remove('match'); + firstCardElement.classList.remove('match'); + cardElement.classList.remove('no-match'); + firstCardElement.classList.remove('no-match'); + + if (matchedPairs === totalPairs) { resetBoardFunction(); } + else if (!match) { + cardElement.innerHTML = ''; + firstCardElement.innerHTML = ''; + cardElement.classList.remove('face-up'); + firstCardElement.classList.remove('face-up'); + } + firstCard = null; + canClick = true; + printMessage(`Find the Pairs.`); + }, 1000); +}; + +const cardClick = (cardElement, row, column) => { + if (canClick) { + const clickedCard = board[row][column]; + // the user already clicked on this card + if (cardElement.innerHTML !== '') { + return; + } + // first turn + if (firstCard === null) { + firstCard = clickedCard; + // turn this card over + createCardUI(firstCard, cardElement); + // hold onto this for later when it may not match + firstCardElement = cardElement; + // second turn + } else { + // don't allow the user to click until the ui effects are done + canClick = false; + createCardUI(clickedCard, cardElement); + setUIEffects(clickedCard, cardElement); + } + } +}; + +// Create all the board elements that will go on the screen +const buildBoardElements = () => { + for (let i = 0; i < board.length; i += 1) { + // make a container for a row of cards + const rowElement = document.createElement('div'); + rowElement.classList.add('row'); + + // make all the cards for this row + for (let j = 0; j < board[i].length; j += 1) { + // create the card element + const card = document.createElement('div'); + card.classList.add('card', 'face-down'); + + card.addEventListener('click', (event) => { + cardClick(event.currentTarget, i, j); + }); + rowElement.appendChild(card); + } + boardElement.appendChild(rowElement); + } +}; + +const initBoard = () => { + numOfGames += 1 // Assignment of variables playerName = formPlayerName.value - gridSize = formGridSize.value - timer = formTimeSelection.value + boardSize = formBoardSize.value // Change texts based on inputs playerMessage.textContent=`${playerName}'s Match Game!` playerWinMessage.textContent =`Total Wins: ${winCounter}` - winCounter =1 - numOfGames = 1 playerWinRate.textContent = `Win Rate: ${winRate(winCounter,numOfGames)}%` - playerTimer.textContent = `Timer: ${timer}:00` - // Hide modal & unhide container + + boardElement.innerHTML ="" + boardSize = formBoardSize.value + totalPairs = (boardSize * boardSize) / 2; + makeDeck(); + + // deal the cards out to the board data structure + for (let i = 0; i < boardSize; i += 1) { + board.push([]); + for (let j = 0; j < boardSize; j += 1) { + board[i].push(deck.pop()); + } + } + buildBoardElements(board); +}; + +const initTimer = () => { + const minutes = formTimeSelection.value ; + let seconds = minutes * 60; + playerTimer.innerText = `${minutes}:00`; + timer = setInterval(() => { + seconds -= 1; + const secondsLeft = seconds % 60; + const minutesLeft = Math.floor(seconds / 60); + + if (secondsLeft >= 10) { + playerTimer.innerText = `${minutesLeft}:${secondsLeft}`; + } else { + playerTimer.innerText = `${minutesLeft}:0${secondsLeft}`; + } + + if (seconds <= 0) { + clearInterval(timer); + canClick = false; + printMessage("Time's up! You lose."); + setTimeout(resetBoardFunction, 1000); + } + }, 1000); +}; + + +// ### INITIALISE GAME PROPER ### +const initGame = () => { + if (formPlayerName.value.length < 1 || formPlayerName.value == " ") { + alert('Please input your name') + } + else { + + // Hide modal & unhide container modal.classList.add("hide") modalContainer.classList.add("hide") container.classList.remove("hide") -} + + //Initialise Board and Timer + initBoard() + initTimer() + } } // ### EVENT LISTENERS ### formSubmitBtn.addEventListener("click", initGame) resetGame.addEventListener("click",resetGameFunction) +resetBoard.addEventListener("click",() => { + clearInterval(timer) + resetBoardFunction() + initTimer() + initBoard() +}) diff --git a/styles.css b/styles.css index db3fd81..0d7b155 100644 --- a/styles.css +++ b/styles.css @@ -1,6 +1,6 @@ @import url("https://fonts.googleapis.com/css2?family=Odibee+Sans&family=Poppins&display=swap"); body { - background-image: url("https://media.istockphoto.com/photos/green-felt-and-playing-chips-abstract-background-picture-id672556284?k=20&m=672556284&s=612x612&w=0&h=Eh62_3jBb3TdkEkWz8G4oonuEAdqPrneAbYjibj3lhk="); + background-image: url("https://i.pinimg.com/564x/9a/b9/d2/9ab9d210c745e2a3d588a29c10fa440f.jpg"); background-size: cover; background-position: center center; background-repeat: no-repeat; @@ -9,6 +9,7 @@ body { box-sizing: border-box; align-items: center; height: 97.8vh; + font-family: "Poppins"; } .hide { @@ -17,7 +18,7 @@ body { } #header { - margin-top: 30px; + margin-top: -4px; color: #f5f5f5; } @@ -70,7 +71,7 @@ body { } .modal .modal-container .form-container .form-item #form-player-name, .modal .modal-container .form-container .form-item #form-time-selection, -.modal .modal-container .form-container .form-item #form-grid-size { +.modal .modal-container .form-container .form-item #form-board-size { font-size: 1.3rem; width: 50%; border: 2px solid black; @@ -112,3 +113,88 @@ body { #game-title { text-transform: capitalize; } + +.center-middle { + color: mintcream; + display: flex; + align-items: center; + justify-content: center; + margin: 30px; +} + +.content-top, +.content-bottom { + color: mintcream; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.card { + margin: 5px; + padding: 5px; + width: 25px; + height: 35px; + text-align: center; + border: solid 2px; + border-radius: 8px; + display: inline-block; + vertical-align: top; +} + +.face-down { + background: repeating-linear-gradient( + 45deg, + LightGoldenRodYellow 0px, + LightGoldenRodYellow 15px, + black 17px, + red 20px + ); +} + +.face-up { + background: white; +} + +.suit { + margin: 3px; + font-size: 14px; +} + +.name { + font-size: 16px; + font-weight: bold; + font-family: sans-serif; +} + +.red { + color: red; +} + +.black { + color: black; +} + +#timer { + background-color: aliceblue; + width: 60px; + border: solid 2px black; + border-radius: 20%; + font-weight: bold; + font-family: monospace; + font-size: 16px; + margin-top: 10px; +} + +#board { + margin-top: 10px; +} + +.match { + border: solid 2px cornsilk; +} + +.no-match { + border: solid 2px red; +} From c56b867d80fcc6ed6137a4a7f02f9019dfec8dc2 Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 01:44:37 +0800 Subject: [PATCH 4/9] fixed ui --- script.js | 7 ++++++- styles.css | 19 ++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/script.js b/script.js index 1a56d63..fd387c6 100644 --- a/script.js +++ b/script.js @@ -122,7 +122,12 @@ const resetBoardFunction = () => { totalPairs = 0; matchedPairs = 0; } - +// Check win +const checkWin = () => { + if (matchedPairs == totalPairs) { + printMessage('You win!!!
Hit Reset Board to play again.') + } +} // Create the appearance of a card by adding name and suit to the existing face-down cards const createCardUI = (card, cardElement) => { const suit = document.createElement('div'); diff --git a/styles.css b/styles.css index 0d7b155..2b21956 100644 --- a/styles.css +++ b/styles.css @@ -145,11 +145,11 @@ body { .face-down { background: repeating-linear-gradient( - 45deg, + 135deg, LightGoldenRodYellow 0px, LightGoldenRodYellow 15px, - black 17px, - red 20px + black 30px, + red 60px ); } @@ -176,23 +176,12 @@ body { color: black; } -#timer { - background-color: aliceblue; - width: 60px; - border: solid 2px black; - border-radius: 20%; - font-weight: bold; - font-family: monospace; - font-size: 16px; - margin-top: 10px; -} - #board { margin-top: 10px; } .match { - border: solid 2px cornsilk; + border: solid 2px gold; } .no-match { From db90f3b08e3e405a260d335f44546818fe248559 Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 11:22:45 +0800 Subject: [PATCH 5/9] removed check win function --- script.js | 159 ++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/script.js b/script.js index fd387c6..b2cfd18 100644 --- a/script.js +++ b/script.js @@ -38,24 +38,24 @@ let numOfGames = -1 // ### CARD FUNCTIONS ### // Get a random index ranging from 0 (inclusive) to max (exclusive). -const getRandomIndex = (max) => Math.floor(Math.random() * max); +const getRandomIndex = (max) => Math.floor(Math.random() * max) const generateCard = (cardRank, suit) => { - const symbols = ['♥', '♦', '♣', '♠']; - let cardName = ''; + const symbols = ['♥', '♦', '♣', '♠'] + let cardName = '' switch (cardRank) { case 1: - cardName = 'A'; - break; + cardName = 'A' + break case 11: - cardName = 'J'; - break; + cardName = 'J' + break case 12: - cardName = 'Q'; - break; + cardName = 'Q' + break case 13: - cardName = 'K'; - break; + cardName = 'K' + break default: cardName = cardRank; } @@ -106,7 +106,7 @@ const printMessage = message => { //reset game const resetGameFunction = () => { if (confirm("Reset Game? Your data will be erased.")) { - window.location = window.location; + window.location = window.location } else { alert('Game reset fail.') } @@ -114,72 +114,68 @@ const resetGameFunction = () => { //reset board const resetBoardFunction = () => { - board = []; - firstCard = null; - firstCardElement = null; - deck = []; - canClick = true; - totalPairs = 0; - matchedPairs = 0; -} -// Check win -const checkWin = () => { - if (matchedPairs == totalPairs) { - printMessage('You win!!!
Hit Reset Board to play again.') - } + board = [] + firstCard = null + firstCardElement = null + deck = [] + canClick = true + totalPairs = 0 + matchedPairs = 0 } // Create the appearance of a card by adding name and suit to the existing face-down cards const createCardUI = (card, cardElement) => { - const suit = document.createElement('div'); - suit.classList.add('suit', card.colour); - suit.innerText = card.suit; + const suit = document.createElement('div') + suit.classList.add('suit', card.colour) + suit.innerText = card.suit - const name = document.createElement('div'); - name.classList.add('name', card.colour); - name.innerText = card.name; + const name = document.createElement('div') + name.classList.add('name', card.colour) + name.innerText = card.name - cardElement.appendChild(name); - cardElement.appendChild(suit); - cardElement.classList.add('face-up'); + cardElement.appendChild(name) + cardElement.appendChild(suit) + cardElement.classList.add('face-up') }; const setUIEffects = (clickedCard, cardElement) => { const match = clickedCard.name === firstCard.name && clickedCard.suit === firstCard.suit; if (match) { matchedPairs += 1; - let message = `It's a match!`; - cardElement.classList.add('match'); - firstCardElement.classList.add('match'); + let message = `It's a match!` + cardElement.classList.add('match') + firstCardElement.classList.add('match') if (matchedPairs === totalPairs) { // This means user won, clear timer winCounter +=1 - message += '
You win!!!'; - clearInterval(timer); + message += '
You win!!!' + clearInterval(timer) } - printMessage(message); + printMessage(message) } else { - cardElement.classList.add('no-match'); - firstCardElement.classList.add('no-match'); - printMessage(`No match! Try again.`); + cardElement.classList.add('no-match') + firstCardElement.classList.add('no-match') + printMessage(`No match! Try again.`) } setTimeout(() => { // The effects set above last for 1 sec and will be removed here - cardElement.classList.remove('match'); - firstCardElement.classList.remove('match'); - cardElement.classList.remove('no-match'); - firstCardElement.classList.remove('no-match'); + cardElement.classList.remove('match') + firstCardElement.classList.remove('match') + cardElement.classList.remove('no-match') + firstCardElement.classList.remove('no-match') - if (matchedPairs === totalPairs) { resetBoardFunction(); } + if (matchedPairs === totalPairs) { + resetBoardFunction() + } else if (!match) { - cardElement.innerHTML = ''; - firstCardElement.innerHTML = ''; - cardElement.classList.remove('face-up'); - firstCardElement.classList.remove('face-up'); + cardElement.innerHTML = '' + firstCardElement.innerHTML = '' + cardElement.classList.remove('face-up') + firstCardElement.classList.remove('face-up') } - firstCard = null; - canClick = true; - printMessage(`Find the Pairs.`); + firstCard = null + canClick = true + printMessage(`Find the Pairs.`) }, 1000); }; @@ -188,21 +184,21 @@ const cardClick = (cardElement, row, column) => { const clickedCard = board[row][column]; // the user already clicked on this card if (cardElement.innerHTML !== '') { - return; + return } // first turn if (firstCard === null) { - firstCard = clickedCard; + firstCard = clickedCard // turn this card over - createCardUI(firstCard, cardElement); + createCardUI(firstCard, cardElement) // hold onto this for later when it may not match - firstCardElement = cardElement; + firstCardElement = cardElement // second turn } else { // don't allow the user to click until the ui effects are done canClick = false; - createCardUI(clickedCard, cardElement); - setUIEffects(clickedCard, cardElement); + createCardUI(clickedCard, cardElement) + setUIEffects(clickedCard, cardElement) } } }; @@ -211,21 +207,21 @@ const cardClick = (cardElement, row, column) => { const buildBoardElements = () => { for (let i = 0; i < board.length; i += 1) { // make a container for a row of cards - const rowElement = document.createElement('div'); - rowElement.classList.add('row'); + const rowElement = document.createElement('div') + rowElement.classList.add('row') // make all the cards for this row for (let j = 0; j < board[i].length; j += 1) { // create the card element - const card = document.createElement('div'); - card.classList.add('card', 'face-down'); + const card = document.createElement('div') + card.classList.add('card', 'face-down') card.addEventListener('click', (event) => { - cardClick(event.currentTarget, i, j); + cardClick(event.currentTarget, i, j) }); - rowElement.appendChild(card); + rowElement.appendChild(card) } - boardElement.appendChild(rowElement); + boardElement.appendChild(rowElement) } }; @@ -256,27 +252,27 @@ const initBoard = () => { }; const initTimer = () => { - const minutes = formTimeSelection.value ; - let seconds = minutes * 60; - playerTimer.innerText = `${minutes}:00`; + const minutes = formTimeSelection.value + let seconds = minutes * 60 + playerTimer.innerText = `${minutes}:00` timer = setInterval(() => { - seconds -= 1; - const secondsLeft = seconds % 60; - const minutesLeft = Math.floor(seconds / 60); + seconds -= 1 + const secondsLeft = seconds % 60 + const minutesLeft = Math.floor(seconds / 60) if (secondsLeft >= 10) { - playerTimer.innerText = `${minutesLeft}:${secondsLeft}`; + playerTimer.innerText = `${minutesLeft}:${secondsLeft}` } else { - playerTimer.innerText = `${minutesLeft}:0${secondsLeft}`; + playerTimer.innerText = `${minutesLeft}:0${secondsLeft}` } if (seconds <= 0) { - clearInterval(timer); - canClick = false; - printMessage("Time's up! You lose."); - setTimeout(resetBoardFunction, 1000); + clearInterval(timer) + canClick = false + printMessage("Time's up! You lose.") + setTimeout(resetBoardFunction, 1000) } - }, 1000); + }, 1000) }; @@ -286,7 +282,6 @@ const initGame = () => { alert('Please input your name') } else { - // Hide modal & unhide container modal.classList.add("hide") modalContainer.classList.add("hide") From 8a0bb0d3ff9636031ef218c189096bef42f7f223 Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 11:33:53 +0800 Subject: [PATCH 6/9] fixed visuals --- styles.css | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/styles.css b/styles.css index 2b21956..e1a23fb 100644 --- a/styles.css +++ b/styles.css @@ -23,11 +23,11 @@ body { } .modal { + margin-top: 80px; display: flex; justify-content: center; align-items: center; font-size: 1.1rem; - transition: all 1s ease; } .modal .modal-container { width: 500px; @@ -109,7 +109,10 @@ body { inset rgba(255, 255, 255, 0.7) 0 2px 1px 7px, rgba(243, 30, 30, 0.8) 0 0px 3px 2px; } - +.container { + margin-top: 10px; + font-size: 18px; +} #game-title { text-transform: capitalize; } @@ -187,3 +190,13 @@ body { .no-match { border: solid 2px red; } + +button { + font-family: "Poppins"; + border-radius: 10px; +} +button:hover { + transform: scale(0.98); + background-color: red; + color: whitesmoke; +} From 25d723fc820b36c4ee930b4765f5108fd9886769 Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 11:40:00 +0800 Subject: [PATCH 7/9] fxed typo error --- index.html | 2 +- script.js | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 8d4f64e..39ee51e 100644 --- a/index.html +++ b/index.html @@ -31,7 +31,7 @@

🃏 Match Game 🃏

diff --git a/script.js b/script.js index b2cfd18..ffa4988 100644 --- a/script.js +++ b/script.js @@ -67,7 +67,7 @@ const generateCard = (cardRank, suit) => { rank: cardRank, }; return card; -}; +} // generate the deck for gameplay const makeDeck = () => { @@ -85,7 +85,7 @@ const makeDeck = () => { deck.splice(getRandomIndex(deck.length + 1), 0, randCard); deck.splice(getRandomIndex(deck.length + 1), 0, randCard); } -}; +} // ### HELPER FUNCTIONS ### //win rate calculator @@ -135,7 +135,7 @@ const createCardUI = (card, cardElement) => { cardElement.appendChild(name) cardElement.appendChild(suit) cardElement.classList.add('face-up') -}; +} const setUIEffects = (clickedCard, cardElement) => { const match = clickedCard.name === firstCard.name && clickedCard.suit === firstCard.suit; @@ -176,8 +176,8 @@ const setUIEffects = (clickedCard, cardElement) => { firstCard = null canClick = true printMessage(`Find the Pairs.`) - }, 1000); -}; + }, 1000) +} const cardClick = (cardElement, row, column) => { if (canClick) { @@ -201,7 +201,7 @@ const cardClick = (cardElement, row, column) => { setUIEffects(clickedCard, cardElement) } } -}; +} // Create all the board elements that will go on the screen const buildBoardElements = () => { @@ -223,7 +223,7 @@ const buildBoardElements = () => { } boardElement.appendChild(rowElement) } -}; +} const initBoard = () => { numOfGames += 1 @@ -249,7 +249,7 @@ const initBoard = () => { } } buildBoardElements(board); -}; +} const initTimer = () => { const minutes = formTimeSelection.value @@ -273,8 +273,7 @@ const initTimer = () => { setTimeout(resetBoardFunction, 1000) } }, 1000) -}; - +} // ### INITIALISE GAME PROPER ### const initGame = () => { From 9a477fe1e50b7b07447921c9f3c2687bf662574b Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 21:06:19 +0800 Subject: [PATCH 8/9] Fixed UI from Bernice's suggestions --- .vscode/settings.json | 3 ++- index.html | 3 +++ styles.css | 14 +++++++++----- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 202a1c1..40bef48 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,6 @@ "editor.wordWrap": "on", "eslint.format.enable": true, "eslint.lintTask.enable": true, - "eslint.migration.2_x": "off" + "eslint.migration.2_x": "off", + "editor.fontFamily": "Segoe UI Emoji" } diff --git a/index.html b/index.html index 39ee51e..5ade691 100644 --- a/index.html +++ b/index.html @@ -2,6 +2,9 @@ SWE101 + + + diff --git a/styles.css b/styles.css index e1a23fb..20577e2 100644 --- a/styles.css +++ b/styles.css @@ -110,8 +110,8 @@ body { rgba(243, 30, 30, 0.8) 0 0px 3px 2px; } .container { - margin-top: 10px; font-size: 18px; + margin-top: -80px; } #game-title { text-transform: capitalize; @@ -122,7 +122,7 @@ body { display: flex; align-items: center; justify-content: center; - margin: 30px; + margin: 10px; } .content-top, @@ -135,10 +135,10 @@ body { } .card { - margin: 5px; + margin: 5px 10px; padding: 5px; - width: 25px; - height: 35px; + width: 35px; + height: 50px; text-align: center; border: solid 2px; border-radius: 8px; @@ -173,10 +173,14 @@ body { .red { color: red; + font-size: 24px; + margin: -2px; } .black { color: black; + font-size: 24px; + margin: 0; } #board { From a45d85ce5431ff45cab2365f8947525fb406871c Mon Sep 17 00:00:00 2001 From: Frankie Date: Tue, 30 Nov 2021 22:08:51 +0800 Subject: [PATCH 9/9] fixed emoji issue for chrome --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 5ade691..f4819e4 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ -

🃏 Match Game 🃏

+

🎴🃏 Match Game 🃏🎴