Home > Software design >  Making Answer button render with random indexes
Making Answer button render with random indexes

Time:07-19

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.

  • Related