Is there a way to make the correct
button hard coded in the Question component render between the mapped incorrect buttons to prevent the correct answer from always being the first button rendered with every question? Or a way to map through both correct and incorrect answers to display the answers with random positions, the question array comes from the API in this form:
{
question: "The words and originate from the languages of which country?",
correctAnswer: "India",
incorrectAnswers: ["Papua New Guinea", "Ethiopia", "China"]
}
const [request, setRequest] = React.useState([])
React.useEffect (() => {
fetch('https://opentdb.com/api.php?amount=5')
.then(res => res.json())
.then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({question, correct_answer, incorrect_answers}))))
}, [])
console.log(request)
const questionElements = request.map(req => {
return (
<Question
question = {req.question}
correct_answer ={req.correct_answer}
incorrect_answers = {req.incorrect_answers}
scoreFunction = {scoreFunction}
// disabled = {disable}
/>
)
})
// Question Component
const incorrectAnswers = props.incorrect_answers.map(ans => {
return (
<button className ="button">{ans}</button>
)
})
return(
<div className = "question-div">
<h1 className = "question">{props.question}</h1>
<div className = "answerBlock">
<button
disabled = {disable}
className ="button correct"
onClick = {() => {
props.scoreFunction()
setDisable(true)}}>{props.correct_answer} </button>
{incorrectAnswers}
</div>
<hr />
</div>
)
CodePudding user response:
You can put all answers to the same array, sort data inside it and then generate buttons.
This shows a simple shuffle function for arrays: How to randomize (shuffle) a JavaScript array?
Example:
const correct_answer = 'correct'
const incorrect_answers = ['incorrect 1','incorrect 2','incorrect 3']
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
const all_answers = shuffle([correct_answer, ...incorrect_answers])
console.log(all_answers)
So your code should look like this:
const [request, setRequest] = React.useState([])
React.useEffect (() => {
fetch('https://opentdb.com/api.php?amount=5')
.then(res => res.json())
.then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({question, correct_answer, incorrect_answers, all_answers: [correct_answer, ...incorrect_answers]}))))
}, [])
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
console.log(request)
const questionElements = request.map(req => {
return (
<Question
question = {req.question}
correct_answer ={req.correct_answer}
incorrect_answers = {req.incorrect_answers}
scoreFunction = {scoreFunction}
// disabled = {disable}
/>
)
})
// Question Component
const allAnswers = shuffle(props.all_answers).map(ans => {
if(ans !== props.correct_answer) {
return (
<button className ="button">{ans}</button>
)
}
return (
<button
disabled = {disable}
className ="button correct"
onClick = {() => {
props.scoreFunction()
setDisable(true)}}
>{props.ans}</button>
)
})
return(
<div className = "question-div">
<h1 className = "question">{props.question}</h1>
<div className = "answerBlock">{allAnswers }</div>
<hr />
</div>
)
CodePudding user response:
How about something like this?
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) min;
}
const incorrect_answers_count = props.incorrect_answers.length;
const correct_answer_random_index = getRandomArbitrary(1, incorrect_answers_count) - 1;
const combined_answers = props.incorrect_answers.splice(correct_answer_random_index, 0, props.correct_answer);
const answers = combined_answers.map((ans, index) => {
return (
<button key={"answer-button-" index} className ="button">{ans}</button>
)
})
Not sure why you want to have the correct button different, because the user can actually see this in the browser. But if you do, you can predefined the buttons and only then do the mapping.