Android 简单的do-while循环导致崩溃
我正在为Android开发一款智力竞赛游戏。我正在尝试生成尚未挑选的随机测验问题 (对不起,这里不合适) 您可以在Android 简单的do-while循环导致崩溃,android,while-loop,Android,While Loop,我正在为Android开发一款智力竞赛游戏。我正在尝试生成尚未挑选的随机测验问题 (对不起,这里不合适) 您可以在public void GenerateQuiz()中找到导致崩溃的do while。 该应用程序在没有do while功能的情况下运行良好,因此一定是出了问题。 它只是不断地在6/7/8上使应用程序崩溃。随机的问题,但它至少起作用。 它所做的只是检查这个随机问题是否已经被问过了 如果是->生成一个新的随机问题,直到它成为一个新问题&以前从未被问过 如果没有->那将是下一个问题 片段
public void GenerateQuiz()
中找到导致崩溃的do while。
该应用程序在没有do while功能的情况下运行良好,因此一定是出了问题。
它只是不断地在6/7/8上使应用程序崩溃。随机的问题,但它至少起作用。
它所做的只是检查这个随机问题是否已经被问过了
如果是->生成一个新的随机问题,直到它成为一个新问题&以前从未被问过
如果没有->那将是下一个问题
片段:
public void GenerateQuiz() {
do{
QuizID = ShuffleQuiz();
}while(CheckIfQuestionIsNew(QuizID)==false);
有三个困难:简单、中等和困难。他们每个人只有10个问题=总共30个问题。问题由随机生成的1-10个整数生成。
一旦用户完成10个问题,应用程序将把难度调到下一个最高点。示例:如果第10题(简单)回答正确,则难度将变为中等。一旦你完成第十道中等题,它将变为硬题
已更新
LogCat崩溃后的错误消息:
05-12 16:45:00.232 14067-14067/?E/ClockAlarmWidget﹕
[AlarmWidgetIdManager]getListItem():itemIndex=0,widgetID:1 05-12
16:45:00.232 14067-14067/? E/ClockAlarmWidget﹕ [AlarmWidgetIdManager]
getListItem():ItemIndex超过ListItemCount。itemIndex=1 05-12
16:45:00.232 14067-14067/? E/ClockAlarmWidget﹕ [AlarmWidgetIdManager]
getListItem():itemIndex=1,widgetID:1
资料来源:
boolean CheckIfQuestionIsNew(int element) {
List<Integer> ListDifficulty = new ArrayList<Integer>();
//#########GET ARRAYLIST#########
//Determine the Difficulty since each Difficulty got it's own arraylist.
if (QuizDifficulty==1){//Example: If Difficulty==1, copy it's arrays to the new list of array.
ListDifficulty.addAll(QuizIDsPassedD1);
}else if (QuizDifficulty==2){
ListDifficulty.addAll(QuizIDsPassedD2);
}else if (QuizDifficulty==3){
ListDifficulty.addAll(QuizIDsPassedD3);
}
if (ListDifficulty.contains(element))
return false;
//#########UPDATE ARRAYLIST#########
// If Question was not asked before then --> Add the new question ID to the arraylist
ListDifficulty.add(element);
//#########SAVE NEW ARRAYLIST#########
//Now it needs to determine the difficulty aggain to update its arraylist with the new items.
if (QuizDifficulty==1){
QuizIDsPassedD1.removeAll((QuizIDsPassedD1));//Remove All (Double Make Sure)
QuizIDsPassedD1.addAll(ListDifficulty);//Transfer new Arraylist to the difficultyies array list
}else if (QuizDifficulty==2){
QuizIDsPassedD2.removeAll((QuizIDsPassedD2));
QuizIDsPassedD2.addAll(ListDifficulty);
}else if (QuizDifficulty==3){
QuizIDsPassedD3.removeAll((QuizIDsPassedD3));
QuizIDsPassedD3.addAll(ListDifficulty);
}
return true;
}
布尔CheckIfQuestionIsNew(int元素){
List ListDemobility=新建ArrayList();
//#########获取阵列列表#########
//确定难度,因为每个难度都有自己的arraylist。
如果(QuizDifficulty==1){//示例:如果难度==1,则将其数组复制到新的数组列表中。
列表难度.addAll(QuizIDsPassedD1);
}else if(QuizDifficity==2){
列表难度.addAll(QuizIDsPassedD2);
}else if(QuizDifficity==3){
列表难度.addAll(QuizIDsPassedD3);
}
if(listDemobility.contains(元素))
返回false;
//#########更新ARRAYLIST#########
//如果之前未询问问题,则-->将新问题ID添加到arraylist
添加(元素);
//#########保存新ARRAYLIST#########
//现在,它需要确定使用新项更新其arraylist的难度。
如果(QuizDifficity==1){
QuizIDsPassedD1.removeAll((QuizIDsPassedD1));//全部删除(双重确认)
QuizIDsPassedD1.addAll(ListOfficity);//将新的Arraylist传输到困难数组列表
}else if(QuizDifficity==2){
QuizIDsPassedD2.移除所有((QuizIDsPassedD2));
QuizIDsPassedD2.addAll(列表难度);
}else if(QuizDifficity==3){
移除所有((QuizIDsPassedD3));
QuizIDsPassedD3.addAll(列表难度);
}
返回true;
}
改为使用下面的代码,然后检查CheckIfQuestionIsNew(QuizID)是否返回布尔值
do{
QuizID = ShuffleQuiz();
}while(CheckIfQuestionIsNew(QuizID));
在“DO/WHILE”循环中,大括号之间的代码至少执行一次。因此,如果您在其中遇到异常,这应该是因为您正在以不应该的方式进入循环。考虑使用AWS子句代替?< /P>
如果这是导致崩溃的大括号之间的一行,请添加该方法的代码
另外,请添加日志猫。问题在于
OutOfMemoryException
:
java.lang.OutOfMemoryError at java.util.ArrayList.addAll(ArrayList.java:194) at
de.hackert.wwequiz2014.QuizScreen.CheckIfQuestionIsNew(QuizScreen.java:49) at
private void bindAnswerToButton(Button button, Answer answer) {
int answerTextResId = answer.getAnswerTextResId();
button.setText(answerTextResId);
button.setOnClickListener(new AnswerClickListener(answer));
}
private void gotoNextQuestion() {
this.questionIndex++;
moveToQuestion(this.questionIndex);
}
这是由于在CheckIfQuestionIsNew()
方法中向ArrayList
中添加项造成的。很可能在那里的某个地方有一个无限循环,因为您必须向列表视图添加大量项(我说的是数千到数百万项),以获得OutOfMemoryException
。我会检查你的代码,但我认为你可能会更快地识别出确切的错误,因为你熟悉代码
编辑:
我想我发现了错误
你到底想在这里做什么:
ListDifficulty = QuizIDsPassedD1;
ListDifficulty.addAll(QuizIDsPassedD1);
对我来说没什么意义。这将与do/while循环一次又一次地重复列表中的所有项目,这很可能是罪魁祸首
编辑:
我在CheckIfQuestionIsNew()
中注释了您的代码:
因为你看不到什么特别的东西。它的成员变量包括问题文本的资源id、图像的资源id和答案的列表。此外,我还添加了一个addAnswer()
方法,方便地为问题添加答案
答案
类如下所示:
public class Question {
private final int imageResId;
private final int questionTextResId;
private final List<Answer> answers = new ArrayList<Answer>();
public Question(int questionTextResId, int imageResId) {
this.imageResId = imageResId;
this.questionTextResId = questionTextResId;
}
public Question addAnswer(int answerTextResId, boolean correct) {
Answer answer = new Answer(answerTextResId, correct);
this.answers.add(answer);
return this;
}
public int getQuestionTextResId() {
return questionTextResId;
}
public int getImageResId() {
return imageResId;
}
public List<Answer> getAnswers() {
return answers;
}
}
public class Answer {
private final int answerTextResId;
private final boolean correct;
public Answer(int answerTextResId, boolean correct) {
this.answerTextResId = answerTextResId;
this.correct = correct;
}
public int getAnswerTextResId() {
return answerTextResId;
}
public boolean isCorrect() {
return correct;
}
}
private void startGame() {
Collections.shuffle(this.easyQuestions);
Collections.shuffle(this.mediumQuesitons);
Collections.shuffle(this.hardQuestions);
this.questionQueue.clear();
this.questionQueue.addAll(this.easyQuestions);
this.questionQueue.addAll(this.mediumQuesitons);
this.questionQueue.addAll(this.hardQuestions);
this.questionIndex = 0;
moveToQuestion(0);
}
private void moveToQuestion(int index) {
// First we check if we have reached the end of the queue
if(index < this.questionQueue.size()) {
// If not we get the current question
Question question = this.questionQueue.get(index);
// Here we set the question text to the TextView
int questionTextResId = question.getQuestionTextResId();
this.textViewFrage.setText(questionTextResId);
// And here the question image to the ImageView.
int imageResId = question.getImageResId();
this.imageViewBild.setImageResource(imageResId);
// We get the answers from the question and create two count variables for convenience
List<Answer> answers = question.getAnswers();
int answerCount = answers.size();
int buttonCount = this.answerButtons.length;
// We start a loop through all the answer buttons
for(int i = 0; i < buttonCount; i++) {
// We get the current button from the Button[] which contains all the answer buttons
Button button = this.answerButtons[i];
// There might not be as many answers as there are buttons, that's what we check here
if(i < answerCount) {
// If there is an answer for this button make it visible
button.setVisibility(View.VISIBLE);
// We get the answer and bind to the button by calling bindAnswerToButton()
Answer answer = answers.get(i);
bindAnswerToButton(button, answer);
} else {
// If no answer exists for the Button we make it invisible.
button.setVisibility(View.GONE);
}
}
} else {
// We have reached the end of the queue
// You have to decide what happens when the game is won
Toast toast = Toast.makeText(this, R.string.game_won, Toast.LENGTH_SHORT);
toast.show();
}
}
private class AnswerClickListener implements View.OnClickListener {
private final Answer answer;
private AnswerClickListener(Answer answer) {
this.answer = answer;
}
@Override
public void onClick(View v) {
if(this.answer.isCorrect()) {
gotoNextQuestion();
} else {
// You have to decide what happens when someone picks the wrong answer
Toast toast = Toast.makeText(QuizScreen.this, R.string.toast_wrong_answer, Toast.LENGTH_SHORT);
toast.show();
}
}
}
正如您再次看到的,没有什么特别的,但是这里只有两个成员变量,一个是答案文本的资源id,另一个是布尔值,如果这个答案正确与否
在向您展示我改进的QuizScreen
活动的完整代码之前,我将向您解释我所做的所有更改及其工作原理。首先,我为您使用的所有视图创建了成员变量。您不应该经常调用findViewById()
。将引用保存在成员变量中时,不必再次调用findViewById()
:
private Button buttonAntwort1;
private Button buttonAntwort2;
private Button buttonAntwort3;
private Button buttonAntwort4;
private TextView textViewFrage;
private ImageView imageViewBild;
private Button[] answerButtons;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz_screen);
this.imageViewBild = (ImageView) findViewById(R.id.imageViewBild);
this.textViewFrage = (TextView) findViewById(R.id.textViewFrage);
this.buttonAntwort1 = (Button) findViewById(R.id.buttonAntwort1);
this.buttonAntwort2 = (Button) findViewById(R.id.buttonAntwort2);
this.buttonAntwort3 = (Button) findViewById(R.id.buttonAntwort3);
this.buttonAntwort4 = (Button) findViewById(R.id.buttonAntwort4);
this.answerButtons = new Button[] { this.buttonAntwort1, this.buttonAntwort2, this.buttonAntwort3, this.buttonAntwort4 };
createQuestions();
startGame();
}
如您所见,我还创建了一个按钮[]
,其中包含所有可用于回答问题的按钮。我的解决方案在这方面是完全灵活的。您可以有问题
和任意数量的答案
,每个问题
都可以有不同数量的答案
。您只需确保按钮[]
中有足够的按钮。如果您想让问题
有4个以上的答案,只需添加为
private void moveToQuestion(int index) {
// First we check if we have reached the end of the queue
if(index < this.questionQueue.size()) {
// If not we get the current question
Question question = this.questionQueue.get(index);
// Here we set the question text to the TextView
int questionTextResId = question.getQuestionTextResId();
this.textViewFrage.setText(questionTextResId);
// And here the question image to the ImageView.
int imageResId = question.getImageResId();
this.imageViewBild.setImageResource(imageResId);
// We get the answers from the question and create two count variables for convenience
List<Answer> answers = question.getAnswers();
int answerCount = answers.size();
int buttonCount = this.answerButtons.length;
// We start a loop through all the answer buttons
for(int i = 0; i < buttonCount; i++) {
// We get the current button from the Button[] which contains all the answer buttons
Button button = this.answerButtons[i];
// There might not be as many answers as there are buttons, that's what we check here
if(i < answerCount) {
// If there is an answer for this button make it visible
button.setVisibility(View.VISIBLE);
// We get the answer and bind to the button by calling bindAnswerToButton()
Answer answer = answers.get(i);
bindAnswerToButton(button, answer);
} else {
// If no answer exists for the Button we make it invisible.
button.setVisibility(View.GONE);
}
}
} else {
// We have reached the end of the queue
// You have to decide what happens when the game is won
Toast toast = Toast.makeText(this, R.string.game_won, Toast.LENGTH_SHORT);
toast.show();
}
}
private void bindAnswerToButton(Button button, Answer answer) {
int answerTextResId = answer.getAnswerTextResId();
button.setText(answerTextResId);
button.setOnClickListener(new AnswerClickListener(answer));
}
private class AnswerClickListener implements View.OnClickListener {
private final Answer answer;
private AnswerClickListener(Answer answer) {
this.answer = answer;
}
@Override
public void onClick(View v) {
if(this.answer.isCorrect()) {
gotoNextQuestion();
} else {
// You have to decide what happens when someone picks the wrong answer
Toast toast = Toast.makeText(QuizScreen.this, R.string.toast_wrong_answer, Toast.LENGTH_SHORT);
toast.show();
}
}
}
private void gotoNextQuestion() {
this.questionIndex++;
moveToQuestion(this.questionIndex);
}
public static class QuizScreen extends ActionBarActivity {
private final List<Question> easyQuestions = new ArrayList<Question>();
private final List<Question> mediumQuesitons = new ArrayList<Question>();
private final List<Question> hardQuestions = new ArrayList<Question>();
private final List<Question> questionQueue = new ArrayList<Question>();
private int questionIndex = 0;
private Button buttonAntwort1;
private Button buttonAntwort2;
private Button buttonAntwort3;
private Button buttonAntwort4;
private TextView textViewFrage;
private ImageView imageViewBild;
private Button[] answerButtons;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz_screen);
this.imageViewBild = (ImageView) findViewById(R.id.imageViewBild);
this.textViewFrage = (TextView) findViewById(R.id.textViewFrage);
this.buttonAntwort1 = (Button) findViewById(R.id.buttonAntwort1);
this.buttonAntwort2 = (Button) findViewById(R.id.buttonAntwort2);
this.buttonAntwort3 = (Button) findViewById(R.id.buttonAntwort3);
this.buttonAntwort4 = (Button) findViewById(R.id.buttonAntwort4);
this.answerButtons = new Button[] { this.buttonAntwort1, this.buttonAntwort2, this.buttonAntwort3, this.buttonAntwort4 };
createQuestions();
startGame();
}
private void createQuestions() {
newEasy(R.string.question1_text, R.drawable.question1_picture1)
.addAnswer(R.string.question1_answer1, false).addAnswer(R.string.question1_answer2, true)
.addAnswer(R.string.question1_answer3, false).addAnswer(R.string.question1_answer4, false);
newMedium(R.string.question2_text, R.drawable.question2_picture1)
.addAnswer(R.string.question2_answer1, false).addAnswer(R.string.question2_answer2, true)
.addAnswer(R.string.question2_answer3, false).addAnswer(R.string.question2_answer4, false);
newHard(R.string.question3_text, R.drawable.question3_picture1)
.addAnswer(R.string.question3_answer1, false).addAnswer(R.string.question3_answer2, true)
.addAnswer(R.string.question3_answer3, false).addAnswer(R.string.question3_answer4, false);
}
private Question newEasy(int questionTextResId, int imageResId) {
Question question = new Question(questionTextResId, imageResId);
this.easyQuestions.add(question);
return question;
}
private Question newMedium(int questionTextResId, int imageResId) {
Question question = new Question(questionTextResId, imageResId);
this.mediumQuesitons.add(question);
return question;
}
private Question newHard(int questionTextResId, int imageResId) {
Question question = new Question(questionTextResId, imageResId);
this.hardQuestions.add(question);
return question;
}
private void startGame() {
Collections.shuffle(this.easyQuestions);
Collections.shuffle(this.mediumQuesitons);
Collections.shuffle(this.hardQuestions);
this.questionQueue.clear();
this.questionQueue.addAll(this.easyQuestions);
this.questionQueue.addAll(this.mediumQuesitons);
this.questionQueue.addAll(this.hardQuestions);
this.questionIndex = 0;
moveToQuestion(0);
}
private void moveToQuestion(int index) {
if(index < this.questionQueue.size()) {
Question question = this.questionQueue.get(index);
int questionTextResId = question.getQuestionTextResId();
this.textViewFrage.setText(questionTextResId);
int imageResId = question.getImageResId();
this.imageViewBild.setImageResource(imageResId);
List<Answer> answers = question.getAnswers();
int answerCount = answers.size();
int buttonCount = this.answerButtons.length;
for(int i = 0; i < buttonCount; i++) {
Button button = this.answerButtons[i];
if(i < answerCount) {
button.setVisibility(View.VISIBLE);
Answer answer = answers.get(i);
bindAnswerToButton(button, answer);
} else {
button.setVisibility(View.GONE);
}
}
}
}
private void gotoNextQuestion() {
this.questionIndex++;
moveToQuestion(this.questionIndex);
}
private void bindAnswerToButton(Button button, Answer answer) {
int answerTextResId = answer.getAnswerTextResId();
button.setText(answerTextResId);
button.setOnClickListener(new AnswerClickListener(answer));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.quiz_screen, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class AnswerClickListener implements View.OnClickListener {
private final Answer answer;
private AnswerClickListener(Answer answer) {
this.answer = answer;
}
@Override
public void onClick(View v) {
if(this.answer.isCorrect()) {
gotoNextQuestion();
} else {
Toast toast = Toast.makeText(QuizScreen.this, R.string.toast_wrong_answer, Toast.LENGTH_SHORT);
toast.show();
}
}
}
}