show solutions
This commit is contained in:
2 files changed
+115
-56
No files matched your search
@@ -84,6 +84,20 @@ public class Question
|
|||||||
return this.answers;
|
return this.answers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAnswersString()
|
||||||
|
{
|
||||||
|
final StringBuilder sb;
|
||||||
|
sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (final String answer : this.answers)
|
||||||
|
{
|
||||||
|
sb.append(answer);
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a user's answer is correct.
|
* Checks whether a user's answer is correct.
|
||||||
* Matching is case-insensitive.
|
* Matching is case-insensitive.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import javafx.scene.layout.VBox;
|
|||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.TextArea;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
@@ -35,42 +36,45 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Quiz extends Application
|
public class Quiz extends Application
|
||||||
{
|
{
|
||||||
private static final int WIDTH = 800;
|
private static final int WIDTH_PIXELS = 800;
|
||||||
private static final int HEIGHT = 600;
|
private static final int HEIGHT_PIXELS = 600;
|
||||||
private static final int QUESTION_SPLIT = 0;
|
private static final int QUESTION_SPLIT_INDEX = 0;
|
||||||
private static final int COUNTER_STARTER = 0;
|
private static final int COUNTER_STARTER = 0;
|
||||||
private static final int ANSWER_SPLIT = 1;
|
private static final int ANSWER_SPLIT_INDEX = 1;
|
||||||
private static final int ONE_SECOND = 1;
|
private static final int SECOND = 1;
|
||||||
private static final int MIN_LENGTH = 2;
|
private static final int MIN_CHAR_LENGTH = 2;
|
||||||
private static final String DELIMITER = "\\|";
|
private static final String QUESTION_DELIMITER = "\\|";
|
||||||
private static final int NUM_QUESTIONS = 10;
|
private static final int NUM_QUESTIONS = 10;
|
||||||
private static final int START_TIME_SECS = 90;
|
private static final int START_TIME_SECONDS = 90;
|
||||||
|
private static final int INDEX_OFFSET = 1;
|
||||||
|
|
||||||
private static final Path QUIZ_FILE_PATH;
|
private static final Path QUIZ_FILE_PATH;
|
||||||
private static final List<Question> questions;
|
private static final List<Question> questions;
|
||||||
|
|
||||||
static {
|
static
|
||||||
questions = new ArrayList<>();
|
{
|
||||||
|
questions = new ArrayList<>();
|
||||||
QUIZ_FILE_PATH = Paths.get("data", "quiz.txt");
|
QUIZ_FILE_PATH = Paths.get("data", "quiz.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Question current;
|
private Question current;
|
||||||
private List<Question> quizQuestions;
|
private List<Question> quizQuestions;
|
||||||
|
|
||||||
private int currentQuestionIndex;
|
private int currentQuestionIndex;
|
||||||
private int correctCount;
|
private int correctCount;
|
||||||
private int wrongCount;
|
private int wrongCount;
|
||||||
private int remainingSeconds;
|
private int remainingSeconds;
|
||||||
|
private List<Question> wrongQuestions;
|
||||||
|
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
|
|
||||||
private Label questionLabel;
|
private Label questionLabel;
|
||||||
private Label feedbackLabel;
|
private Label feedbackLabel;
|
||||||
private Label statusLabel;
|
private Label statusLabel;
|
||||||
private TextField answerField;
|
private TextField answerField;
|
||||||
private Button submitButton;
|
private Button submitButton;
|
||||||
private Button startButton;
|
private Button startButton;
|
||||||
private Button playAgainButton;
|
private Button playAgainButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and loads quiz questions from a file.
|
* Reads and loads quiz questions from a file.
|
||||||
@@ -93,8 +97,8 @@ public class Quiz extends Application
|
|||||||
while ((line = reader.readLine()) != null)
|
while ((line = reader.readLine()) != null)
|
||||||
{
|
{
|
||||||
final String[] parts;
|
final String[] parts;
|
||||||
parts = line.split(DELIMITER);
|
parts = line.split(QUESTION_DELIMITER);
|
||||||
if (parts.length < MIN_LENGTH)
|
if (parts.length < MIN_CHAR_LENGTH)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -102,20 +106,18 @@ public class Quiz extends Application
|
|||||||
final String questionText;
|
final String questionText;
|
||||||
final String[] answers;
|
final String[] answers;
|
||||||
|
|
||||||
questionText = parts[QUESTION_SPLIT];
|
questionText = parts[QUESTION_SPLIT_INDEX];
|
||||||
answers = parts[ANSWER_SPLIT].split(",");
|
answers = parts[ANSWER_SPLIT_INDEX].split(",");
|
||||||
|
|
||||||
questions.add(new Question(
|
questions.add(new Question(
|
||||||
questionText,
|
questionText,
|
||||||
answers
|
answers
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
} catch (final FileNotFoundException e)
|
||||||
catch (final FileNotFoundException e)
|
|
||||||
{
|
{
|
||||||
System.out.println("Unable to open file: " + path);
|
System.out.println("Unable to open file: " + path);
|
||||||
}
|
} catch (final IOException e)
|
||||||
catch (final IOException e)
|
|
||||||
{
|
{
|
||||||
System.out.println("Error reading file: " + path);
|
System.out.println("Error reading file: " + path);
|
||||||
}
|
}
|
||||||
@@ -131,17 +133,17 @@ public class Quiz extends Application
|
|||||||
{
|
{
|
||||||
final VBox root;
|
final VBox root;
|
||||||
root = new VBox();
|
root = new VBox();
|
||||||
root.setPrefSize(WIDTH, HEIGHT);
|
root.setPrefSize(WIDTH_PIXELS, HEIGHT_PIXELS);
|
||||||
|
|
||||||
questionLabel = new Label("Click \"Start quiz\" to begin.");
|
questionLabel = new Label("Click \"Start quiz\" to begin.");
|
||||||
feedbackLabel = new Label();
|
feedbackLabel = new Label();
|
||||||
statusLabel = new Label();
|
statusLabel = new Label();
|
||||||
|
|
||||||
answerField = new TextField();
|
answerField = new TextField();
|
||||||
answerField.setPromptText("Type your answer here");
|
answerField.setPromptText("Type your answer here");
|
||||||
|
|
||||||
submitButton = new Button("Submit");
|
submitButton = new Button("Submit");
|
||||||
startButton = new Button("Start quiz");
|
startButton = new Button("Start quiz");
|
||||||
playAgainButton = new Button("Play again");
|
playAgainButton = new Button("Play again");
|
||||||
|
|
||||||
answerField.setDisable(true);
|
answerField.setDisable(true);
|
||||||
@@ -150,20 +152,20 @@ public class Quiz extends Application
|
|||||||
playAgainButton.setVisible(false);
|
playAgainButton.setVisible(false);
|
||||||
|
|
||||||
root.getChildren().addAll(
|
root.getChildren().addAll(
|
||||||
questionLabel,
|
questionLabel,
|
||||||
answerField,
|
answerField,
|
||||||
submitButton,
|
submitButton,
|
||||||
feedbackLabel,
|
feedbackLabel,
|
||||||
statusLabel,
|
statusLabel,
|
||||||
startButton,
|
startButton,
|
||||||
playAgainButton
|
playAgainButton
|
||||||
);
|
);
|
||||||
|
|
||||||
final Scene scene;
|
final Scene scene;
|
||||||
scene = new Scene(root);
|
scene = new Scene(root);
|
||||||
|
|
||||||
scene.getStylesheets().add(
|
scene.getStylesheets().add(
|
||||||
getClass().getResource("style.css").toExternalForm()
|
getClass().getResource("style.css").toExternalForm()
|
||||||
);
|
);
|
||||||
|
|
||||||
readQuestions(QUIZ_FILE_PATH);
|
readQuestions(QUIZ_FILE_PATH);
|
||||||
@@ -193,13 +195,15 @@ public class Quiz extends Application
|
|||||||
/**
|
/**
|
||||||
* getRunnable creates a Runnable
|
* getRunnable creates a Runnable
|
||||||
* lambda that is used to enter an answer on button click.
|
* lambda that is used to enter an answer on button click.
|
||||||
|
*
|
||||||
* @return Runnable to manage answer
|
* @return Runnable to manage answer
|
||||||
*/
|
*/
|
||||||
private Runnable getRunnable()
|
private Runnable getRunnable()
|
||||||
{
|
{
|
||||||
final Runnable submitAction;
|
final Runnable submitAction;
|
||||||
|
|
||||||
submitAction = () -> {
|
submitAction = () ->
|
||||||
|
{
|
||||||
if (current == null)
|
if (current == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -220,10 +224,10 @@ public class Quiz extends Application
|
|||||||
if (current.validateAnswer(cleaned))
|
if (current.validateAnswer(cleaned))
|
||||||
{
|
{
|
||||||
correctCount++;
|
correctCount++;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
{
|
||||||
wrongCount++;
|
wrongCount++;
|
||||||
|
this.wrongQuestions.add(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentQuestionIndex++;
|
currentQuestionIndex++;
|
||||||
@@ -239,15 +243,18 @@ public class Quiz extends Application
|
|||||||
*/
|
*/
|
||||||
private void startGame()
|
private void startGame()
|
||||||
{
|
{
|
||||||
correctCount = COUNTER_STARTER;
|
((VBox) feedbackLabel.getParent()).getChildren().removeIf(node -> node instanceof TextArea);
|
||||||
wrongCount = COUNTER_STARTER;
|
|
||||||
remainingSeconds = START_TIME_SECS;
|
correctCount = COUNTER_STARTER;
|
||||||
|
wrongCount = COUNTER_STARTER;
|
||||||
|
remainingSeconds = START_TIME_SECONDS;
|
||||||
currentQuestionIndex = COUNTER_STARTER;
|
currentQuestionIndex = COUNTER_STARTER;
|
||||||
|
|
||||||
feedbackLabel.setText("");
|
feedbackLabel.setText("");
|
||||||
questionLabel.setText("");
|
questionLabel.setText("");
|
||||||
|
|
||||||
quizQuestions = new ArrayList<>(questions);
|
wrongQuestions = new ArrayList<>();
|
||||||
|
quizQuestions = new ArrayList<>(questions);
|
||||||
Collections.shuffle(quizQuestions);
|
Collections.shuffle(quizQuestions);
|
||||||
|
|
||||||
if (quizQuestions.size() > NUM_QUESTIONS)
|
if (quizQuestions.size() > NUM_QUESTIONS)
|
||||||
@@ -261,15 +268,16 @@ public class Quiz extends Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
timeline = new Timeline(
|
timeline = new Timeline(
|
||||||
new KeyFrame(Duration.seconds(ONE_SECOND), event -> {
|
new KeyFrame(Duration.seconds(SECOND), event ->
|
||||||
remainingSeconds--;
|
|
||||||
updateStatusLabel();
|
|
||||||
|
|
||||||
if (remainingSeconds <= COUNTER_STARTER)
|
|
||||||
{
|
{
|
||||||
endGame("Time's up!");
|
remainingSeconds--;
|
||||||
}
|
updateStatusLabel();
|
||||||
})
|
|
||||||
|
if (remainingSeconds <= COUNTER_STARTER)
|
||||||
|
{
|
||||||
|
endGame("Time's up!");
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
timeline.setCycleCount(Timeline.INDEFINITE);
|
timeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
timeline.play();
|
timeline.play();
|
||||||
@@ -315,7 +323,7 @@ public class Quiz extends Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int displayIndex;
|
final int displayIndex;
|
||||||
displayIndex = Math.min(currentQuestionIndex + ONE_SECOND, quizQuestions.size());
|
displayIndex = Math.min(currentQuestionIndex + SECOND, quizQuestions.size());
|
||||||
|
|
||||||
statusLabel.setText(
|
statusLabel.setText(
|
||||||
displayIndex + "/" + quizQuestions.size() +
|
displayIndex + "/" + quizQuestions.size() +
|
||||||
@@ -339,13 +347,50 @@ public class Quiz extends Application
|
|||||||
answerField.setDisable(true);
|
answerField.setDisable(true);
|
||||||
current = null;
|
current = null;
|
||||||
|
|
||||||
final String finalScore;
|
final String finalScore;
|
||||||
|
final TextArea solutions;
|
||||||
|
|
||||||
|
if (wrongCount > COUNTER_STARTER)
|
||||||
|
{
|
||||||
|
final StringBuilder allSolutions;
|
||||||
|
|
||||||
|
allSolutions = new StringBuilder();
|
||||||
|
|
||||||
|
for (final Question question : wrongQuestions)
|
||||||
|
{
|
||||||
|
final StringBuilder solution;
|
||||||
|
solution = new StringBuilder();
|
||||||
|
|
||||||
|
solution.append("Question: ");
|
||||||
|
solution.append(question.getQuestion());
|
||||||
|
solution.append("\n");
|
||||||
|
solution.append("Answer: ");
|
||||||
|
solution.append(question.getAnswersString());
|
||||||
|
solution.append("\n\n");
|
||||||
|
|
||||||
|
allSolutions.append(solution.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
solutions = new TextArea(allSolutions.toString());
|
||||||
|
solutions.setEditable(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solutions = null;
|
||||||
|
}
|
||||||
|
|
||||||
finalScore = reason +
|
finalScore = reason +
|
||||||
"\n\nFinal score:" +
|
"\n\nFinal score:" +
|
||||||
"\nCorrect: " + correctCount +
|
"\nCorrect: " + correctCount +
|
||||||
"\nWrong: " + wrongCount;
|
"\nWrong: " + wrongCount;
|
||||||
|
|
||||||
|
if (solutions != null)
|
||||||
|
{
|
||||||
|
final VBox root;
|
||||||
|
root = (VBox) feedbackLabel.getParent();
|
||||||
|
root.getChildren().add(root.getChildren().indexOf(feedbackLabel) + INDEX_OFFSET, solutions);
|
||||||
|
}
|
||||||
|
|
||||||
feedbackLabel.setText(finalScore);
|
feedbackLabel.setText(finalScore);
|
||||||
|
|
||||||
questionLabel.setText("Game over.");
|
questionLabel.setText("Game over.");
|
||||||
|
|||||||
Reference in new issue
Block a user