I am currently working on an object-oriented mental math program using Java Swing. Since I am relatively new to the object oriented principals of design, it'd be nice to know how well the code conforms to OOP principals, and what kinds of improvements to make, including:
- If it would be possible to introduce subclasses, especially for the
MathQuestionGenerator
(e.g.AdditionQuestionGenerator
,SubtractionQuestionGenerator
etc.) - If there is a better way to handle the score rather than returning
-1
when the session has not completed yet
Overview of Project: The following code is essentially a model that a GUI can use to handle mental math sessions. The code will generate 20 random questions, and keeps track of time and number of wrong questions. It can work with 5 types of sessions (addition, subtraction, multiplication, division, or mixed) and 3 difficulty settings (easy, medium, difficult)
MathSession.java - Represents a mental math session where the user answers 20 questions.
The GUI will call startSession()
and proceed to submitAnswer()
until all 20 questions are completed. Then the GUI can get the user's calculated score with getFinalScore()
public class MathSession {
public SessionType type;
public SessionDifficulty difficulty;
public MathQuestionGenerator generator;
public MathQuestion currentQuestion;
public int progress;
public int numberWrongQuestions;
public final int numberOfQuestions = 20;
private long startTime;
private long endTime;
// Returns whether or not the session has completed
public boolean isComplete() {
return progress == numberOfQuestions;
}
// Calculates and returns a final score
// Returns -1 when the session has not been completed yet
public int getFinalScore() {
if (!isComplete()) {
return -1;
} else {
double secondsElapsed = (endTime - startTime)/ 1000;
double penalty = numberWrongQuestions * 5;
int score = (int) Math.round(secondsElapsed + penalty);
return score;
}
}
public MathSession(SessionType operator, SessionDifficulty difficulty) {
this.type = operator;
this.difficulty = difficulty;
this.generator = new MathQuestionGenerator(operator, difficulty);
}
// Starts the session
public void startSession() {
startTime = System.currentTimeMillis();
progress = 0;
numberWrongQuestions = 0;
currentQuestion = generator.generateQuestion();
}
// The user submits an answer, it is either right (returns true) or wrong (returns false)
public boolean submitAnswer(int answer) {
if (answer == currentQuestion.correct) {
progress++;
if (isComplete()) {
endTime = System.currentTimeMillis();
} else {
currentQuestion = generator.generateQuestion();
}
return true;
} else {
numberWrongQuestions++;
return false;
}
}
}
MathQuestionGenerator.java - Generates mental math questions given a difficulty and session type.
public class MathQuestionGenerator {
public SessionType type;
public SessionDifficulty difficulty;
private Random random;
public MathQuestionGenerator(SessionType type, SessionDifficulty difficulty) {
this.type = type;
this.difficulty = difficulty;
random = new Random();
}
// Generates a random math question given the session type and difficulty
public MathQuestion generateQuestion() {
int num1Max, num2Max, num1, num2, min = 1;
MathOperator operation = null;
if (type == SessionType.Addition) {
operation = MathOperator.Addition;
} else if (type == SessionType.Subtraction) {
operation = MathOperator.Subtraction;
} else if (type == SessionType.Multiplication) {
operation = MathOperator.Multiplication;
} else if (type == SessionType.Division) {
operation = MathOperator.Division;
} else if (type == SessionType.Mixed) {
// Choose an operation randomly
operation = random.nextInt(1) == 0 ?
(random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) :
(random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
}
if (operation == MathOperator.Addition || operation == MathOperator.Subtraction) {
if (difficulty == SessionDifficulty.Easy) {
num1Max = 12;
num2Max = 12;
} else if (difficulty == SessionDifficulty.Medium) {
num1Max = 100;
num2Max = 100;
} else {
num1Max = 10000;
num2Max = 10000;
}
} else {
if (difficulty == SessionDifficulty.Easy) {
num1Max = 12;
num2Max = 12;
} else if (difficulty == SessionDifficulty.Medium) {
num1Max = 100;
num2Max = 10;
} else {
num1Max = 100;
num2Max = 100;
}
}
num1 = min + random.nextInt(num1Max - min);
num2 = min + random.nextInt(num2Max - min);
MathQuestion question;
if (type == SessionType.Addition) {
question = new MathQuestion(MathOperator.Addition, num1, num2, num1 + num2);
} else if (type == SessionType.Subtraction) {
question = new MathQuestion(MathOperator.Subtraction, num1 + num2, num1, num2);
} else if (type == SessionType.Multiplication) {
question = new MathQuestion(MathOperator.Multiplication, num1, num2, num1 * num2);
} else {
question = new MathQuestion(MathOperator.Division, num1 * num2, num2, num1);
}
return question;
}
}
MathQuestion.java - Represents a math question with two numbers, an operation and a correct answer
public class MathQuestion {
public MathOperator operator;
public int number1;
public int number2;
public int correct;
public MathQuestion(MathOperator operator, int number1, int number2, int correct) {
this.operator = operator;
this.number1 = number1;
this.number2 = number2;
this.correct = correct;
}
}
MathOperator.java
public enum MathOperator {
Addition,
Subtraction,
Multiplication,
Division
}
SessionType.java
public enum SessionType {
Addition,
Subtraction,
Multiplication,
Division,
Mixed
}
SessionDifficulty.java
public enum SessionDifficulty {
Easy,
Medium,
Hard
}