javascript - 在按钮单击时启动 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);
});
});
}
解决方案
document.getElementById()
仅返回单个节点而不是节点数组。
因此,您可以使用querySelectorAll
它来指定选择具有相同 ID 或 Class 的多个元素。
因此,像下面这样更改startButton
分配,并替换startButton.addEventListener
为start.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;
}
推荐阅读
- javascript - jexcel清除和更新新数据
- excel - VBA 仅在当前工作表而不是整个工作簿上运行
- javascript - javascript 引用实例无法访问构造函数中的方法?
- android - 在 Kotlin DialogFragment 上使用多项选择项设置完成按钮
- java - 卸载旧 Java 版本后 Eclipse 崩溃
- javascript - 如何阻止 Heroku 尝试使用 `npm start` 启动脚本?
- laravel - Laravel - Laravel Spatie - 资源特定权限 [替代 - 解决方案]
- mysql - 如何从日期中提取日、月和年?
- php - 删除嵌套 foreach PHP 中的嵌套数组
- java - 插入排序arraylist,按字母顺序对数字和名称进行升序排序