Solution for Programming Exercise 5.7
This page contains a sample solution to one of the exercises from Introduction to Programming Using Java.
Exercise 5.7:
Rewrite the program from the previous exercise so that it administers a quiz with several different kinds of questions. In the previous exercise, you used a class to represent addition questions. For this exercise, you will use the following interface, or an equivalent abstract class, to represent the more general idea of a question that has an integer as its answer:
public interface IntQuestion { public String getQuestion(); public int getCorrectAnswer(); }
You can make the AdditionQuestion class implement the interface simply by adding "implements IntQuestion" to its definition. Write a similar class to represent subtraction questions. When creating a subtraction problem, you should make sure that the answer is not negative.
For the new program, use an array of type IntQuestion[] to hold the quiz questions. Include some addition questions and some subtraction questions in the quiz. You can also add a couple non-math questions, including this one, created as an anonymous class:
IntQuestion bigQuestion = new IntQuestion() { public String getQuestion() { return "What is the answer to the ultimate question " + " of life, the universe, and everything?"; } public int getCorrectAnswer() { return 42; } };
Where the solution to the previous exercise used an array of AdditionQuestion to store addition problems, the new program has to store questions of various types. An array of type IntQuestion[] can hold any object that implements the IntQuestion interface. That includes objects of type AdditionQuestion as long as we modify that class so that it implements IntQuestion. But it can also include other types of objects. For one thing, we want to have subtraction problems. We can implement subtraction with a class very similar to the class for addition questions:
class SubtractionQuestion implements IntQuestion {
private int a, b; // The numbers in the problem.
public SubtractionQuestion() { // constructor
a = (int)(Math.random() * 50 + 1);
b = (int)(Math.random() * 50);
if (a - b < 0) { // swap a and b so answer won't be negative
int temp = a;
a = b;
b = temp;
}
}
public String getQuestion() {
return "What is " + a + " - " + b + " ?";
}
public int getCorrectAnswer() {
return a - b;
}
}
The exercise asks for subtraction problems for which the answer is not negative. There are a number of ways to accomplish that. For example, you could use a loop that would continue selecting random values for a and b as long as a - b < 0. You could choose b and the answer randomly and then compute a as a = answer + b. In my solution, I just swap the values of a and b when a - b < 0.
Creating the quiz becomes a more difficult problem in the new version, since we need to use several different kinds of questions. In my solution, the first seven questions are math problems. For each math problem, the program decides randomly whether to make it an addition question or a subtraction question. The last three questions are created using anonymous classes, just like the example given in the exercise. You can see my solution below.
But the three anonymous classes in my solution have a lot in common: They are the same except for the particular string that is used to ask the question and the particular number that is the correct answer. A better approach would probably have been to create a class to represent such questions:
public class GeneralQuestion implements IntQuestion { private String question; private int answer; public GeneralQuestion( String question, int answer ) { this.question = question; this.answer = answer; } public String getQuestion() { return question; } public int getCorrectAnswer() { return answer; } }
In that case, the subroutine for creating the quiz would become:
private static void createQuiz() { questions = new IntQuestion[10]; for ( int i = 0; i < 7; i++ ) { if (Math.random() < 0.5) questions[i] = new AdditionQuestion(); else questions[i] = new SubtractionQuestion(); } questions[7] = new GeneralQuestion( "How many states are there in the United States?", 50 ); questions[8] = new GeneralQuestion( "In what year did the First World War begin?", 1914 ); questions[9] = new GeneralQuestion( "What is the answer to the ultimate question " + "of life, the universe, and everything?", 42 ); }
Aside from the declaration of the array questions and the routine for creating the quiz, everything else in the program can be exactly as it was in the previous exercise. (However, I did change the format of the output in gradeQuiz() to make it look better for longer questions.)
In my solution, just to keep everything in one file, I nested the interface and the two classes that implement it inside the main program class. It would probably be better style to put them all in their own files.
import textio.TextIO; /** * This program creates, administers, and grades a quiz made up of ten questions, * where each question has an integer answer. The quiz includes some simple addition * problems, some subtraction problems, and some non-math questions. */ public class GeneralQuiz { // -------------------- Nested classes and interface ----------------------- interface IntQuestion { public String getQuestion(); public int getCorrectAnswer(); } static class AdditionQuestion implements IntQuestion { private int a, b; // The numbers in the problem. public AdditionQuestion() { // constructor a = (int)(Math.random() * 50 + 1); b = (int)(Math.random() * 50); } public String getQuestion() { return "What is " + a + " + " + b + " ?"; } public int getCorrectAnswer() { return a + b; } } static class SubtractionQuestion implements IntQuestion { private int a, b; // The numbers in the problem. public SubtractionQuestion() { // constructor a = (int)(Math.random() * 50 + 1); b = (int)(Math.random() * 50); if (b > a) { // swap a and b so answer won't be negative int temp = a; a = b; b = temp; } } public String getQuestion() { return "What is " + a + " - " + b + " ?"; } public int getCorrectAnswer() { return a - b; } } // -------------------- The Program -------------------------------------- private static IntQuestion[] questions; // The questions for the quiz private static int[] userAnswers; // The user's answers to the ten questions. public static void main(String[] args) { System.out.println(); System.out.println("Welcome to the quiz"); System.out.println(); System.out.println("There are some math questions and a few non-math"); System.out.println("questions, but the answer to every question is"); System.out.println("an integer."); System.out.println(); createQuiz(); administerQuiz(); gradeQuiz(); } /** * Creates the array of objects that holds the quiz questions */ private static void createQuiz() { questions = new IntQuestion[10]; for ( int i = 0; i < 7; i++ ) { if (Math.random() < 0.5) questions[i] = new AdditionQuestion(); else questions[i] = new SubtractionQuestion(); } questions[7] = new IntQuestion() { public String getQuestion() { return "How many states are there in the United States?"; } public int getCorrectAnswer() { return 50; } }; questions[8] = new IntQuestion() { public String getQuestion() { return "In what year did the First World War begin?"; } public int getCorrectAnswer() { return 1914; } }; questions[9] = new IntQuestion() { public String getQuestion() { return "What is the answer to the ultimate question " + "of life, the universe, and everything?"; } public int getCorrectAnswer() { return 42; } }; } /** * Asks the user each of the ten quiz questions and gets the user's answers. * The answers are stored in an array, which is created in this subroutine. */ private static void administerQuiz() { userAnswers = new int[10]; for (int i = 0; i < 10; i++) { int questionNum = i + 1; System.out.printf("Question %2d: %s ", questionNum, questions[i].getQuestion()); userAnswers[i] = TextIO.getlnInt(); } } /** * Shows all the questions, with their correct answers, and computes a grade * for the quiz. For each question, the user is told whether they got * it right. */ private static void gradeQuiz() { System.out.println(); System.out.println("Here are the correct answers:"); System.out.println(); int numberCorrect = 0; int grade; for (int i = 0; i < 10; i++) { System.out.println("Question number " + (i+1) + ":"); System.out.println(" " + questions[i].getQuestion()); System.out.println(" Correct answer: " + questions[i].getCorrectAnswer()); if ( userAnswers[i] == questions[i].getCorrectAnswer() ) { System.out.println(" You were CORRECT."); numberCorrect++; } else { System.out.println(" You said " + userAnswers[i] + ", which is INCORRECT."); } System.out.println(); } grade = numberCorrect * 10; System.out.println(); System.out.println("You got " + numberCorrect + " questions correct."); System.out.println("Your grade on the quiz is " + grade); System.out.println(); } } // end class GeneralQuiz