Skip to content
This repository has been archived by the owner on Jan 18, 2025. It is now read-only.

Commit

Permalink
Add code breaker hint validation
Browse files Browse the repository at this point in the history
Closes #11
  • Loading branch information
powersagitar committed Jan 12, 2025
1 parent 9430f49 commit 878ac01
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;


public class CodeBreaker extends Scene {
private final MastermindAlgorithm solver;
private final GameBoard gameBoard = new GameBoard();
private final AtomicInteger correctCount = new AtomicInteger(2);
private final AtomicInteger misplacementCount = new AtomicInteger(2);
private final List<Code> guesses = new ArrayList<>(Mastermind.MAX_GUESSES);
private final List<Response> responses = new ArrayList<>(Mastermind.MAX_GUESSES);

private final GameBoard gameBoard = new GameBoard();
private final JButton proceedButton = new JButton("Proceed");
private final JPanel flowPanel = new JPanel(new FlowLayout());
private final JPanel controlPanel = new JPanel();
Expand Down Expand Up @@ -297,6 +302,7 @@ private void registerGuessHandler() {
// first guess
final Code firstGuess = solver.guess();
gameBoard.updateGuess(0, firstGuess.getColors());
guesses.add(firstGuess);

Mastermind.log.info("Guess 0: " + firstGuess);

Expand All @@ -308,18 +314,22 @@ private void registerGuessHandler() {
final int currentAttempt = solver.getAttempts();
final Tuple2<MastermindSolver.Status, Code> result = solver.guess(responseForPreviousGuess);

responses.add(responseForPreviousGuess);

Mastermind.log.info("Response: " + responseForPreviousGuess);
Mastermind.log.info("Solver status: " + result.first);

if (result.first == MastermindSolver.Status.Continue) {
Mastermind.log.info("Guess " + currentAttempt + ": " + result.second);

guesses.add(result.second);

gameBoard.updateHints(currentAttempt - 1, responseForPreviousGuess);
gameBoard.updateGuess(currentAttempt, result.second.getColors());
return;
}

new SecretCodePrompt(frame);
new SecretCodePrompt(frame, result.first, guesses, responses);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package mastermind.gui.scenes;

import mastermind.Mastermind;
import mastermind.core.Code;
import mastermind.core.Response;
import mastermind.core.solvers.MastermindSolver;
import mastermind.gui.panels.GameBoard;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class CodeBreakerResult extends Scene {
private final Code secretCode;
private final List<Code> guesses;
private final List<Response> responses;
private final List<Integer> invalidResponses;

public CodeBreakerResult(final JFrame frame,
final MastermindSolver.Status status,
final Code secretCode,
final List<Code> guesses,
final List<Response> responses) {
super(frame);

this.secretCode = secretCode;
this.guesses = guesses;
this.responses = responses;

this.invalidResponses = validateResponses();

if (!invalidResponses.isEmpty()) {
drawInvalidResponses();
} else {
final JLabel descriptionLabel;

if (status == MastermindSolver.Status.Win) {
descriptionLabel = new JLabel("Program successfully guessed the code.");
} else {
descriptionLabel = new JLabel("Program failed to guess the code.");
}

descriptionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
frame.add(descriptionLabel);

drawCorrectCode();
}

drawProceedButton();

refreshFrame();
}

private List<Integer> validateResponses() {
if (guesses.size() != responses.size()) {
throw new IllegalArgumentException("Guesses and responses must have the same size");
}

final List<Integer> invalidResponses = new ArrayList<>(Mastermind.CODE_LENGTH);

for (int i = 0; i < guesses.size(); ++i) {
final Response expectedResponse = new Response(secretCode, guesses.get(i));

if (!expectedResponse.equals(responses.get(i))) {
invalidResponses.add(i);
}
}

return invalidResponses;
}

private void drawProceedButton() {
final JButton button = new JButton("Proceed");
frame.add(button);

button.setAlignmentX(Component.CENTER_ALIGNMENT);

button.addActionListener(e -> new GameModeSelector(frame));
}

private void drawInvalidResponses() {
final String description = """
You did not provide the correct hints for the following guesses,
thus it is not possible to derive a win/lose endgame status:
""".replaceAll("\n", "<br>");

final JLabel descriptionLabel = new JLabel(
"<html><div align=\"center\">" + description + "</div></html>",
SwingConstants.CENTER);

descriptionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

frame.add(descriptionLabel);

final GameBoard invalidGameBoard = new GameBoard();

for (final int i : invalidResponses) {
invalidGameBoard.updateGuess(i, guesses.get(i).getColors());
invalidGameBoard.updateHints(i, responses.get(i));
}

final JPanel gameBoardPanel = invalidGameBoard.getBoardPanel();
gameBoardPanel.setAlignmentX(Component.CENTER_ALIGNMENT);

frame.add(gameBoardPanel);
}

private void drawCorrectCode() {
final List<Color> codeAWTColors = secretCode
.getColors()
.stream()
.map(GameBoard.codeColorToAwtColor::get)
.toList();

final JPanel codePanel = new JPanel(new FlowLayout());
frame.add(codePanel);

GameBoard.drawGuess(codePanel, codeAWTColors);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import mastermind.Mastermind;
import mastermind.core.Code;
import mastermind.core.Response;
import mastermind.core.solvers.MastermindSolver;
import mastermind.gui.panels.CodeCircle;
import mastermind.gui.panels.CodeInput;
import mastermind.gui.panels.GameBoard;
Expand All @@ -14,15 +16,21 @@

public class SecretCodePrompt extends Scene {
private Code secretCode = null;

public SecretCodePrompt(final JFrame frame) {
private final MastermindSolver.Status status;
private final List<Code> guesses;
private final List<Response> responses;

public SecretCodePrompt(final JFrame frame,
final MastermindSolver.Status status,
final List<Code> guesses,
final List<Response> responses) {
super(frame);

Mastermind.log.info("Creating CorrectCodePrompt scene");

final JLabel failureLabel = new JLabel("The program failed to guess the code.");
failureLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
frame.add(failureLabel);
this.status = status;
this.guesses = guesses;
this.responses = responses;

final JLabel promptLabel = new JLabel("Please enter the correct code:");
promptLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
Expand Down Expand Up @@ -94,8 +102,7 @@ private JButton drawProceedButton() {
return;
}

// TODO: transition to code breaker result
new GameModeSelector(frame);
new CodeBreakerResult(frame, status, secretCode, guesses, responses);
});

return proceedButton;
Expand Down

0 comments on commit 878ac01

Please sign in to comment.