diff --git a/index.html b/index.html index 25a06fd..617e38b 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,21 @@ - SWE101 + Match the cards! -

SWE101! 🚀

+

Match Game 🚀

+
+ +
+
+
+ + +
diff --git a/script.js b/script.js index e2d0297..ef09a14 100644 --- a/script.js +++ b/script.js @@ -1 +1,317 @@ -// Please implement exercise logic here + +// boardSize has to be an even number +const boardSize = 4; +let board = []; +let firstCard = null; +let firstCardElement; +let deck; + +const container = document.querySelector(".container") + + +//0 means can flip first card , 1 means 2nd card +let gameState= 0 + +//Part 1: you need a deck of cards, 2 cards each from each deck, say if u need 16 cards, 1 card each from +const makeDeck = (cardAmount) => { + // create the empty deck at the beginning + const newDeck = []; + const suits = ['hearts', 'diamonds', 'clubs', 'spades']; + const suitsPic = ["❤️", "♦️", "♣", "♠"] + + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // make a variable of the current suit + const currentSuit = suits[suitIndex]; + const currentSuitsPic=suitsPic[suitIndex] + console.log(`current suit: ${currentSuit}`); + + // loop to create all cards in this suit + // rank 1-13 + for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { + // Convert rankCounter to string + let cardName = `${rankCounter}`; + + // 1, 11, 12 ,13 + if (cardName === '1') { + cardName = 'A'; + } else if (cardName === '11') { + cardName = 'J'; + } else if (cardName === '12') { + cardName = 'Q'; + } else if (cardName === '13') { + cardName = 'K'; + } + + // make a single card object variable + const card = { + name: cardName, + suit: currentSuit, + suitPic: currentSuitsPic, + rank: rankCounter, + }; + + console.log(`rank: ${rankCounter}`); + + // add the card to the deck + newDeck.push(card); // add double the cards to the deck + newDeck.push(card); + } + } + + return newDeck; +}; + +// 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 + let boardElement = document.createElement('div'); + + // give it a class for CSS purposes + boardElement.classList.add('board'); + + boardElement.innerHTML ="" + + // 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]; + + console.log("row",row) + + // 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); + + console.log(event.currentTarget) + + }); + + + rowElement.appendChild(square) + } + boardElement.appendChild(rowElement); + } + + return boardElement; +}; + + +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +//get randomEvenIndex from 0 to 87 + +const getRandomEven = (max) => +{let number + do{ + number = Math.floor(Math.random() * max) +} while (number%2 ===1) + +return number} + + +const shuffleCards = (cards) => { + // Loop over the card deck array once + for (let currentIndex = 0; currentIndex < cards.length; currentIndex += 1) { + // Select a random index in the deck + const randomIndex = getRandomIndex(cards.length); + // Select the card that corresponds to randomIndex + const randomCard = cards[randomIndex]; + // Select the card that corresponds to currentIndex + const currentCard = cards[currentIndex]; + // Swap positions of randomCard and currentCard in the deck + cards[currentIndex] = randomCard; + cards[randomIndex] = currentCard; + } + // Return the shuffled deck + return cards; +}; + +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 evenNumber = getRandomEven(87) +console.log(evenNumber) + let deckSubset = doubleDeck.slice(evenNumber, (boardSize * boardSize + evenNumber)); + + + console.log(deckSubset) + deck = shuffleCards(deckSubset); + board =[] + // 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()); + } + } + + console.log(board) + container.innerHTML ="" + + const timerBorderDiv = document.createElement("div") + timerBorderDiv.classList.add("timer-border") + + const timeDiv = document.createElement("div") + timeDiv.classList.add("timer") + const boardEl = buildBoardElements(board); +timerBorderDiv.appendChild(timeDiv) + container.appendChild(timerBorderDiv) + container.appendChild(boardEl); + + timer() +document.getElementById("play-btn").disabled = true; + +}; + + +//function to show match message +const showMatchMsg = () => +{ +const messageDiv = document.querySelector(".message") +messageDiv.innerHTML =`It is a match!` + +setTimeout(()=>{ +messageDiv.innerHTML ="" +gameState=0 +},1000) +} + + + +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) { + if (gameState===0){ + + console.log('first turn'); + firstCard = clickedCard; + // turn this card over + + cardElement.classList.add('flip') + cardElement.innerText = firstCard.name; + cardElement.innerHTML += `
${firstCard.suitPic}` + + // hold onto this for later when it may not match + firstCardElement = cardElement; + gameState +=1 + console.log(gameState) + + // second turn + } } + else { + console.log('second turn'); + if (gameState === 1){ + if ( + clickedCard.name === firstCard.name && + clickedCard.suit === firstCard.suit + ) { + + console.log('match'); + // turn this card over + + cardElement.classList.add('flip') + cardElement.innerText = clickedCard.name; + cardElement.innerHTML += `
${clickedCard.suitPic}` + showMatchMsg() + + + } else { + console.log('NOT a match'); + + cardElement.classList.add('flip') + cardElement.innerText = clickedCard.name; + cardElement.innerHTML += `
${clickedCard.suitPic}` + setTimeout(()=>{ + firstCardElement.innerText = '' + cardElement.innerText = '' + cardElement.classList.remove('flip') + firstCardElement.classList.remove('flip') + gameState=0 + ;},1000) + + } + + // reset the first card + firstCard = null; + } + } +}; + +const playBtn = document.querySelector("#play-btn") + + +playBtn.addEventListener("click", initGame) + + +// want to display the timer as mm:ss, say starting from 3 minutes, then would be 03:00 + +const formatTime = (time) =>{ + const minutes = Math.floor(time/60) + + let seconds = time%60; + if (seconds <10){ + seconds = `0${seconds}` + } + return `${minutes}:${seconds}` +} + +//et timer +const timer = () =>{ +const timerDiv = document.querySelector(".timer") +//count down by 1 seconds +const delayInMilliseconds = 1000; + +//start timer from 3minutes +let seconds = 180 +console.log(timerDiv) + +const ref = setInterval(() =>{ + //to show timer (starting from 3minutes) + timerDiv.innerText = formatTime(seconds) +if(seconds<=0){ + document.getElementById("play-btn").disabled = false; + clearInterval(ref) + container.innerHTML="" +} +seconds-=1 +},delayInMilliseconds) + +} + + diff --git a/styles.css b/styles.css index 04e7110..fe3bfd3 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,106 @@ +@import url("https://fonts.googleapis.com/css2?family=Abril+Fatface&family=Lato:ital@1&family=Lobster&family=Roboto&display=swap"); + body { - background-color: pink; + background-color: #f0f2f2; +} +h1 { + width: 50%; + margin: auto; + text-align: center; + font-family: "Abril Fatface"; + font-size: 4em; + color: #5f9595; +} +.square { + background-image: linear-gradient(#c4d7d1, #f8e7e560); + padding: 30px; + margin: 10px; + background-color: white; + display: inline-block; + height: 40px; + width: 10px; + vertical-align: top; + border: 2px solid #5f9595; + border-radius: 10px; + vertical-align: middle; +} + +.flip { + color: #121d1d; + background-image: none; + background-color: ghostwhite; + font-family: "Abril Fatface"; + border: 2px solid #f0bc68; + font-size: 22px; + overflow: hidden; +} + +.timer-border { + color: #f0bc68; + background-color: #f0f2f2; + display: inline-block; + width: 80px; + height: 80px; + border: 3px solid #f0bc68; + border-radius: 50%; + padding: 20px; + margin: 50px; + overflow-wrap: break-word; + display: flex; + justify-content: center; + flex-shrink: 0; +} + +.timer { + margin: auto; + font-family: Lato; + font-size: 1.5em; +} + +h1 + div { + width: 50%; + margin: auto; + text-align: center; + padding: 20px; +} + +button { + background-color: #f0f2f2; + padding: 10px 30px; + border-radius: 10px; + border: outset; + color: #5f9595; + font-family: "Abril Fatface"; + font-size: 1.5em; +} + +button:hover { + background-color: #5f9595; + color: #f0f2f2; + cursor: pointer; +} +button:disabled { + background-color: #f0f2f2; + border-style: solid; + color: dimgray; + cursor: auto; +} +.container { + display: flex; + justify-content: center; + gap: 20px; + margin-right: 15em; +} + +.board { + flex-shrink: 0; +} + +.message { + font-family: lato; + margin: auto; + width: 50%; + color: #5f9595; + font-size: 2em; + text-align: center; }