Carminos
Carminos

Reputation: 69

Memory card game stops working after first two cards flipped

I have a simple memory card concentration game with a function to flipCard and checkForMatch . When the checkForMatch function is invoked it evaluates the two cards to see if a match is found and returns an alert message letting the know if the user has got a match or not. Everything works fine initially but right after the first two cards are selected the alerts no longer pop up and the cards don't flip back, so essentially the user can continue flipping over all the remaining cards on the game board. I'm not sure why it's not working after the first two flips. I've tried moving my createBoard() function and moving the flipCard function above the checkForMatch() but that doesn't solve the issue either.

document.addEventListener('DOMContentLoaded', () =>{

const cardArray = [
    {
        name: 'monster1',
        img: 'image1.png'
    },
    {
        name: 'monster1',
        img: 'image1.png'
    },
    {
        name: 'monster2',
        img: 'image2.png'
    },
    {
        name: 'monster2',
        img: 'image2.png'
    },
    {
        name: 'monster3',
        img: 'image3.png'
    },
    {
        name: 'monster3',
        img: 'image3.png'
    },
    {
        name: 'monster4',
        img: 'image4.jpg'
    },
    {
        name: 'monster4',
        img: 'image4.jpg'
    },
    {
        name: 'monster5',
        img: 'image5.png'
    },
    {
        name: 'monster5',
        img: 'image5.png'
    },
    {
        name: 'monster6',
        img: 'image6.png'
    },
    {
        name: 'monster6',
        img: 'image6.png'
    }
]

cardArray.sort(() => 0.5 - Math.random()) 

const grid = document.querySelector('.grid');
const resultDisplay = document.querySelector('#result')
const cardsChosen = []
const cardsChosenId = []
const cardsWon = []

function createBoard(){
    for (let i = 0; i < cardArray.length; i++) {
        const card = document.createElement('img')
        card.setAttribute('src','logo.png')
        card.setAttribute('data-id', i)
        card.addEventListener('click', flipCard)
        grid.appendChild(card)
    }
}

// Flip Your card
function flipCard() {
    const cardId = this.getAttribute('data-id')
    cardsChosen.push(cardArray[cardId].name)
    cardsChosenId.push(cardId)
    this.setAttribute('src', cardArray[cardId].img)
    if(cardsChosen.length === 2) {
        setTimeout(checkForMatch, 500)      }
}

// Check for matches
function checkForMatch() {
    const cards = document.querySelectorAll('img')
    const optionOneId = cardsChosenId[0] 
    const optionTwoId = cardsChosenId[1] 
    
    if (cardsChosen[0] === cardsChosen[1]) {
        alert('You found a match!')
        cards[optionOneId].setAttribute('src', 'white.png')
        cards[optionTwoId].setAttribute('src', 'white.png')
        cardsWon.push(cardsChosen)
    } else {
        alert('Sorry, try again!')
        cards[optionOneId].setAttribute('src', 'logo.png')
        cards[optionTwoId].setAttribute('src', 'logo.png')
    }
    cardsChosen = []
    cardsChosenId = []
    resultDisplay.textContent = cardsWon.length 
    if (cardsWon.length === cardArray.length/2) {
        resultDisplay.textContent = 'Congratulations! You found all the cards!'
    }
}

createBoard()

})
.grid{
    display: flex;
    flex-wrap: wrap;
    height: 300px;
    width: 400px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <title>Memory Game - Ania Kubow Tutorial</title>
</head>

<body>
    <h3>Score:<span id="result"></span></h3>

    <div class="grid"></div>

    <script src="index.js"></script>
</body>
</html>

Upvotes: 1

Views: 137

Answers (1)

Karan
Karan

Reputation: 12629

Problem : You can not re-instantiate const variables which you were doing inside checkForMatch, which is throwing error and your code is not working.

There are two solutions for this.

Solution 1 - You can update declaration of cardsChosen & cardsChosenId with let instead of const.

Solution 2 - To clear array, do not re-instantiate it with cardsChosen = [] but use cardsChosen.splice(0, cardsChosen.length);.

P.S. - You can check browser console and you would have idea about what error you were getting. This way it could have been easy for you to fix problem.

document.addEventListener('DOMContentLoaded', () => {

  const cardArray = [{
      name: 'monster1',
      img: 'image1.png'
    },
    {
      name: 'monster1',
      img: 'image1.png'
    },
    {
      name: 'monster2',
      img: 'image2.png'
    },
    {
      name: 'monster2',
      img: 'image2.png'
    },
    {
      name: 'monster3',
      img: 'image3.png'
    },
    {
      name: 'monster3',
      img: 'image3.png'
    },
    {
      name: 'monster4',
      img: 'image4.jpg'
    },
    {
      name: 'monster4',
      img: 'image4.jpg'
    },
    {
      name: 'monster5',
      img: 'image5.png'
    },
    {
      name: 'monster5',
      img: 'image5.png'
    },
    {
      name: 'monster6',
      img: 'image6.png'
    },
    {
      name: 'monster6',
      img: 'image6.png'
    }
  ]

  cardArray.sort(() => 0.5 - Math.random())

  const grid = document.querySelector('.grid');
  const resultDisplay = document.querySelector('#result')
  let cardsChosen = []
  let cardsChosenId = []
  let cardsWon = []

  function createBoard() {
    for (let i = 0; i < cardArray.length; i++) {
      const card = document.createElement('img')
      card.setAttribute('src', 'logo.png')
      // Added alt for test only
      card.setAttribute('alt', cardArray[i].name)
      card.setAttribute('data-id', i)
      card.addEventListener('click', flipCard)
      grid.appendChild(card)
    }
  }

  // Flip Your card
  function flipCard() {
    const cardId = this.getAttribute('data-id')
    cardsChosen.push(cardArray[cardId].name)
    cardsChosenId.push(cardId)
    this.setAttribute('src', cardArray[cardId].img)
    if (cardsChosen.length === 2) {
      setTimeout(checkForMatch, 500)
    }
  }

  // Check for matches
  function checkForMatch() {
    const cards = document.querySelectorAll('img')
    const optionOneId = cardsChosenId[0]
    const optionTwoId = cardsChosenId[1]

    if (cardsChosen[0] === cardsChosen[1]) {
      alert('You found a match!')
      cards[optionOneId].setAttribute('src', 'white.png')
      cards[optionTwoId].setAttribute('src', 'white.png')
      cardsWon.push(cardsChosen)
    } else {
      alert('Sorry, try again!')
      cards[optionOneId].setAttribute('src', 'logo.png')
      cards[optionTwoId].setAttribute('src', 'logo.png')
    }
    cardsChosen = []
    cardsChosenId = []
    resultDisplay.textContent = cardsWon.length
    if (cardsWon.length === cardArray.length / 2) {
      resultDisplay.textContent = 'Congratulations! You found all the cards!'
    }
  }

  createBoard()

})
.grid {
  display: flex;
  flex-wrap: wrap;
  height: 300px;
  width: 400px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="index.css">
  <title>Memory Game - Ania Kubow Tutorial</title>
</head>

<body>
  <h3>Score:<span id="result"></span></h3>

  <div class="grid"></div>

  <script src="index.js"></script>
</body>

</html>

Upvotes: 1

Related Questions