diff --git a/index.html b/index.html index 4771b50..5578129 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,24 @@ - Timer + Match Game Timer + + + -

Timer!

+

Match Game - Timer!

+ + + diff --git a/script.js b/script.js index e2d0297..e7e13f0 100644 --- a/script.js +++ b/script.js @@ -1 +1,309 @@ -// Please implement exercise logic here +// This thing mainly uses JS to generate and add HTML elements, as opposed to directly creating HTML elements in the index file + +// Global Variables +// boardSize has to be an even number +const boardSize = 4; +const board = []; +let firstCard = null; +let firstCardElement; +let deck; +const gameInfo = document.createElement("div"); +gameInfo.id = "gameInfo"; +gameInfo.classList.add("gluten"); +let currentScore = 0; +const maxScore = boardSize * 2; +let canCLick = false; +// const gameTime = 180; // time in seconds +let timeLeft = 180; +let timeInterval; + +const cardRankEmojiMap = { + 1: "🅰", + 2: "2️⃣", + 3: "3️⃣", + 4: "4️⃣", + 5: "5️⃣", + 6: "6️⃣", + 7: "7️⃣", + 8: "8️⃣", + 9: "9️⃣", + 10: "🔟", + 11: "👑👶", + 12: "👑👩", + 13: "👑👨", +}; + +const cardNameMap = { + 1: "A", + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: "J", + 12: "Q", + 13: "K", +}; + +// HTML Element Creation +// Win Message +const winMessage = document.createElement("div"); +winMessage.id = "winMessage"; +winMessage.classList.add("gluten", "winMessage"); +winMessage.innerText = "You've Won!\nCongratulations!"; +// i can't actually figure out how to make this look more like an annoying popup message +// but whatever + +// Time Div +const timeSection = document.createElement("div"); +timeSection.id - "timeSection"; +timeSection.classList.add("timeSection"); + +// Timer Display +const timeDisplay = document.createElement("h1"); +timeDisplay.id = "timeDisplay"; +timeDisplay.classList.add("gluten", "timeDisplay"); +timeDisplay.innerText = "3:00"; +timeSection.appendChild(timeDisplay); + +// Start Button +const startButton = document.createElement("button"); +startButton.id = "startButton"; +startButton.classList.add("gluten", "button"); +startButton.innerText = "Start"; +startButton.addEventListener("click", () => { + startRound(); +}); +timeSection.appendChild(startButton); + +// Reset Button +const resetButton = document.createElement("button"); +resetButton.id = "resetButton"; +resetButton.classList.add("gluten", "button"); +resetButton.innerText = "Reset"; +resetButton.addEventListener("click", () => { + resetRound(); +}); +timeSection.appendChild(resetButton); + +document.body.appendChild(timeSection); + +const refreshTimer = function () { + if (timeLeft > 0) { + timeLeft -= 1; + const secondsDisplay = ("0" + (timeLeft % 60)).slice(-2); + const minutesDisplay = Math.floor(timeLeft / 60); + + document.getElementById( + "timeDisplay" + ).innerText = `${minutesDisplay}:${secondsDisplay}`; + } else { + document.getElementById( + "gameInfo" + ).innerText = `Time's UP!\nYou did not manage to match all the cards. Your score was ${currentScore}.\n\nReset the game to play again.`; + canCLick = false; + setInterval(() => { + resetRound(); + }); + } +}; + +// Gameplay Logic +const squareClick = (cardElement, column, row) => { + // console.log(cardElement); + // console.log("FIRST CARD DOM ELEMENT", firstCard); + // console.log("BOARD CLICKED CARD", board[column][row]); + const clickedCard = board[column][row]; + + // the user already clicked on this square + if (cardElement.innerText !== "") { + return; + } + + // first turn + if (firstCard === null) { + firstCard = clickedCard; + // turn this card over + cardElement.innerText = firstCard.name; + // hold onto this for later when it may not match + firstCardElement = cardElement; + canCLick = true; + + // second turn + } else { + if ( + clickedCard.name === firstCard.name && + clickedCard.suit === firstCard.suit + ) { + currentScore++; + gameInfo.innerText = `A Match! Continue opening your cards.\nYour current score is ${currentScore}. `; + setTimeout(() => { + gameInfo.innerText = '"Pick a card, any (closed) card..."'; + }, 1000); + cardElement.innerText = clickedCard.name; + canCLick = true; + } else { + // show card to user for 1 second before turning over + gameInfo.innerText = + "Not a Match - Cards will be turned over again in 1 second!"; + cardElement.innerText = clickedCard.name; + canCLick = false; + setTimeout(() => { + // turn both cards back over + firstCardElement.innerText = ""; + cardElement.innerText = ""; + gameInfo.innerText = "Pick a card, any (closed) card..."; + canCLick = true; + }, 1000); + } + // reset the first card + firstCard = null; + } + + if (currentScore == maxScore) { + gameInfo.innerText = "Well done! You've completed the game."; + document.body.appendChild(winMessage); + setTimeout(() => { + const elementsToRemove = document.getElementById("winMessage"); + elementsToRemove.remove(); + resetRound(); + }, 5000); + } +}; + +const startRound = function () { + canCLick = true; + timeInterval = setInterval(() => { + refreshTimer(); + }, 1000); +}; + +const resetRound = function () { + firstCard = null; + canCLick = false; + + board.length = 0; + deck.length = 0; + currentScore = 0; + timeLeft = 180; + clearInterval(timeInterval); + document.getElementById("timeDisplay").innerText = "3:00"; + + document.getElementById("boardElement").remove(); + initGame(); +}; + +// Game Initialization Logic +// 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"); + boardElement.id = "boardElement"; + + // 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", "gluten"); + + // 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" + if (canCLick) { + squareClick(event.currentTarget, i, j); + } + }); + + rowElement.appendChild(square); + } + boardElement.appendChild(rowElement); + } + + return boardElement; +}; + +const makeDeck = function () { + const cardDeck = []; + const suits = ["hearts", "diamonds", "clubs", "spades"]; + let suitIndex = 0; + while (suitIndex < suits.length) { + var currentSuit = suits[suitIndex]; + let rankCounter = 1; + while (rankCounter <= 13) { + const cardName = cardNameMap[rankCounter]; + const cardRankEmojiTemp = cardRankEmojiMap[rankCounter]; + + const card = { + name: cardName, + suit: currentSuit, + rank: rankCounter, + cardRankEmoji: cardRankEmojiTemp, + }; + cardDeck.push(card); + cardDeck.push(card); + rankCounter += 1; + } + suitIndex += 1; + } + return cardDeck; +}; + +const shuffleCards = function (array) { + // based on Durstenfeld shuffle + // https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array + for (let i = array.length - 1; i > 0; i -= 1) { + const j = Math.floor(Math.random() * (i + 1)); + const temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + return array; +}; + +const initGame = () => { + // create this special deck by getting the doubled cards and + // making a smaller array that is ( boardSize squared ) number of cards + let doubleDeck = makeDeck(); + let deckSubset = doubleDeck.slice(0, boardSize * boardSize); + deck = 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(deck.pop()); + } + } + + const boardEl = buildBoardElements(board); + document.body.appendChild(boardEl); + + gameInfo.innerText = "Welcome to Match Game - Click Start to begin~"; + gameInfo.classList.add("game-info"); + document.body.appendChild(gameInfo); +}; + +// Main Function +initGame(); diff --git a/stopwatch_index.html b/stopwatch_index.html new file mode 100644 index 0000000..9514147 --- /dev/null +++ b/stopwatch_index.html @@ -0,0 +1,49 @@ + + + + Stopwatch + + + + + + + +

Stopwatch

+ +
+
+

Insert Lap Data

+
+ +
+

00 : 00 : 00

+ +
+
+ + +
+
+ + +
+
+
+
+ +
+ + + +
+ + + + + diff --git a/stopwatch_script.js b/stopwatch_script.js new file mode 100644 index 0000000..ff13885 --- /dev/null +++ b/stopwatch_script.js @@ -0,0 +1,56 @@ +// laps are saved as values within a 1D array +// elapsed time must start from 0a nd count up +let currentElapsedTime = 0; +let stopped = true; +let timerInterval; + +const showTime = function (element, elapsedTime) { + let tempTime = elapsedTime; + + let seconds = tempTime % 1000; // get the remainder of 1000 ms which can go to second + tempTime = Math.floor(tempTime / 1000); //to get seconds + let minutes = tempTime % 60; // get the remainder of 60s which can go to minutes + tempTime = Math.floor(tempTime / 60); // to get minutes + let hours = tempTime % 60; // get the remainder of 60mins which can go to hours + + let timeStr = ""; + timeStr += hours.toString().padStart(2, "0") + " : "; + timeStr += minutes.toString().padStart(2, "0") + " : "; + timeStr += seconds.toString().padStart(2, "0"); + element.innerHTML = timeStr; + return element.innerHTML; +}; + +const startButtonFunction = function () { + stopped = false; + timerInterval = setInterval(() => { + currentElapsedTime += 1; + showTime(document.getElementById("elapsedTime"), currentElapsedTime); + }, 1000); +}; + +const stopButtonFunction = function () { + clearInterval(timerInterval); +}; + +const startButton = document.getElementById("startButton"); +const stopButton = document.getElementById("stopButton"); +const resetButton = document.getElementById("resetButton"); +const lapButton = document.getElementById("lapButton"); + +// Setting Event Listeners +window.onload = function () { + startButton.addEventListener("click", () => { + startButtonFunction(); + }); + stopButton.addEventListener("click", () => { + // call a fuction to stop the countdown + stopButtonFunction(); + }); + resetButton.addEventListener("click", () => { + // call a function to set elapsed time and lap data to zero + }); + lapButton.addEventListener("click", () => { + // call a fuction to lap and append the current lap time to the lap data div + }); +}; diff --git a/stopwatch_styles.css b/stopwatch_styles.css new file mode 100644 index 0000000..3186bd5 --- /dev/null +++ b/stopwatch_styles.css @@ -0,0 +1,77 @@ +body { + background-color: #36395a; + color: #fff; + font-family: "Concert One", cursive; + text-align: center; +} + +.timeSection { + display: block; + width: auto; + background-color: #5a5e9a; + text-align: center; +} + +.timeDisplay { + width: fit-content; + height: fit-content; + margin: auto; + text-align: center; + font-size: 72px; + display: inline-block; +} + +.functionButtons { + display: inline-block; + width: auto; + background-color: #2cc8f7; + text-align: center; + vertical-align: middle; +} + +.button { + margin: auto; + padding: 10px; + font-size: 24px; + text-align: center; + width: 150px; + + display: inline-block; + outline: 0; + cursor: pointer; + border-radius: 6px; + border: 2px solid #618685; + color: #618685; + background: 0 0; + padding: 8px; + box-shadow: rgba(0, 0, 0, 0.07) 0px 2px 4px 0px, + rgba(0, 0, 0, 0.05) 0px 1px 1.5px 0px; + font-family: "Concert One", cursive; + font-weight: 800; + font-size: 16px; + height: 42px; +} + +.button:hover { + background-color: #618685; + color: #fff; +} + +.concert { + font-family: "Concert One", cursive; +} + +.center { + width: auto; + margin: auto; +} + +.leftSide { + background-color: pink; + display: inline-block; +} + +.rightSide { + background-color: powderblue; + display: inline-block; +} diff --git a/styles.css b/styles.css index 04e7110..f1c44c5 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,91 @@ body { - background-color: pink; + background-color: #fefbd8; + font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande", + "Lucida Sans Unicode", Geneva, Verdana, sans-serif; + text-align: center; +} + +.board { + background-color: #d5f4e6; + border-radius: 10px; + width: fit-content; + margin: auto; +} + +.square { + padding: 10px; + margin: 10px; + background-color: white; + display: inline-block; + height: 30px; + width: 30px; + vertical-align: middle; + border-radius: 5px; + text-align: match-parent; +} + +.square:hover { + background-color: #618685; +} + +.game-info { + padding: 10px; + margin: 10px auto auto auto; + width: fit-content; + background-color: #80ced6; + border-radius: 10px; + border: 2px solid black; + text-align: center; + font-size: 24px; +} + +.winMessage { + width: auto; + margin: 20px; + padding: 40px; + background-color: #618685; + color: white; + text-align: center; + border-radius: 6px; + font-size: 48px; +} + +.timeSection { + /* background-color: aquamarine; */ + text-align: center; +} + +.timeDisplay { + width: fit-content; + margin: auto; + text-align: center; + font-size: 48px; +} + +.button { + margin: 0 5px 10px 5px; + font-size: 24px; + + display: inline-block; + outline: 0; + cursor: pointer; + border-radius: 6px; + border: 2px solid #618685; + color: #618685; + background: 0 0; + padding: 8px; + box-shadow: rgba(0, 0, 0, 0.07) 0px 2px 4px 0px, + rgba(0, 0, 0, 0.05) 0px 1px 1.5px 0px; + font-weight: 800; + font-size: 16px; + height: 42px; +} + +.button:hover { + background-color: #618685; + color: #fff; +} + +.gluten { + font-family: "Gluten", cursive; }