From 4ae20e85b2678f04012d0d34f5fda3c64be17b31 Mon Sep 17 00:00:00 2001 From: shannonssd Date: Mon, 11 Oct 2021 16:30:44 +0800 Subject: [PATCH 1/2] Base - Countdown Timer --- index.html | 1 + script.js | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++- styles.css | 35 +++++++ 3 files changed, 337 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 4771b50..e2afb9f 100644 --- a/index.html +++ b/index.html @@ -2,6 +2,7 @@ Timer + diff --git a/script.js b/script.js index e2d0297..69e7a91 100644 --- a/script.js +++ b/script.js @@ -1 +1,301 @@ -// Please implement exercise logic here +// Global variables +const boardSize = 4; +const board = []; +let firstCard = null; +let firstCardElement; +let shuffledDeck; +let secondCardElement; +let userName = ''; +let seconds = 0; +const winCount = 0; + +// Gameplay Logic +const squareClick = (cardElement, row, column) => { + const clickedCard = board[row][column]; + // the user already clicked on this square + if (cardElement.innerHTML !== '') { + // Inform player to select a diff card + output(` ${userName}!
You have already selected this card.
Please select another one!`); + return; + } + // first turn + if (firstCard === null) { + firstCard = clickedCard; + // turn this card over + cardElement.innerHTML = `${firstCard.displayName} ${firstCard.suitSymbol} `; + // Inform player of selected card + output(` ${userName}!
You selected a ${firstCard.name} of ${firstCard.suitSymbol}
Try to find the same number!`); + // hold onto this for later when it may not match + firstCardElement = cardElement; + // second turn + } else { + if ( + clickedCard.name === firstCard.name + && clickedCard.suit === firstCard.suit + ) { + // turn this card over + cardElement.innerHTML = `${clickedCard.displayName} ${clickedCard.suitSymbol} `; + output(` ${userName}!
WOOOOO!
You found a match!`); + // Show match message for 3 sec + matchInfo.innerHTML = 'MATCH!!!!!!!!!'; + document.body.appendChild(matchInfo); + // Timeout to empty out element content + setTimeout(() => { + matchInfo.innerHTML = ''; + }, 3000); + } else { + // turn this card back over + firstCardElement.innerHTML = ''; + output(` ${userName}!
Darn! It wasn\'t a match...
Try again!`); + // Show wrong card for 3 sec + secondCardElement = cardElement; + secondCardElement.innerHTML = `${clickedCard.displayName} ${clickedCard.suitSymbol} `; + setTimeout(() => { + secondCardElement.innerHTML = ''; + }, 1000); + } + + // reset the first card + firstCard = null; + } + checkWin(); +}; + +// Create all the board elements that will go on the screen +// return the built board +const buildBoardElements = (board) => { + // create the element that everything will go inside of + const boardElement = document.createElement('div'); + // give it a class for CSS purposes + boardElement.classList.add('board'); + // use the board data structure we passed in to create the correct size board + for (let i = 0; i < board.length; i += 1) { + // make a var for just this row of cards + const row = board[i]; + // make an element for this row of cards + const rowElement = document.createElement('div'); + rowElement.classList.add('row'); + // make all the squares for this row + for (let j = 0; j < row.length; j += 1) { + // create the square element + const square = document.createElement('div'); + // set a class for CSS purposes + square.classList.add('square'); + // set the click event + // eslint-disable-next-line + square.addEventListener('click', (event) => { + // we will want to pass in the card element so + // that we can change how it looks on screen, i.e., + // "turn the card over" + squareClick(event.currentTarget, i, j); + }); + rowElement.appendChild(square); + } + boardElement.appendChild(rowElement); + } + return boardElement; +}; + +// Create double decks +const makeDeck = () => { + const newDeck = []; + const suits = ['hearts', 'diamonds', 'clubs', 'spades']; + const suitEmoji = ['❤️', '♦️', '♣️', '♠️']; + // const suitEmoji = ['❤️H', 'D', 'C', 'S']; + // Loop over the suits array + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // Store the current suit & suit emoji in a variable + const currentSuit = suits[suitIndex]; + const currentEmoji = suitEmoji[suitIndex]; + // Loop from 1 to 13 to create all cards for a given suit + for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { + let shortName = `${rankCounter}`; + + if (shortName === '1') { + shortName = 'A'; + } else if (shortName === '11') { + shortName = 'J'; + } else if (shortName === '12') { + shortName = 'Q'; + } else if (shortName === '13') { + shortName = 'K'; + } + + let cardName = `${rankCounter}`; + if (cardName === '1') { + cardName = 'ace'; + } else if (cardName === '11') { + cardName = 'jack'; + } else if (cardName === '12') { + cardName = 'queen'; + } else if (cardName === '13') { + cardName = 'king'; + } + let emojiColour = ''; + + if (currentSuit === 'hearts') { + emojiColour = 'red'; + } else if (currentSuit === 'diamonds') { + emojiColour = 'red'; + } else if (currentSuit === 'spades') { + emojiColour = 'black'; + } else if (currentSuit === 'clubs') { + emojiColour = 'black'; + } + // Create a new card with the current name, suit, and rank, colour, displayName and emoji + const card = { + name: cardName, + suit: currentSuit, + rank: rankCounter, + suitSymbol: currentEmoji, + displayName: shortName, + colour: emojiColour, + }; + // add double the cards to the deck + newDeck.push(card); + newDeck.push(card); + } + } + return newDeck; +}; + +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +const shuffleCards = (deckSubset) => { + for (let currentIndex = 0; currentIndex < deckSubset.length; currentIndex += 1) { + const randomIndex = getRandomIndex(deckSubset.length); + const randomCard = deckSubset[randomIndex]; + const currentCard = deckSubset[currentIndex]; + deckSubset[currentIndex] = randomCard; + deckSubset[randomIndex] = currentCard; + } + return deckSubset; +}; + +// Create line break between game board and game info +const brk = document.createElement('br'); + +// Create element for game info +const gameInfo = document.createElement('div'); +// Add class to make visual changes in CSS +gameInfo.classList.add('gameInfo'); + +// Create element for 'MATCH!' pop up message +const matchInfo = document.createElement('div'); +// Add class to make visual changes in CSS +matchInfo.classList.add('matchInfo'); + +// Create function to help change output message +const output = (message) => { + gameInfo.innerHTML = message; +}; + +// Create element for game timer +const gameTimer = document.createElement('div'); +// Add class to make visual changes in CSS +gameTimer.classList.add('gameTimer'); +seconds = 180; + +// Create input button to take user's name +const playerName = document.createElement('input'); +playerName.placeholder = 'Please enter your name'; +// Create submit button +const submit = document.createElement('button'); +submit.innerHTML = 'Submit'; + +// Create reset button +const reset = document.createElement('button'); +reset.innerText = 'Reset'; + +// Start timer and game after name is input +const startGame = () => { + userName = playerName.value; + playerName.value = ''; + playerName.placeholder = 'Enjoy the game!'; + gameInfo.innerHTML = ` Hello ${userName}! 😊
Try to pick two of the same cards in a row.
Pick all the cards correctly to win!`; +}; + +const checkWin = () => { + const checkSquares = document.querySelectorAll('.square'); + for (let m = 0; m < checkSquares.length; m += 1) { + if (checkSquares[m].innerText === '') { + break; + } else if (checkSquares[checkSquares.length - 1].innerText !== '') + { + gameInfo.innerText = 'Game Over!'; + resetGame(); + } + } +}; + +const initGame = () => { + // create this special deck by getting fthe doubled cards and + // making a smaller array that is ( boardSize squared ) number of cards + const doubleDeck = makeDeck(); + const deckSubset = doubleDeck.slice(0, boardSize * boardSize); + shuffledDeck = shuffleCards(deckSubset); + + // 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(shuffledDeck.pop()); + } + } + // Append all elements to body + const boardEl = buildBoardElements(board); + document.body.appendChild(playerName); + document.body.appendChild(submit); + document.body.appendChild(reset); + document.body.appendChild(boardEl); + document.body.appendChild(gameTimer); + document.body.appendChild(brk); + document.body.appendChild(gameInfo); + + // // Callback function to reset game + const resetGame = () => { + // Clear out array with cards + board.length = 0; + // Clear out shuffled deck + shuffledDeck.length = 0; + // Create new shuffled deck + const doubleDeck = makeDeck(); + const deckSubset = doubleDeck.slice(0, boardSize * boardSize); + shuffledDeck = shuffleCards(deckSubset); + + // Deal cards to array again + for (let i = 0; i < boardSize; i += 1) { + board.push([]); + for (let j = 0; j < boardSize; j += 1) { + board[i].push(shuffledDeck.pop()); + } + } + // Create element array which selects all squares + const allSquares = document.querySelectorAll('.square'); + // Clear out all square elements so that board appears empty + for (let k = 0; k < allSquares.length; k += 1) { + allSquares[k].innerHTML = ''; + } + + gameInfo.innerHTML = ` ${userName}! 😊
The game has been reset!
Enjoy the next round!`; + seconds = 180; + gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; + }; + // setInterval to stop timer after 180 secs + const countdown = setInterval(() => { + gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; + + if (seconds === 0) { + gameInfo.innerHTML = 'Sorry! You ran out of time. Please try again!'; + // seconds = 15; + resetGame(); + // seconds = 15; + // gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; + } + seconds -= 1; + }, 1000); + submit.addEventListener('click', () => startGame()); + reset.addEventListener('click', () => resetGame()); +}; + +initGame(); diff --git a/styles.css b/styles.css index 04e7110..e8408ce 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,38 @@ body { background-color: pink; } +.square { + padding: 10px; + margin: 10px; + background-color: white; + display: inline-block; + height: 40px; + width: 40px; + vertical-align: top; +} + +.matchInfo { + font-size: 50px; + font-family: "Lucida Console", monospace; +} + +.gameInfo { + font-size: 20px; + font-family: "Lucida Console", monospace; +} + +.gameTimer { + font-size: 18px; + font-family: "Lucida Console", monospace; +} + +timer { + font-size: 30px; + color: green; + font-family: "Source Sans Pro", sans-serif; + background-color: black; +} + +name { + font-size: 40px; +} From 1ef730486b056fc213447835e25ccd45b4d01ab6 Mon Sep 17 00:00:00 2001 From: shannonssd Date: Mon, 11 Oct 2021 16:59:03 +0800 Subject: [PATCH 2/2] Base - Timer --- script.js | 361 ++++++++++++------------------------------------------ 1 file changed, 77 insertions(+), 284 deletions(-) diff --git a/script.js b/script.js index 69e7a91..4d8d9ab 100644 --- a/script.js +++ b/script.js @@ -1,301 +1,94 @@ // Global variables -const boardSize = 4; -const board = []; -let firstCard = null; -let firstCardElement; -let shuffledDeck; -let secondCardElement; -let userName = ''; +let minutes = 0; +let hours = 0; +let clock; let seconds = 0; -const winCount = 0; +let displaySeconds; +let displayMinutes; +let isTimeRunning = true; + +// Create stopwatch display +const stopwatch = document.createElement('div'); + +// Create start button +const start = document.createElement('button'); +start.innerHTML = 'Start'; +document.body.appendChild(start); +start.addEventListener('click', () => startTimer()); + +// Create stop button +const stopButton = document.createElement('button'); +stopButton.innerHTML = 'Stop'; +document.body.appendChild(stopButton); +stopButton.addEventListener('click', () => stopTimer()); + +// Create lap button +const lapButton = document.createElement('button'); +lapButton.innerHTML = 'Lap'; +document.body.appendChild(lapButton); +lapButton.addEventListener('click', () => showLapTime(seconds)); -// Gameplay Logic -const squareClick = (cardElement, row, column) => { - const clickedCard = board[row][column]; - // the user already clicked on this square - if (cardElement.innerHTML !== '') { - // Inform player to select a diff card - output(` ${userName}!
You have already selected this card.
Please select another one!`); - return; - } - // first turn - if (firstCard === null) { - firstCard = clickedCard; - // turn this card over - cardElement.innerHTML = `${firstCard.displayName} ${firstCard.suitSymbol} `; - // Inform player of selected card - output(` ${userName}!
You selected a ${firstCard.name} of ${firstCard.suitSymbol}
Try to find the same number!`); - // hold onto this for later when it may not match - firstCardElement = cardElement; - // second turn - } else { - if ( - clickedCard.name === firstCard.name - && clickedCard.suit === firstCard.suit - ) { - // turn this card over - cardElement.innerHTML = `${clickedCard.displayName} ${clickedCard.suitSymbol} `; - output(` ${userName}!
WOOOOO!
You found a match!`); - // Show match message for 3 sec - matchInfo.innerHTML = 'MATCH!!!!!!!!!'; - document.body.appendChild(matchInfo); - // Timeout to empty out element content - setTimeout(() => { - matchInfo.innerHTML = ''; - }, 3000); - } else { - // turn this card back over - firstCardElement.innerHTML = ''; - output(` ${userName}!
Darn! It wasn\'t a match...
Try again!`); - // Show wrong card for 3 sec - secondCardElement = cardElement; - secondCardElement.innerHTML = `${clickedCard.displayName} ${clickedCard.suitSymbol} `; - setTimeout(() => { - secondCardElement.innerHTML = ''; - }, 1000); +// Create reset button +const resetButton = document.createElement('button'); +resetButton.innerHTML = 'Reset'; +document.body.appendChild(resetButton); +resetButton.addEventListener('click', () => resetTimer()); + +// Callback function for timer +const startTimer = () => { + isTimeRunning = true; + // Create counter + const timer = setInterval(() => { + stopwatch.innerHTML = `Timer: ${showAsClock(seconds)}`; + + if (isTimeRunning === false) { + clearInterval(timer); } - - // reset the first card - firstCard = null; - } - checkWin(); + seconds += 1; + }, 1000); + // Append timer to document + document.body.appendChild(stopwatch); }; -// Create all the board elements that will go on the screen -// return the built board -const buildBoardElements = (board) => { - // create the element that everything will go inside of - const boardElement = document.createElement('div'); - // give it a class for CSS purposes - boardElement.classList.add('board'); - // use the board data structure we passed in to create the correct size board - for (let i = 0; i < board.length; i += 1) { - // make a var for just this row of cards - const row = board[i]; - // make an element for this row of cards - const rowElement = document.createElement('div'); - rowElement.classList.add('row'); - // make all the squares for this row - for (let j = 0; j < row.length; j += 1) { - // create the square element - const square = document.createElement('div'); - // set a class for CSS purposes - square.classList.add('square'); - // set the click event - // eslint-disable-next-line - square.addEventListener('click', (event) => { - // we will want to pass in the card element so - // that we can change how it looks on screen, i.e., - // "turn the card over" - squareClick(event.currentTarget, i, j); - }); - rowElement.appendChild(square); - } - boardElement.appendChild(rowElement); - } - return boardElement; +// Ensure that displayed seconds resets after 59sec +const showSeconds = (seconds) => { + if (seconds > 59) { + displaySeconds = seconds - 60 * (Math.floor(seconds / 60)); + } else { displaySeconds = seconds; } + return displaySeconds; }; -// Create double decks -const makeDeck = () => { - const newDeck = []; - const suits = ['hearts', 'diamonds', 'clubs', 'spades']; - const suitEmoji = ['❤️', '♦️', '♣️', '♠️']; - // const suitEmoji = ['❤️H', 'D', 'C', 'S']; - // Loop over the suits array - for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { - // Store the current suit & suit emoji in a variable - const currentSuit = suits[suitIndex]; - const currentEmoji = suitEmoji[suitIndex]; - // Loop from 1 to 13 to create all cards for a given suit - for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { - let shortName = `${rankCounter}`; - - if (shortName === '1') { - shortName = 'A'; - } else if (shortName === '11') { - shortName = 'J'; - } else if (shortName === '12') { - shortName = 'Q'; - } else if (shortName === '13') { - shortName = 'K'; - } - - let cardName = `${rankCounter}`; - if (cardName === '1') { - cardName = 'ace'; - } else if (cardName === '11') { - cardName = 'jack'; - } else if (cardName === '12') { - cardName = 'queen'; - } else if (cardName === '13') { - cardName = 'king'; - } - let emojiColour = ''; - - if (currentSuit === 'hearts') { - emojiColour = 'red'; - } else if (currentSuit === 'diamonds') { - emojiColour = 'red'; - } else if (currentSuit === 'spades') { - emojiColour = 'black'; - } else if (currentSuit === 'clubs') { - emojiColour = 'black'; - } - // Create a new card with the current name, suit, and rank, colour, displayName and emoji - const card = { - name: cardName, - suit: currentSuit, - rank: rankCounter, - suitSymbol: currentEmoji, - displayName: shortName, - colour: emojiColour, - }; - // add double the cards to the deck - newDeck.push(card); - newDeck.push(card); - } - } - return newDeck; +// Ensure that displayed minutes resets after 59min +const showMinutes = (seconds) => { + minutes = Math.floor(seconds / 60); + if (minutes > 59) { + displayMinutes = minutes - 60 * (Math.floor(minutes / 60)); + } else { displayMinutes = minutes; } + return displayMinutes; }; -const getRandomIndex = (max) => Math.floor(Math.random() * max); - -const shuffleCards = (deckSubset) => { - for (let currentIndex = 0; currentIndex < deckSubset.length; currentIndex += 1) { - const randomIndex = getRandomIndex(deckSubset.length); - const randomCard = deckSubset[randomIndex]; - const currentCard = deckSubset[currentIndex]; - deckSubset[currentIndex] = randomCard; - deckSubset[randomIndex] = currentCard; - } - return deckSubset; +// Convert seconds to hr, min, sec +const showAsClock = (seconds) => { + hours = Math.floor(minutes / 60); + clock = `${hours}: ${showMinutes(seconds)}: ${showSeconds(seconds)} `; + return clock; }; -// Create line break between game board and game info -const brk = document.createElement('br'); - -// Create element for game info -const gameInfo = document.createElement('div'); -// Add class to make visual changes in CSS -gameInfo.classList.add('gameInfo'); - -// Create element for 'MATCH!' pop up message -const matchInfo = document.createElement('div'); -// Add class to make visual changes in CSS -matchInfo.classList.add('matchInfo'); - -// Create function to help change output message -const output = (message) => { - gameInfo.innerHTML = message; -}; - -// Create element for game timer -const gameTimer = document.createElement('div'); -// Add class to make visual changes in CSS -gameTimer.classList.add('gameTimer'); -seconds = 180; - -// Create input button to take user's name -const playerName = document.createElement('input'); -playerName.placeholder = 'Please enter your name'; -// Create submit button -const submit = document.createElement('button'); -submit.innerHTML = 'Submit'; - -// Create reset button -const reset = document.createElement('button'); -reset.innerText = 'Reset'; - -// Start timer and game after name is input -const startGame = () => { - userName = playerName.value; - playerName.value = ''; - playerName.placeholder = 'Enjoy the game!'; - gameInfo.innerHTML = ` Hello ${userName}! 😊
Try to pick two of the same cards in a row.
Pick all the cards correctly to win!`; +// Callback function for stop event +const stopTimer = () => { + // This will cause clearInterval() to be run at line 32 + isTimeRunning = false; }; -const checkWin = () => { - const checkSquares = document.querySelectorAll('.square'); - for (let m = 0; m < checkSquares.length; m += 1) { - if (checkSquares[m].innerText === '') { - break; - } else if (checkSquares[checkSquares.length - 1].innerText !== '') - { - gameInfo.innerText = 'Game Over!'; - resetGame(); - } - } +// Callback function for lap event +const showLapTime = (seconds) => { + const lap = document.createElement('div'); + document.body.appendChild(lap); + const lapTime = showAsClock(seconds); + lap.innerText = `${lapTime}`; }; -const initGame = () => { - // create this special deck by getting fthe doubled cards and - // making a smaller array that is ( boardSize squared ) number of cards - const doubleDeck = makeDeck(); - const deckSubset = doubleDeck.slice(0, boardSize * boardSize); - shuffledDeck = shuffleCards(deckSubset); - - // 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(shuffledDeck.pop()); - } - } - // Append all elements to body - const boardEl = buildBoardElements(board); - document.body.appendChild(playerName); - document.body.appendChild(submit); - document.body.appendChild(reset); - document.body.appendChild(boardEl); - document.body.appendChild(gameTimer); - document.body.appendChild(brk); - document.body.appendChild(gameInfo); - - // // Callback function to reset game - const resetGame = () => { - // Clear out array with cards - board.length = 0; - // Clear out shuffled deck - shuffledDeck.length = 0; - // Create new shuffled deck - const doubleDeck = makeDeck(); - const deckSubset = doubleDeck.slice(0, boardSize * boardSize); - shuffledDeck = shuffleCards(deckSubset); - - // Deal cards to array again - for (let i = 0; i < boardSize; i += 1) { - board.push([]); - for (let j = 0; j < boardSize; j += 1) { - board[i].push(shuffledDeck.pop()); - } - } - // Create element array which selects all squares - const allSquares = document.querySelectorAll('.square'); - // Clear out all square elements so that board appears empty - for (let k = 0; k < allSquares.length; k += 1) { - allSquares[k].innerHTML = ''; - } - - gameInfo.innerHTML = ` ${userName}! 😊
The game has been reset!
Enjoy the next round!`; - seconds = 180; - gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; - }; - // setInterval to stop timer after 180 secs - const countdown = setInterval(() => { - gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; - - if (seconds === 0) { - gameInfo.innerHTML = 'Sorry! You ran out of time. Please try again!'; - // seconds = 15; - resetGame(); - // seconds = 15; - // gameTimer.innerHTML = `Try to complete the board in 3 min!: ${seconds} `; - } - seconds -= 1; - }, 1000); - submit.addEventListener('click', () => startGame()); - reset.addEventListener('click', () => resetGame()); +// // Callback function to reset Timer +const resetTimer = () => { + seconds = 0; }; - -initGame();