英文:
Quiz in Javascript
问题
以下是您提供的代码的翻译部分:
我对编程还很陌生,但我必须重新创建一个测验。然而,有些东西不正常工作,最大的问题是:在选择答案时,我应该得到有关答案是正确还是错误的消息(答案应该被隐藏,下一个按钮应该显示),然后点击下一个按钮后,答案再次显示,按钮隐藏。
以下是我的代码:
<!-- 开始代码段:js 隐藏:false 控制台:true Babel:false -->
<!-- 语言: lang-js -->
const questions = [
{
question: "这是一个容易的问题。你能认出这辆豪华SUV吗?",
image: "images/jaguar.jpg",
answers: ["捷豹E-Pace", "保时捷卡宴", "梅赛德斯GLA"],
correct: "捷豹E-Pace"
},
{
question: "你认为你能认出这是哪个宝马系列吗?",
image: "images/bmw8.jpg",
answers: ["宝马6系", "宝马3系", "宝马8系"],
correct: "宝马8系"
},
{
question: "再来一个SUV……",
image: "images/duster.jpg",
answers: ["达奇亚·达斯特", "MINI Countryman", "Jeep Renegade"],
correct: "达奇亚·达斯特"
},
{
question: "你认出这款新型轿车了吗?",
image: "images/genesis.jpg",
answers: ["MG HS", "Genesis G80", "奥迪A7"],
correct: "Genesis G80"
},
{
question: "你能认出这款家庭SUV吗?",
image: "images/outlander.jpg",
answers: ["现代圣达菲", "起亚Sorento", "三菱Outlander PHEV"],
correct: "三菱Outlander PHEV"
},
{
question: "现在是紧凑型SUV的时候……",
image: "images/ford.jpg",
answers: ["福特普马", "保时捷麦坎", "尼桑Juke"],
correct: "福特普马"
},
{
question: "你能猜出这是哪款德国掀背车吗?",
image: "images/audi3.jpg",
answers: ["梅赛德斯A级", "奥迪A3运动型掀背车", "宝马1系"],
correct: "奥迪A3运动型掀背车"
},
{
question: "嗯,这个怎么样…… ",
image: "images/renault.jpg",
answers: ["雷诺Zoe", "DS 3", "日产March"],
correct: "雷诺Zoe"
},
{
question: "这是哪款现代车?",
image: "images/hyundaikona.jpg",
answers: ["现代i10", "现代Ioniq", "现代Kona"],
correct: "现代Kona"
},
{
question: "这是哪款掀背车?",
image: "images/mazda2.jpg",
answers: ["福特福克斯", "马自达2", "日产March"],
correct: "马自达2"
},
{
question: "你能认出这款豪华轿车吗?",
image: "images/jaguarxe.jpg",
answers: ["捷豹XE", "宝马3系", "梅赛德斯E级"],
},
{
question: "这是哪款SUV?",
image: "images/jeep.jpg",
answers: ["路虎发现", "Jeep Compass", "起亚Sorento"],
correct: "Jeep Compass"
},
{
question: "这是哪款福特型号?",
image: "images/fiesta.jpg",
answers: ["普马", "库加", "嘉年华ST"],
correct: "嘉年华ST"
},
{
question: "你认出这辆玛莎拉蒂了吗?",
image: "images/maserati.jpg",
answers: ["吉布利", "莱文特", "四门轿车"],
correct: "吉布利"
},
{
question: "你能猜出这是哪款路虎吗?",
image: "images/rangerover.jpg",
answers: ["揽胜", "极光", "卫士"],
correct: "揽胜"
},
{
question: "这是哪款新混合动力超迷你车型?",
image: "images/fiat.jpg",
answers: ["MINI掀背车", "菲亚特500", "雷诺Twingo"],
correct: "菲亚特500"
},
{
question: "这款斯柯达车型怎么样?",
image: "images/skoda.jpg",
answers: ["明锐", "卡米克", "速派"],
correct: "明锐"
},
{
question: "你能认出这款沃尔沃吗?",
image: "images/volvo.jpg",
answers: ["XC40", "XC90", "XC60"],
correct: "XC 40"
},
{
question: "这是哪款大众车型?",
image: "images/golf.jpg",
answers: ["阿蒂昂", "高尔夫", "T-Roc"],
correct: "高尔夫"
},
{
question: "这是哪款掀背车?",
image: "images/corsa.jpg",
answers: ["欧宝科尔萨", "欧宝Astra", "欧宝Adam"],
correct: "欧宝科尔萨"
}
]
<details>
<summary>英文:</summary>
I'm quite new to programming and I have to recreate a quiz. Though something is not working properly, the biggest issue is: when selecting an answer I should get the message about whether the answer is correct or wrong(answers should be hidden, and the next button displayed) and after clicking the next button, answers get displayed again and the button hidden.
Here is my code:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const questions = [
{
question: "Here's an easy one. Can you recognise this premium SUV?",
image: "images/jaguar.jpg",
answers: ["Jaguar E-Pace", "Porsche Cayenne", "Mercedex GLA"],
correct: "Jaguar E-Pace"
},
{
question: "Do you think you can recognise what BMW series this is?",
image: "images/bmw8.jpg",
answers: ["BMW 6 Series", "BMW 3 Series", "BMW 8 Series"],
correct: "BMW 8 Series"
},
{
question: "Time for another SUV...",
image: "images/duster.jpg",
answers: ["Dacia Duster", "MINI Countryman", "Jeep Renegade"],
correct: "Dacia Duster"
},
{
question: "Do you recognise this new saloon?",
image: "images/genesis.jpg",
answers: ["MG HS", "Genesis G80", "Audi A7"],
correct: "Genesis G80"
},
{
question: "Can you recognise this family SUV?",
image: "images/outlander.jpg",
answers: ["Hyundai Santa Fe", "Kia Sorento", "Mitsubishi Outlander PHEV"],
correct: "Mitsubishi Outlander PHEV"
},
{
question: "Now for a compact SUV...",
image: "images/ford.jpg",
answers: ["Ford Puma", "Porsche Macan", "Nissan Juke"],
correct: "Ford Puma"
},
{
question: "Can you guess what German hatchback this is?",
image: "images/audi3.jpg",
answers: ["Mercedes A Class", "Audi A3 Sportback", "Bmw 1 Series"],
correct: "Audi A3 Sportback"
},
{
question: "Hmmm, how about this one... ",
image: "images/renault.jpg",
answers: ["Renault Zoe", "DS 3", "Nissan Micra"],
correct: "Renault Zoe"
},
{
question: "Which Hyundai is this?",
image: "images/hyundaikona.jpg",
answers: ["Hyundai i10", "Hyundai Ioniq", "Hyundai Kona"],
correct: "Hyundai Kona"
},
{
question: "What hatchback is this?",
image: "images/mazda2.jpg",
answers: ["Ford Focus", "Mazda 2", "Nissan Micra"],
correct: "Mazda 2"
},
{
question: "Can you recognise this premium saloon?",
image: "images/jaguarxe.jpg",
answers: ["Jaguar XE", "BMW 3 Series", "Mercedes E Class"]
},
{
question: "What SUV is this?",
image: "images/jeep.jpg",
answers: ["Landrover Discovery", "Jeep Compass", "Kia Sorento"],
correct: "Jeep Compass"
},
{
question: "What Ford model is this?",
image: "images/fiesta.jpg",
answers: ["Puma", "Kuga", "Fiesta ST"],
correct: "Fiesta ST"
},
{
question: "Do you recognise this Maserati?",
image: "images/maserati.jpg",
answers: ["Ghibli", "Levante", "Quattroporte"],
correct: "Ghibli"
},
{
question: "Can you guess what Landrover this is?",
image: "images/rangerover.jpg",
answers: ["Range Rover", "Evoque", "Defender"],
correct: "Range Rover"
},
{
question: "What new Hybrid super mini this is?",
image: "images/fiat.jpg",
answers: ["MINI Hatchback", "Fiat 500", "Renault Twingo"],
correct: "Fiat 500"
},
{
question: "How about this Skoda model?",
image: "images/skoda.jpg",
answers: ["Octavia", "Kamiq", "Superb"],
correct: "Octavia"
},
{
question: "Can you recognise this Volvo?",
image: "images/volvo.jpg",
answers: ["XC40", "XC90", "XC60"],
correct: "XC 40"
},
{
question: "Which Volkswagen model is this?",
image: "images/golf.jpg",
answers: ["Arteon", "Golf", "T-Roc"],
correct: "Golf"
},
{
question: "What is this hatchback?",
image: "images/corsa.jpg",
answers: ["Vauxhall Corsa", "Vauxhall Astra", "Vauxhall Adam"],
correct: "Vauxhall Corsa"
}
]
const startButton = document.getElementById('start-btn')
const nextButton = document.getElementById('next-btn')
const questionEl = document.getElementById('question')
const answers = document.getElementById('answers')
const message = document.getElementById('message')
const image = document.getElementById('image')
//const text = document.getElementById('text')
let questionNr = 0
startButton.addEventListener("click", startGame)
nextButton.addEventListener("click", () => {
questionNr++
setNextQuestion()
})
function startGame() {
startButton.classList.add('hide')
question.classList.remove('hide')
setNextQuestion()
}
function setNextQuestion() {
resetState()
showQuestion(questions[questionNr])
}
function showQuestion(question) {
questionEl.innerHTML = question.question
//answers.innerHTML = questions[questionNr].answers
image.src = questions[questionNr].image
answers.innerHTML = ''
questions[questionNr].answers.forEach(answer => {
answers.innerHTML += `<button class="btn">${answer}</button>`
})
// question.answers.forEach(answer => {
// const button = document.createElement('button')
// button.innerText = `${answer}`
// button.classList.add('btn')
// if (answer.correct) {
// button.dataset.correct = answer.correct
// }
// button.addEventListener("click", selectAnswer)
// answers.appendChild(button)
const answerBtns = document.getElementsByClassName('btn')
Array.from(answerBtns).forEach(btn => {
btn.addEventListener('click', () => {
if (btn.textContent === questions[questionNr].correct) {
message.style.display = 'flex'
correct.style.display = 'flex'
const stats = document.getElementById('stats')
stats.innerHTML = `${questionNr + 1}/${questions.length}`
} else {
message.style.display = 'flex'
wrong.style.display = 'flex'
stats.innerHTML = `${questionNr + 1}/${questions.length}`
}
nextButton.classList.remove('hide')
// answers.style.display = "none"
});
})
}
function resetState() {
nextButton.classList.add('hide')
while (answers.firstChild) {
answers.removeChild
(answers.firstChild)
}
}
function selectAnswer(e) {
const selectedButton = e.target
const correct = selectedButton.dataset.correct
setStatusClass(document.body, correct)
Array.from(answers.children).forEach(button => {
setStatusClass(button, button.dataset.correct)
})
if (questions.length > questionNr + 1) {
nextButton.classList.remove('hide')
} else {
startButton.innerHTML = "Restart Quiz"
startButton.classList.remove('hide')
}
}
function setStatusClass(element, correct) {
clearStatusClass(element)
if (correct) {
element.classList.add('correct')
} else {
element.classList.add('wrong')
}
}
function clearStatusClass(element) {
element.classList.remove('correct')
element.classList.remove('wrong')
}
<!-- language: lang-css -->
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
#container {
width: 100vw;
height: 100vh;
background-color: #081536;
display: flex;
justify-content: center;
align-items: center;
}
#content {
width: 700px;
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
}
#correct {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}
#correct h1, p {
color: white;
}
#wrong {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}
#wrong h1, p {
color: white;
}
#content img {
width: 400px;
height: 250px;
object-fit: cover;
}
.text {
color: white;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#next, #next-wr {
position: absolute;
width: 200px;
height: 40px;
color: white;
background-color: orange;
border: none;
border-radius: 10px;
}
.hide {
display: none;
}
#answers {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}
.btn {
width: 250px;
height: 50px;
outline: white;
border-radius: 5px;
border: 1px solid white;
color: white;
background: none;
cursor: pointer;
}
<!-- language: lang-html -->
<!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">
<title>CarQuiz</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="container">
<div id="message" class="hide">
<div id="correct">
<i class="fas fa-check-circle"></i>
<h1>Well done!</h1>
<p id="correct-answer"></p>
</div>
<div id="wrong">
<i class="fa-solid fa-circle-xmark"></i>
<h1>Wrong!</h1>
<p id="actual-answer"></p>
</div>
</div>
<div id="content">
<img src="" alt="" id="image">
<div class="text" class="hide">
<div id="stats"></div>
<div id="question" class="hide"></div>
<div id="answers" class="hide">
</div>
<div class="controls">
<button id="start-btn" class="start-btn btn">Start</button>
<button id="next-btn" class="hide-btn btn">Next</button>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
<!-- end snippet -->
</details>
# 答案1
**得分**: 1
以下是翻译后的内容,仅包括代码部分:
1. 给你的“下一题”按钮添加一个`hide`类,这样在加载测验后它就不会可见。
2. 在你的`style.css`文件中,给你的`.hide {...}`添加`!important`。稍后我会解释原因。
3. 在你的`setNextQuestion()`函数声明中,添加以下行:
```javascript
message.classList.add('hide');
这是必要的,因为你希望在加载新问题后隐藏消息("Well done!" / "Wrong!")。由于你将内联样式display:flex
添加到#message
中,它的特异性比.hide
设置的显示样式更高。这就是为什么需要添加!important
的原因。再次强调,这只是解决问题的最简单方法,也许不是最佳方法。
- 在你的
showQuestion(question)
函数声明中,将这个:
answers.innerHTML += `<button class="btn">${answer}</button>`
更改为这个:
answers.innerHTML += `<button class="answer-btn btn">${answer}</button>`;
- 在相同的函数中,将这个:
const answerBtns = document.getElementsByClassName('btn')
更改为这个:
const answerBtns = document.getElementsByClassName('answer-btn')
原因是.btn
类还在其他地方(start
, next
)使用,很可能你不希望收集与答案相关的按钮以外的按钮。
- 在上一行代码的下方,添加这行:
answers.classList.remove('hide');
这行代码是必要的,因为我们在第2步中所做的。.hide
的重要性已增加,没有这行代码,我们的问题将不会显示。
- 同样在相同的函数声明中,在将点击事件侦听器附加到各个
answerBtns
时,需要进行以下更改(具有// new
注释的部分是你需要添加的):
Array.from(answerBtns).forEach(btn => {
btn.addEventListener('click', () => {
message.classList.remove('hide'); // new
answers.classList.add('hide'); // new
if (btn.textContent === questions[questionNr].correct) {
message.style.display = 'flex';
correct.style.display = 'flex';
wrong.style.display = 'none'; // new
const stats = document.getElementById('stats');
stats.innerHTML = `${questionNr + 1}/${questions.length}`;
} else {
message.style.display = 'flex';
wrong.style.display = 'flex';
correct.style.display = 'none'; // new
stats.innerHTML = `${questionNr + 1}/${questions.length}`;
}
nextButton.classList.remove('hide');
});
});
添加这些的原因是,无论答案是否正确,我们都需要隐藏问题并显示答案消息(message
)。然后,在if / else中,我们显示相应的消息(正确/不正确),并隐藏另一个消息(不正确/正确)。
注意:
- 虽然这样可以实现你的意图(答案应该被隐藏,然后显示下一按钮),但它不会解决测验在完成后不显示最终结果/分数的问题。
- 一旦回答了最后一个问题,点击“下一题”按钮将触发控制台错误,因为在你的
const questions
中没有更多问题了。你可以在初始化showQuestion(question)
函数之后,引入一个简单的检查来解决这个问题。例如:
function showQuestion(question) {
if (typeof question.question === 'undefined') {
return false; // 此外,执行其他操作 - 警告用户,显示分数等等
}
// ... 你原来的代码的其余部分
}
英文:
Not the most optimal way of achieving what you need (there would have to be some rewriting to what you have right now, and you can focus on that later on), but this is one way of solving it.
- Add a
hide
class to yournext
button, so that it wouldn't be visible once the quiz is loaded. - In your
style.css
, add!important
to your.hide {...}
. I'll explain the reason for this later. - In your
setNextQuestion()
function declaration, add the following line:
message.classList.add('hide');
This is needed because you want to hide the message ("Well done!" / "Wrong!"), once the new questions are loaded. Since you're adding the inline display:flex
to your #message
, it has a greater specificity in comparison to what the .hide
sets for the display. That's why adding !important
was needed. Again, this is just the simplest way of solving it, and perhaps not the best.
- In your
showQuestion(question)
function declaration, change this
answers.innerHTML += `<button class="btn">${answer}</button>`
to this
answers.innerHTML += `<button class="answer-btn btn">${answer}</button>
- In the same function, change this
const answerBtns = document.getElementsByClassName('btn')
to this
const answerBtns = document.getElementsByClassName('answer-btn')
The reason - .btn
class is also used elsewhere (start
,next
), and, presumably, you don't want to collect those buttons as well as those related to the answers.
- Below the previous line of code, add this
answers.classList.remove('hide');
This line is needed, because of what we did in step 2. The importance of .hide
has been increased, and without this line, our questions would not be showing up.
- Also in the same function declaration, when attaching the click event listeners to individual
answerBtns
, you need to make the following changes (the ones with the// new
are what you need to add):
Array.from(answerBtns).forEach(btn => {
btn.addEventListener('click', () => {
message.classList.remove('hide'); // new
answers.classList.add('hide'); // new
if (btn.textContent === questions[questionNr].correct) {
message.style.display = 'flex'
correct.style.display = 'flex'
wrong.style.display = 'none'; // new
const stats = document.getElementById('stats')
stats.innerHTML = `${questionNr + 1}/${questions.length}`
} else {
message.style.display = 'flex'
wrong.style.display = 'flex'
correct.style.display = 'none'; // new
stats.innerHTML = `${questionNr + 1}/${questions.length}`
}
nextButton.classList.remove('hide')
// answers.style.display = "none"
});
})
The reason for adding these - regardless of whether the answer is correct or not, we need to hide the questions and show the answer holder (message
). Then, within the if / else, we show the appropriate message (correct / incorrect), and hide the other (incorrect / correct).
Some notes:
- while this will do what you intend ( (answers should be hidden, and next button displayed) and after clicking next button, answers get displayed again and the button hidden), it won't solve the issue with the quiz not displaying the end result / score, once it's done
- once the last question has been answered, clicking on the
next
button will trigger a console error, since there are no more questions within yourconst questions
. You can solve this by introducing a simple check right after theshowQuestion(question)
function is initialized. For example:
function showQuestion(question) {
if(typeof question.question === 'undefined') {
return false; // additionally, do something else - alert the user, show the score,etc
}
// ... the rest of your original code
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论