Issue
I am making a quiz application in Java and am using JUnit to test my methods. Right now, my src folder has one main folder. The main folder further has two packages, model and UI. The model package contains one class called QuizQuestions and contains the modeling of data. The UI package has 2 classes, Quiz and Main. Quiz class provides print statements to the QuizQuestions class and the Main class has the Main method. Here is the code:
QuizQuestions class (model):
package model;
import ui.Quiz;
import java.util.*;
public class QuizQuestions {
Map<String, String> questionsAndAnswers;
Quiz quiz;
// REQUIRES: the map data structure, specifically the field named questionsAndAnswers
// MODIFIES: nothing
// EFFECTS: creates a new linked hashmap by the name questionsAndAnswers
public QuizQuestions() {
questionsAndAnswers = new LinkedHashMap<>();
}
// REQUIRES: nothing
// MODIFIES: this
// EFFECTS: adds the questions and answers to the linked list in an ordered format
public LinkedHashMap<String, String> entireQuestionsList() {
questionsAndAnswers.put("Purpose of spinning jenny in the Industrial Revolution ",
"\na)A device for making cloth\nb)A device for storing energy\nc)A steam engine\nd)A water pump\n\n");
questionsAndAnswers.put("A city NOT founded by the Romans ", "\na)Alexandria\nb)Berlin\nc)London\nd)None\n\n");
questionsAndAnswers.put("Number of wives Henry VIII had ", "\na)1\nb)6\nc)3\nd)2\n");
questionsAndAnswers.put("Country of origin of Zoroastrianism ", "\na)Brazil\nb)Egypt\nc)Persia\nd)India\n\n");
questionsAndAnswers.put("The person who captured Moscow for the last time in history ",
"\na)No one\nb)Hitler\nc)Napoleon\nd)Ogedei Khan\n\n");
questionsAndAnswers.put("First time the Winter Olympics were held in ",
"\na)1896\nb)1900\nc)1888\nd)1924\n\n");
questionsAndAnswers.put("Number of chapters in the Olympic Charter ", "\na)5\nb)6\nc)7\nd)8\n\n");
questionsAndAnswers.put("Designer of the trophy of FIFA Women’s World Cup? ",
"\na)William Sawaya\nb)Formiga\nc)Marta\nd)Sun Wen\n\n");
questionsAndAnswers.put("The Mission Hills World Cup is related to ", "\na)Golf\nb)Polo\nc)TT\nd)Chess\n\n");
questionsAndAnswers.put("Number of players who have reached the 100-goal mark in EPL ",
"\na)5\nb)10\nc)28\nd)30\n\n");
questionsAndAnswers.put("Location of the Spanish Steps ", "\na)Rome\nb)Lisbon\nc)Madrid\nd)Barcelona\n\n");
questionsAndAnswers.put("Total number of provinces in Canada ", "\na)5\nb)10\nc)30\nd)20\n\n");
questionsAndAnswers.put("A popular Middle Eastern dish ", "\na)Pasta\nb)Dolma\nc)Pizza\nd)Curry\n\n");
questionsAndAnswers.put("Location of the Chocolate Hills ",
"\na)Pakistan\nb)Japan\nc)Philippines\nd)India\n\n");
questionsAndAnswers.put("The tallest building amongst the following is ",
"\na)The Shard\nb)Burj Khalifa\nc)Skytree\nd)Moscow Tower\n\n");
return (LinkedHashMap<String, String>) questionsAndAnswers;
}
// REQUIRES: questionsAndAnswers linked list should not be empty
// MODIFIES: nothing
// EFFECTS: gets the questions and answers from the linked list
// and displays one question and its corresponding answers one after
// the other while providing the user the option to enter his/her answer
// for each question.
public ArrayList<String> askQuestionsOneByOne() {
quiz = new Quiz();
Set<Map.Entry<String, String>> entry = questionsAndAnswers.entrySet();
ArrayList<String> userAnswer = new ArrayList<>();
for (Object o : entry) {
System.out.println(o);
String answer = quiz.askUser();
userAnswer.add(answer);
}
return userAnswer;
}
// REQUIRES: nothing
// MODIFIES: this
// EFFECTS: adds the correct answers of all the questions to
// a linked list and returns that list.
public ArrayList<String> storeCorrectAnswers() {
ArrayList<String> correctAnswers = new ArrayList<>();
correctAnswers.add("a");
correctAnswers.add("a");
correctAnswers.add("b");
correctAnswers.add("c");
correctAnswers.add("c");
correctAnswers.add("d");
correctAnswers.add("b");
correctAnswers.add("a");
correctAnswers.add("a");
correctAnswers.add("d");
correctAnswers.add("a");
correctAnswers.add("b");
correctAnswers.add("b");
correctAnswers.add("c");
correctAnswers.add("b");
return correctAnswers;
}
// REQUIRES: storeCorrectAnswers and askQuestionsOneByOne is not empty
// MODIFIES: nothing
// EFFECTS: stores the answers obtained from storeCorrectAnswers and
// askQuestionsOneByOne into 2 new linked lists and compares both of
// them. Whenever the answer at a particular index in both the lists
// is the same, the score of the user is incremented by 1 and the
// total score is returned at the end of the method.
public int compareAnswers() {
ArrayList<String> userAnswers = storeCorrectAnswers();
ArrayList<String> correctAnswers = askQuestionsOneByOne();
int score = 0;
for (int i = 0; i < userAnswers.size(); i++) {
if (userAnswers.get(i).equals(correctAnswers.get(i))) {
score++;
}
}
return score;
}
// REQUIRES: the value of the score variable from compareAnswers()
// MODIFIES: nothing
// EFFECTS: displays the score of the user and according to the score,
// displays a message informing the user about how good the score is.
public void displayScoreAndPerformanceMessage() {
quiz = new Quiz();
int score = compareAnswers();
quiz.printScore();
if (score < 5 && score > 0) {
quiz.messageForScoreLessThanFive();
askUserToPlayAgain();
} else if (score >= 5 && score < 10) {
quiz.messageForScoreMoreThanFiveAndLessThanTen();
askUserToPlayAgain();
} else if (score >= 10 && score != 15) {
quiz.messageGorScoreMoreThanTenAndLessThanFifteen();
askUserToPlayAgain();
} else {
quiz.messageForPerfectScore();
}
}
// REQUIRES: the list of quiz questions and the user score
// MODIFIES: converts the user answer to lower case if he/she enters
// the response in uppercase.
// EFFECTS: gives the user the option to play the quiz again
// and based on the answer, starts the quiz from scratch or exits the program
public void askUserToPlayAgain() {
quiz = new Quiz();
String response = quiz.askUserForPlayingAgain();
while (response.equalsIgnoreCase("y")) {
entireQuestionsList();
displayScoreAndPerformanceMessage();
askUserToPlayAgain();
}
if (response.equalsIgnoreCase("n")) {
quiz.thankYouMessage();
System.exit(1);
} else {
quiz.errorMessage();
askUserToPlayAgain();
}
}
}
Quiz class (UI):
package ui;
import model.QuizQuestions;
import java.util.Scanner;
public class Quiz {
Quiz qz;
public Quiz() {
qz = new Quiz();
}
public void displayGreeting() {
System.out.println("Welcome to the quiz application!\n\nHere are the quiz questions.");
}
// REQUIRES: nothing
// MODIFIES: nothing
// EFFECTS: allows the user to enter their answer for
// each question and returns that answer.
public String askUser() {
Scanner sc = new Scanner(System.in);
return sc.next();
}
// REQUIRES: score from the compareAnswers method in QuizQuestions
// MODIFIES: nothing
// EFFECTS: displays the score of the user on the screen
public void printScore() {
QuizQuestions qq = new QuizQuestions();
int score = qq.compareAnswers();
System.out.println("Your score is " + score);
}
// EFFECTS: displays a particular message if the user score is less than 5
public void messageForScoreLessThanFive() {
System.out.println("Looks like your general knowledge is weak. Try to read books!");
}
// EFFECTS: displays a particular message if the user score is more than 5
// but less than 10.
public void messageForScoreMoreThanFiveAndLessThanTen() {
System.out.println("You are doing good! There is still potential to improve though!");
}
// EFFECTS: displays a particular message if the user score is more than 10
// but less than 15.
public void messageGorScoreMoreThanTenAndLessThanFifteen() {
System.out.println("You are awesome! Your score is better than most of the people!");
}
// EFFECTS: displays a particular message if the user score is equal to 15.
public void messageForPerfectScore() {
System.out.println("Perfect score! Congratulations!");
}
// EFFECTS: asks the user whether he/she wants to play again and prompts them for a response.
public String askUserForPlayingAgain() {
System.out.println("Do you want to play the quiz again? (Y)es/(N)o?\n");
Scanner scanner = new Scanner(System.in);
return scanner.next();
}
// EFFECTS: displays a thank-you message at the end of the program.
public void thankYouMessage() {
System.out.println("Thanks for playing!\n");
}
// EFFECTS: displays an error message if the user does not select a right option
public void errorMessage() {
System.out.println("Please enter a valid response.\n");
}
}
Main method:
package ui;
import model.QuizQuestions;
public class Main {
public static void main(String[] args) {
QuizQuestions qq = new QuizQuestions();
qq.entireQuestionsList();
qq.askQuestionsOneByOne();
qq.compareAnswers();
qq.displayScoreAndPerformanceMessage();
qq.askUserToPlayAgain();
}
}
All my tests are passing but when I try to run my program from the main method, it doesn't run. Where am I going wrong?
Thank you
Solution
There were a few issues with your code. I will summarize them here:
- Remove the qz = new Quiz() line in the constructor of the Quiz class, this led to a Stack Overflow as it kept running the constructor again and again.
- The main other issue in you code is instead of saving the score value for printing and other usage, it kept initializing new Quizes and running compareAnswers() in these new instances. You need to save the score value in the Quiz class, and use that stored value.
- Lastly, in the askQuestionsOneByOne() you are returning the user answers, but never use them. Instead, in compareAnswers() you are again initializing new Lists.
You can fix the Quiz class by adding a score field (first code example below). Then, in the main class, when you run compareAnswers(), which returns the score, save that to the current quiz (second code example below). Subsequently, when you need the score, for example in the displayScoreAndPerformance() call, retrieve it from the quiz object. Same for the printScore() in the Quiz object. For this to work, you need to add getter and setter for the Quiz object in the QuizQuestions.
Lastly, you need to parameterize the compareAnswers to accept the user's answers, and in the main method pass the result of the askQuestionsOneByOne() to the compareAnswers().
public class Quiz {
int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public class Main {
public static void main(String[] args) {
ArrayList<String> userAnswers = new ArrayList<>();
QuizQuestions qq = new QuizQuestions();
qq.entireQuestionsList();
userAnswers = qq.askQuestionsOneByOne();
qq.getQuiz().setScore(qq.compareAnswers(userAnswers));
qq.displayScoreAndPerformanceMessage();
qq.askUserToPlayAgain();
}
}
public void displayScoreAndPerformanceMessage() {
// quiz = new Quiz();
//int score = compareAnswers();
int score = quiz.getScore();
quiz.printScore();
if (score < 5 && score > 0) {
quiz.messageForScoreLessThanFive();
askUserToPlayAgain();
} else if (score >= 5 && score < 10) {
quiz.messageForScoreMoreThanFiveAndLessThanTen();
askUserToPlayAgain();
} else if (score >= 10 && score != 15) {
quiz.messageGorScoreMoreThanTenAndLessThanFifteen();
askUserToPlayAgain();
} else {
quiz.messageForPerfectScore();
}
}
public void printScore() {
// QuizQuestions qq = new QuizQuestions();
// int score = qq.compareAnswers();
System.out.println("Your score is " + score);
}
public class QuizQuestions {
Map<String, String> questionsAndAnswers;
Quiz quiz;
public Quiz getQuiz() {
return quiz;
}
public void setQuiz(Quiz quiz) {
this.quiz = quiz;
}
public int compareAnswers(ArrayList<String> userAnswers) {
ArrayList<String> correctAnswers = storeCorrectAnswers();
int score = 0;
for (int i = 0; i < userAnswers.size(); i++) {
if (userAnswers.get(i).equals(correctAnswers.get(i))) {
score++;
}
}
return score;
}
Answered By - kosmasd
Answer Checked By - Clifford M. (JavaFixing Volunteer)