因此,我创建了一个测验应用程序,该应用程序可提取10个随机问题,其中三个不正确,一个正确答案可供选择。目前一切工作正常,除了我无法随机弹出答案。而且,我的意思是正确的答案始终位于提出的选择的底部。
我知道答案是Math.floor(Math.random()* ...),但老实说,我不知道将其放在哪里。我已经尝试了一切。我真的可以帮忙。
import React, { Component } from "react";
import "./App.css";
const API =
"https://opentdb.com/api.php?amount=10&category=20&difficulty=medium";
class App extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
score: []
};
}
componentDidMount() {
this.populateAppWithData();
}
populateAppWithData() {
fetch(API)
.then(response => response.json())
.then(data => this.setState({ results: data.results }))
.catch(error => console.error(error))
}
render() {
const { results } = this.state;
return (
<div className="App">
<h1>Quiz App</h1>
<TheCounter results={results}
Counter={this.state.score}
/>
</div>
);
}
}
class MythologyAnswers extends Component {
constructor(props) {
super(props);
this.state = {
answered: "",
isRight: null,
};
}
answerClicked(answer) {
const { hasAnswered, correct_answer } = this.props;
return event => {
const isRight = correct_answer === answer;
hasAnswered(isRight);
this.setState({
answered: answer,
isRight,
});
};
}
render() {
const { question, correct_answer, incorrect_answers } = this.props;
const { answered, isRight } = this.state;
return (
<div className="allAnswers">
{question}
{incorrect_answers && incorrect_answers
.concat(correct_answer)
.map(answer => (<div onClick={this.answerClicked(answer)}>{answer} </div>))}<br />
{answered && `You answered ${answered}`} {" "} <br />
<div className="correctAnswer"> {" "}{answered && isRight && "This is correct!"} </div> <br />
<div className="incorrectAnswer"> {" "}{answered && !isRight && `This is incorrect. The correct answer is ${this.props.correct_answer}`} {" "}</div>
</div>
)
}
}
class TheCounter extends Component {
constructor(props) {
super(props);
this.state = {
right: 0,
Counter: 0,
unanswered: 0,
};
}
questionAnswered = isRight => {
this.setState(({ Counter, right }) => ({
Counter: Counter + 1,
right: right + isRight,
}));
}
render() {
const { results } = this.props;
const { Counter } = this.state;
const unanswered = this.props.results && Counter;
if (unanswered >= 10) {
return <div className="theUnanswered"> You got {this.state.right} right out of {this.state.Counter} </div>;
}
const question = results[Counter];
return (
<div className="newQuestion">
<MythologyAnswers {...question} hasAnswered={this.questionAnswered} />
</div>
)
}
}
export default App;
答案 0 :(得分:1)
我们只需要在正确的位置应用随机化器即可。您使用.concat()
合并两个数组,因此在调用.map()
我已经设置了一些可以保留您已经编写的现有逻辑的东西。
这将有助于创建新的Arr并设置组件的标记。
renderChoices = () => {
const { correct_answer, incorrect_answers } = this.props;
let allAnswers = incorrect_answers
? incorrect_answers.concat(correct_answer)
: [];
//simple shuffle algorithm. Just inject your array and it'll pop out a new one.
function createRandom(arr) {
let myArr = [...arr]; //copy arr we pass in
let randomizedArr = []; //gets popuated by loop
while (myArr.length > 0) {
var randomIndex = Math.floor(Math.random() * myArr.length); //create random number
randomizedArr.push(myArr[randomIndex]); //add choice randomly to arr
myArr.splice(randomIndex, 1); //cut out a piece of the array then resart loop
}
//when loop has finished, return random array
return randomizedArr;
}
//call randomizer and get new Arr
let randomizedArr = createRandom(allAnswers);
//use .map to create markup with randomizedArr
return randomizedArr.map(answer => {
return <div onClick={this.answerClicked(answer)}>{answer}</div>;
});
};
因此,如果您要在render
中调用上述函数,它将为您创建答案集。
render() {
const { question } = this.props;
const { answered, isRight } = this.state;
return (
<div className="allAnswers">
{question}
{ this.renderChoices()}
<br />
{answered && `You answered ${answered}`} <br />
<div className="correctAnswer">
{answered && isRight && "This is correct!"}
</div>
<br />
<div className="incorrectAnswer">
{answered &&
!isRight &&
`This is incorrect. The correct answer is ${
this.props.correct_answer
}`}
</div>
</div>
);
}
清洁而不是太复杂:)
编辑:因此无需过多更改原始代码:
createRandom(arr) {
let myArr = [...arr]; //copy arr we pass in
let randomizedArr = []; //gets popuated by loop
while (myArr.length > 0) {
var randomIndex = Math.floor(Math.random() * myArr.length); //create random number
randomizedArr.push(myArr[randomIndex]); //add choice randomly to arr
myArr.splice(randomIndex, 1); //cut out a piece of the array then resart loop
}
//when loop has finished, return random array
return randomizedArr;
}
render() {
const { question, correct_answer, incorrect_answers } = this.props;
const { answered, isRight } = this.state;
const allAnswers =
incorrect_answers ? incorrect_answers.concat(correct_answer) : [];
const randomizedAnswers = this.createRandom(allAnswers)
return (
<div className="allAnswers">
{question}
{randomizedAnswers
.map(answer => (
<div onClick={this.answerClicked(answer)}>{answer} </div>
))}
<br />
{answered && `You answered ${answered}`} <br />
<div className="correctAnswer">
{answered && isRight && "This is correct!"}
</div>
<br />
<div className="incorrectAnswer">
{answered &&
!isRight &&
`This is incorrect. The correct answer is ${
this.props.correct_answer
}`}
</div>
</div>
);
}
因此,在编辑后的版本中,我们做了几件事:
createRandom()
的函数...它所做的只是
随机选择答案。render
中,我们创建了一个名为allAnswers的新变量,
concat()
incorrect_answers
和correct_answer
就像您一样
先前。如果没有定义incorrect_answers
,我们将使用
空数组[]作为默认值。randomizedAnswers
的新变量。我们称之为
createRandom()
并传入allAnswers
作为参数。它返回
供我们使用的随机数组。.map()
上方randomizedAnswers
创建您的
答案选择标记。答案 1 :(得分:0)
我将在获取数据后立即添加它。使用像Fisher-Yales这样的内联shuffle,您根本不需要修改结构。
const fisherYalesShuffle = (a) => {
let j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
}
但是,由于您通常希望将尽可能多的数据逻辑移至后端,因此您也应该考虑将其改组到那里。
答案 2 :(得分:0)
在下面的代码中,我想您正在尝试使用正确的答案连接错误的答案
incorrect_answers && incorrect_answers
.concat(correct_answer)
因此数组变为[incorrect_answers,incorrect_answers,incorrect_answers,correct_answer]
即正确答案在结尾
因此,如果您想在随机位置插入正确答案并假设有4个选项,则首先生成一个介于0到3之间的随机数
let randonIndex = Math.floor(Math.random() * 4)
然后在随机索引处插入正确答案
incorrect_answers && incorrect_answers
.splice(randomIndex, 0, correct_answer);
答案 3 :(得分:0)
您可以定义一个随机播放功能(这是Fisher-Yates(又名Knuth)随机播放):
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
然后在设置状态时仅应用该功能:
this.setState({ results: this.shuffle(data.results) })