首页 > 解决方案 > 在按钮单击时启动 gameReady 功能

问题描述

我是 JS 的新手,我正在看一个关于如何创建一个简单的记忆游戏的教程。我有足够的信心理解代码背后的逻辑以开始进行更改,但也许我并不像我想象的那样理解它。

目前,当我在页面重新加载时单击覆盖文本时,游戏开始并运行。我想改变这个,所以只有当我点击新创建的“开始”按钮时游戏才会开始。

我试过下面的代码,但它似乎没有工作。我的 console.log 上没有错误。

任何人都可以指出我做错了什么的正确方向吗?任何帮助表示赞赏。谢谢!

function gameReady() {
    let overlays = Array.from(document.getElementsByClassName("screen-overlay"));
    let cards = Array.from(document.getElementsByClassName("card"));
    let startButton = Array.from(document.getElementById("start"));
    let game = new SimpleMemoryGame (60, cards);

    overlays.forEach(overlay => {
        overlay.addEventListener("click",() =>{
            overlay.classList.remove("show-front");
            //game.startGame();
        });
    });
    cards.forEach(card =>{
        card.addEventListener("click" , () => {
            game.flip(card);
        });
    });

    startButton.forEach(start =>{
        startButton.addEventListener("click" , () => {
            game.startGame();
        });
    });

class SimpleMemoryGame {
    constructor (time, cards) {
        this.cardsList = cards;
        this.time = time;
        this.timeLeft= time;
        this.timerElement = document.getElementById("time-left");
        
    }

    startGame (){
        this.cardToCheck = null;
        this.timeLeft = this.time;
        this.matches = []; 
        this.busy = true;
        setTimeout(()=> {
            this.shuffle(this.cardsList);
            this.timerStarted = this.startTimer();
            this.busy = false;
        },500);
        this.hideCards();
        this.timerElement.innerText = this.timeLeft;


    }

    //Goes through all the cards to remove the "show-front" class at the start of every game

    hideCards() {
        this.cardsList.forEach (card => {
        card.classList.remove("show-front");
    });

    }


    gameOver(){
        clearInterval(this.timerStarted);
        document.getElementById("game-over-screen").classList.add("show-front");

    }

    win (){
        clearInterval(this.timerStarted);
        document.getElementById("you-won").classList.add("show-front");
    }

    //Timer with if statement to trigger gameOver function when it is equal to 0. 
    //setInterval set at 1000 ms to replicate 1s countdown
    startTimer() {
            return setInterval(() => {
            this.timeLeft-=1 ;
            this.timerElement.innerHTML = this.timeLeft;
            if (this.timeLeft === 0) this.gameOver();

        },1000);
    }
    
    //Function to check whether card can be flipped by checking other functions as conditions with an if statement 
    flip(card) {
        if (this.cardIsFlippable(card)){
            card.classList.add("show-front");

            if(this.cardToCheck) {
                this.matchedCardChecker(card);
            } else {
              this.cardToCheck = card;
            }
        }

    }

    matchedCardChecker (card){

        if(this.getCardType(card) === this.getCardType(this.cardToCheck))
            this.cardMatches(card,this.cardToCheck);
        else
            this.cardDoesNotMatch (card,this.cardToCheck);

        this.cardToCheck = null;

    }

    cardMatches(card1,card2) {
        this.matches.push(card1);
        this.matches.push(card2);
        if (this.matches.length === this.cardsList.length)  this.win();
           

    }

    cardDoesNotMatch(card1,card2){
        this.busy = true;
        setTimeout(() => {
            card1.classList.remove("show-front");
            card2.classList.remove("show-front");
            this.busy= false;
        },1000
        )

    }

    getCardType(card){
        return card.getElementsByClassName("card-match")[0].src;
    }

    shuffle() {
        
        for(let i = this.cardsList.length -1; i>0; i--) {
            let randomise = Math.floor(Math.random() * (i+1));
            this.cardsList[randomise].style.order = i; 
            this.cardsList [i].style.order = randomise;
        }
    }
   // Function to check if the user can flip the card
   cardIsFlippable(card){ 
   //All statements need to return false in order for it to be true so they can flip the card
        return !this.busy && !this.matches.includes(card) && card !== this.cardToCheck;
    }

}

// Statement to check if the page has loaded 
if (document.readyState === "loading") {
    document.addEventListener ("DOMContentLoaded",gameReady());
} else {
    gameReady();
}


function gameReady() {
    let overlays = Array.from(document.getElementsByClassName("screen-overlay"));
    let cards = Array.from(document.getElementsByClassName("card"));
    let game = new SimpleMemoryGame (60, cards);
    
    overlays.forEach(overlay => {
        overlay.addEventListener("click",() =>{
            overlay.classList.remove("show-front");
            //game.startGame();
        });
    });
    cards.forEach(card =>{
        card.addEventListener("click" , () => {
            game.flip(card);
        });
    });

}  

标签: javascript

解决方案


document.getElementById()仅返回单个节点而不是节点数组。

因此,您可以使用querySelectorAll它来指定选择具有相同 ID 或 Class 的多个元素。

因此,像下面这样更改startButton分配,并替换startButton.addEventListenerstart.addEventListener.

startGame()如下所述添加 clearInterval 。因此,当用户在没有先完成游戏的情况下开始游戏时,它将清除以前的计时器。

let startButton = Array.from(document.querySelectorAll("#start"));

startButton.forEach(start => {
    start.addEventListener("click" , () => {
        game.startGame();
    });
});

startGame() {
    this.cardToCheck = null;
    this.timeLeft = this.time;
    this.matches = []; 
    this.busy = true;
    setTimeout(()=> {
        this.shuffle(this.cardsList);
        // add clearInterval here so when user starts game without finishing the game first then it will clear previous timer.
        clearInterval(this.timerStarted);
        this.timerStarted = this.startTimer();
        this.busy = false;
    },500);
    this.hideCards();
    this.timerElement.innerText = this.timeLeft;
}

推荐阅读