我创建了具有12种难度的记忆卡游戏 ,我想通过创建新的动态元素来添加更多卡牌,并在遇到困难时将其添加到游戏容器中。
使用此代码,我希望新创建的元素具有flipCard()函数,当我单击它时它将翻转卡片。但是,这不起作用,每当我单击卡时,它给我一个错误
'TypeError: this.classlist is undefined'
(flipCard函数内部错误)
game.addEventListener('click', function (e) {
if (e.target) {
flipCard();
}
});
下面的代码将起作用,但不适用于动态元素。
cards.forEach(card => {
cardCount.push(card);
card.addEventListener('click', flipCard);
});
window.onload = function() {
const game = document.querySelector('.game');
const cards = document.querySelectorAll('.card');
const scoreboard = document.querySelector('.score');
const move = document.querySelector('.move');
const difficulties = document.getElementById("difficulties");
let isCardFlipped = false,
lockBoard = false,
firstCard,
secondCard,
score = 0,
moves = 0,
unflipTimeout = 1500,
cardCount = [];
difficulties.addEventListener("change", function() {
resetGame();
});
function addCard() {
for (i = 0; i < 4; i++) {
game.innerHTML += "<div class='card'>" + "<img src='assets/image/default/bellsprout.svg' class='front-face'>" +
"<img src='assets/image/default/pokeball.svg' class='back-face'>" + "</div>";
}
};
// ATTACH CLICK EVENT AND flipCard() FUNCTION FOR EVERY CARD.
// THIS DOESN'T WORK FOR DYNAMICALLY CREATED ELEMENT
// cards.forEach(card => {
// cardCount.push(card);
// card.addEventListener('click', flipCard);
// });
// ATTACH CLICK EVENT AND flipCard() FUNCTION FOR EVERY CARD.
// THIS WILL WORK FOR DYNAMICALLY CREATED ELEMENT,
// BUT "this." INSIDE flipCard() function is not defined/initialize
game.addEventListener('click', function(e) {
if (e.target) {
flipCard();
}
});
// Difficulty Option
(difficulty = () => {
let selected = difficulties.options[difficulties.selectedIndex].value;
if (selected === 'easy') {
unflipTimeout = 1500;
} else if (selected === 'hard') {
unflipTimeout = 500;
// ADD MORE CARD ONLY IF HARD DIFFICULTY IS SELECTED
addCard();
}
})();
// flip card when card is clicked
function flipCard() {
if (lockBoard || this === firstCard) return;
this.classList.add('flip');
if (!isCardFlipped) {
isCardFlipped = true;
firstCard = this;
return;
}
isCardFlipped = false;
secondCard = this;
checkForMatch();
}
// check if 2 selected card are match.
checkForMatch = () => {
// if matched disabled card function, unflip card if not matched.
let isMatch = firstCard.dataset.pokemon ===
secondCard.dataset.pokemon;
isMatch ? disableCard() : unflipCard(unflipTimeout);
}
// disable flip card function
disableCard = () => {
moves++;
score++;
updateScore();
firstCard.removeEventListener('click', flipCard);
secondCard.removeEventListener('click', flipCard);
}
unflipCard = (timeout) => {
lockBoard = true;
moves++;
updateScore();
setTimeout(() => {
firstCard.classList.remove('flip');
secondCard.classList.remove('flip');
resetBoard();
}, timeout);
}
resetBoard = () => {
[isCardFlipped, lockBoard] = [false, false];
[firstCard, secondCard] = [null, null];
}
resetGame = () => {
if (moves > 0) {
var confirm = window.confirm("Changes will be applied after reset \n \n \t \t Reset The Game?");
if (confirm === true) {
score = 0;
moves = 0;
updateScore();
for (var i = 0; i < cardCount.length; i++) {
cardCount[i].classList.remove('flip');
}
alert('Game Restarted! \n \n \t Card Reshuffle.');
shuffle();
} else return;
}
}
var shuffle;
(shuffle = () => {
cards.forEach(card => {
let randomPos = Math.round(Math.random() * cardCount.length);
card.style.order = randomPos;
});
})();
updateScore = () => {
scoreboard.innerText = score;
move.innerText = moves;
if (score === cardCount.length / 2) {
alert("You Win!");
}
}
};
.scoreboard {
display: flex;
flex-flow: row nowrap;
justify-content: space-around;
align-items: center;
padding: 2px;
border-radius: 5px;
background: #363636;
color: #0a8ec2;
}
.scoreboard h1 {
font-size: 1.5rem;
}
.game {
width: 580px;
height: 580px;
margin: auto;
display: flex;
flex-wrap: wrap;
perspective: 1000px;
position: relative;
}
.game .card {
position: relative;
width: calc(25% - 10px);
height: calc(33.333% - 10px);
margin: 5px;
transform-style: preserve-3d;
transition: transform 500ms linear;
}
.game .card.active {
transform: scale(0.97);
}
.game .card.flip {
transform: rotateY(180deg);
}
.game .card .front-face,
.game .card .back-face {
width: 100%;
height: 100%;
position: absolute;
border-radius: 5px;
padding: 20px;
background: #363636;
backface-visibility: hidden;
}
.game .card .front-face {
transform: rotateY(180deg);
backface-visibility: visible;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="assets/css/styles.css">
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/main.js"></script>
<script src="assets/js/app.js"></script>
<title>Memory Card Game</title>
</head>
<body>
<section class="scoreboard">
<h1>Score: <span class="score">0</span> <br> Moves: <span class="move">0</span></h1>
<select id="difficulties" name="difficulties">
<option value="default" disabled>Select Difficulty</option>
<option value="easy" selected>Easy</option>
<option value="hard">Hard</option>
</select>
</section>
<main class="game">
<div class="card" data-pokemon="rattata">
<img src="assets/image/default/rattata.svg" alt="Rattata" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="rattata">
<img src="assets/image/default/rattata.svg" alt="Rattata" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="meowth">
<img src="assets/image/default/meowth.svg" alt="Meowth" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="meowth">
<img src="assets/image/default/meowth.svg" alt="Meowth" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mew">
<img src="assets/image/default/mew.svg" alt="Mew" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mew">
<img src="assets/image/default/mew.svg" alt="Mew" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mankey">
<img src="assets/image/default/mankey.svg" alt="Mankey" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mankey">
<img src="assets/image/default/mankey.svg" alt="Mankey" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="venonat">
<img src="assets/image/default/venonat.svg" alt="Venonat" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="venonat">
<img src="assets/image/default/venonat.svg" alt="Venonat" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="psyduck">
<img src="assets/image/default/psyduck.svg" alt="Psyduck" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="psyduck">
<img src="assets/image/default/psyduck.svg" alt="Psyduck" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
</main>
</body>
</html>
答案 0 :(得分:0)
代替此:
if (e.target) {
flipCard();
}
执行此操作:
if (e.target) {
flipCard.bind(this)();
}
将此添加到点击监听器中。 this
函数中的flipCard
指向window
。