GUI

by geoog on July 30th, 2010
No notes
Syntax: Java
Show lines - Hide lines - Show in textbox - Download
package aufgabe_4;
 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
 
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
 
/**
 * This class models the GUI for the Mastermind game.
 */
public class MastermindView extends JFrame {
 
    /**
     * This stores whether the game has ended.
     * The game can end by running out of turns, the user cheating or
     * the combination being guessed correctly.
     */
    private boolean gameOver = false;
 
    /**
     * This is the Mastermind game that the GUI corresponds to.
     */
    private MastermindModel theGame = new MastermindModel();
 
    /**
     * This is the label on top of the game board that shows status updates.
     */
    private JPanel descriptionPanel = new JPanel();
 
    /**
     * This is the game board with the panels for moves and ratings.
     */
    private JPanel gameBoard = new JPanel();
 
    /**
     * This is the label separting the game board from the secret panel.
     */
    private JPanel secretLabel = new JPanel();
 
    /**
     * This is the secret panel where the secret can be stored while the
     * machine "guesses" or where the secret is shown at the end of a game
     * where the user guessed.
     */
    private JPanel secretPanel = new JPanel();
 
    /**
     * This holds all the circles representing colors in ColorCodes, including
     * the panel for the secret code. Thus, moveCircles.length is one more than
     * MastermindGame.MAX_MOVES.
     * 
     * The circles in the secretPanel are in
     * moveCircles[MastermindGame.MAX_MOVES].
     */
    private JPanel[][] moveCircles =
        new JPanel[MastermindGame.MAX_MOVES + 1][MastermindGame.NUMBER_SLOTS];
 
    /**
     * This holds the circles used for rating.
     */
    private JPanel[][] ratingCircles =
        new JPanel[MastermindGame.MAX_MOVES][MastermindGame.NUMBER_SLOTS];
 
    /**
     * This defines the width of a JPanel that represents a code circle.
     */
    private static final int MOVE_CIRCLE_WIDTH =
        240 / MastermindGame.NUMBER_SLOTS;
 
    /**
     * This defines the width of a JPanel that represents a rating circle.
     */
    private static final int RATING_CIRCLE_WIDTH = (MOVE_CIRCLE_WIDTH / 2) - 4;
 
    /**
     * This is the Color for the background of both the descriptionPanel and
     * the secretLabel.
     */
    private static final Color LABEL_COLOR = new Color(205, 104, 57);
 
    /**
     * This Color is the background for the game board and the secret panel.
     */
    private static final Color GAMEBOARD_COLOR = new Color(200, 215, 250);
 
    /**
     * This constant represents a circle that isn't set.
     */
    public static final Color SLOT_NOT_SET = Rating.RATING_COLORS[2];
 
    /**
     * This black one-pixel LineBorder is used for look and feel.
     */
    private static final Border LINE = new LineBorder(Color.BLACK);
 
    /**
     * This one-pixel EmptyBorder is used for look and feel.
     */
    private static final Border EMPTY = new EmptyBorder(1, 1, 1, 1);
 
    /**
     * This contains enum objects representing the buttons used to play the
     * game. Its purpose is managing control flow in the method
     * createButton(ButtonOperation). The order of the elements determines
     * the order of the buttons in the GUI (but not their respective function).
     */
    enum ButtonOperation {
 
        /**
         * The button to make the next move/evaluate the machine's guess.
         */
        MOVE,
 
        /**
         * The button to switch the user
         */
        SWITCH,
 
        /**
         * Tht button to start a new game with the same guesser.
         */
        NEW,
 
        /**
         * The button to quit the program.
         */
        QUIT
    }
 
    /**
     * This represents the possible different game situations.
     * It is used to control the updates on the descriptionPanel.
     */
    enum GameSit {
 
        /**
         * The user has to set the secret panel before the machine starts
         * "guessing".
         */
        USER_MOVE_SET_SECRET_PANEL,
 
        /**
         * The user has to enter a rating for the machine's move.
         */
        USER_MOVE_MACHINE_GUESSES,
 
        /**
         * The user has to enter a guess.
         */
        USER_MOVE_USER_GUESSES,
 
        /**
         * The ColorCode entered by the user in the current move is invalid.
         */
        INVALID_COLORCODE,
 
        /**
         * The user cheated.
         */
        USER_CHEATED,
 
        /**
         * The user won.
         */
        USER_WON,
 
        /**
         * The user lost.
         */
        USER_LOST
 
    }
 
    /**
     * Create a new MastermindView.
     * The constructor builds all the elements of the game and structures them.
     */
    public MastermindView() {
        setTitle("Mastermind - have fun!");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
 
        //create and add the label on top of the window showing status texts
        changeTextLabel(descriptionPanel,
                getDescr(GameSit.USER_MOVE_USER_GUESSES),
                LABEL_COLOR);
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.gridx = 0;
        constraints.weightx = 1.0;
        constraints.weighty = 0.0;
        add(descriptionPanel, constraints);
 
        //create and add the game board
        resetGameBoard();
        add(gameBoard, constraints);
 
        //label the secret board
        changeTextLabel(secretLabel, "The secret", LABEL_COLOR);
        constraints.weighty = 1.0;
        add(secretLabel, constraints);
 
        //create the panel where the secret is shown after a user-is-guessing
        //game or the user will set the secret in a machine-is-guessing
        //game
        secretPanel = resetMovePanel(secretPanel, MastermindGame.MAX_MOVES);
        constraints.fill = GridBagConstraints.NONE;
        constraints.weighty = 0.0;
        constraints.insets = new Insets(0, 0, 2, 0);
        add(secretPanel, constraints);
 
        //create and add the buttons on the bottom used to make moves etc.
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.anchor = GridBagConstraints.PAGE_END;
        constraints.insets = new Insets(0, 1, 1, 1);
        add(createButtonPanel(), constraints);
 
        //adjust the frame's size and location, lock the size and show the frame
        pack();
        setLocationRelativeTo(null);
        setResizable(false);
        setVisible(true);
    }
 
    /**
     * Changes the text shown in a JPanel.
     * This method is used to update the descriptionPanel.
     * 
     * @param textPanel The JPanel that is being changed.
     * @param text The new text.
     * @param background The background for the JPanel.
     */
    private void changeTextLabel(JPanel textPanel, String text,
            Color background) {
 
        //remove everything from the JPanel, then build it up
        //the Layout is set so the JPanel will stretch when this JFrame calls
        //pack()
        textPanel.removeAll();
        JLabel addMe = new JLabel(text);
        addMe.setHorizontalAlignment(JLabel.CENTER);
 
        CompoundBorder theBorder = new CompoundBorder(EMPTY, LINE);
        addMe.setBorder(theBorder);
 
        addMe.setFont(new Font("Arial", Font.BOLD, 16));
        textPanel.add(addMe);
        textPanel.setLayout(new GridLayout());
 
        textPanel.setBackground(background);
    }
 
    /**
     * Resets the gameBoard to the state it is in when the game starts.
     */
    private void resetGameBoard() {
 
        //remove everything, then build the board fresh
        gameBoard.removeAll();
        JPanel move = null;
        JPanel codePanel = null;
        JPanel ratingPanel = null;
        gameBoard.setLayout(new GridLayout(0, 1));
        int height = 0;
 
        //add a panel for the code and the rating for each move
        for (int i = 0; i < MastermindGame.MAX_MOVES; i++) {
            move = new JPanel();        
            codePanel = new JPanel();
            move.setLayout(new BoxLayout(move, BoxLayout.X_AXIS));
 
            codePanel = resetMovePanel(codePanel, i);
            ratingPanel = resetRatingPanel(i);
 
            height += codePanel.getPreferredSize().getHeight();
            move.add(codePanel);
            move.add(ratingPanel);            
            gameBoard.add(move);
        }
 
        //adjust the preferred size
        gameBoard.setPreferredSize(new Dimension(
                MastermindGame.NUMBER_SLOTS * MOVE_CIRCLE_WIDTH, height));
    }
 
    /**
     * Resets a panel with circles for color codes.
     * This is used while adding code circles to the game board and building
     * and resetting the secret panel.
     * 
     * @param move The panel that will be reset.
     * @param row The row the panel is in.
     * @return Returns the freshly reset panel.
     */
    private JPanel resetMovePanel(JPanel move, int row) {
 
        //empty the panel and build it fresh
        move.removeAll();
        move.setLayout(new GridLayout(1,
                MastermindGame.NUMBER_SLOTS + 1, 3, 3));
        move.setBackground(GAMEBOARD_COLOR);
 
        JPanel circle = null;
 
        //add it to moveCircles in the place it belongs
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            circle = createMoveCircle();
            moveCircles[row][i] = circle;
            move.add(circle);            
        }
 
        //adjust for size
        int width = (MOVE_CIRCLE_WIDTH) * MastermindGame.NUMBER_SLOTS;
        move.setPreferredSize(new Dimension(width + 6, MOVE_CIRCLE_WIDTH + 6));
 
        //giving the panel a border
        CompoundBorder panelBorder = new CompoundBorder(EMPTY, LINE);
        panelBorder = new CompoundBorder(panelBorder, EMPTY);
        move.setBorder(panelBorder);
 
        return move;
    }
 
    /**
     * Resets a panel with circles for ratings.
     * This is used while adding rating circles to the game board.
     * 
     * @param move The panel that will be reset.
     * @param row The row the panel is in.
     * @return Returns the freshly reset panel.
     */
    private JPanel resetRatingPanel(int row) {
 
        //empty the panel and build it anew
        JPanel ratingSlots = new JPanel();
        ratingSlots.setBackground(GAMEBOARD_COLOR);
        int rows = (MastermindGame.NUMBER_SLOTS / 2)
                        + (MastermindGame.NUMBER_SLOTS % 2);
        ratingSlots.setLayout(new GridLayout(rows, 2));
        ratingSlots.setPreferredSize(new Dimension(MOVE_CIRCLE_WIDTH,
                MOVE_CIRCLE_WIDTH));
 
        JPanel circle = null;
 
        //add the rating circles to the panel
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            circle = createRatingCircle();
            ratingCircles[row][i] = circle;
            ratingSlots.add(circle);
        }
 
        CompoundBorder panelBorder = new CompoundBorder(EMPTY, LINE);
        panelBorder = new CompoundBorder(panelBorder, EMPTY);
        ratingSlots.setBorder(panelBorder);
 
        return ratingSlots;
    }
 
    /**
     * Creates a new circle representing a color on the game board.
     * This also adds the required MouseAdapter to the circle.
     * 
     * @return The created circle as a JPanel.
     */
    private JPanel createMoveCircle() {
 
        //put a circle the size of a color code circle on a new panel
        final JPanel circle = new JPanel() {
 
            @Override
            public void paintComponent(Graphics g) {
                g = (Graphics2D) g;
                g.fillOval(0, 2, MOVE_CIRCLE_WIDTH - 4, MOVE_CIRCLE_WIDTH - 4);
            }
        };
 
        //get a popupmenu with the valid Colors for the circle
        final CodePopupMenu codePopup = new CodePopupMenu(circle);
 
 
        //add a MouseAdapter responding to right clicks
        circle.addMouseListener(new MouseAdapter() {
 
            @Override
            public void mousePressed(MouseEvent event) {
 
                //only react to right clicks
                if ((event.isMetaDown()) && (!gameOver)) {
 
                    /*
                     * in case the machine is guessing, only show the panel for
                     * the circles in the secret panel
                     * if the user is guessing, show it for the circles for the
                     * current move
                     */
                    if (theGame.isMachineGuessing()) {
 
                        //only show the popup for the secret panel before
                        //the machine made its first move
                        if (circleBelongsToPanel(circle, moveCircles,
                                MastermindGame.MAX_MOVES)
                                && (moveCircles[0][0].getForeground()
                                        == SLOT_NOT_SET)) {
                            codePopup.show(event.getComponent(), event.getX(),
                                    event.getY());
                        }
                    } else {
 
                        //only show the popup for the current move
                        if (circleBelongsToPanel(circle, moveCircles,
                                theGame.getMoveCount())) {
                            codePopup.show(event.getComponent(), event.getX(),
                                    event.getY());
                        }
                    }
                }
            }
        });
 
        circle.setForeground(SLOT_NOT_SET);
        circle.setSize(new Dimension(MOVE_CIRCLE_WIDTH, MOVE_CIRCLE_WIDTH));
        return circle;
    }
 
    /**
     * This creates a rating circle analogously to createMoveCircle().
     * 
     * @param row The row which the circle belongs to
     * @return
     */
    private JPanel createRatingCircle() {
 
        //put a circle the size of a rating circle on a new panel
        final JPanel circle = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                g.fillOval(2, 2, RATING_CIRCLE_WIDTH - 4,
                        RATING_CIRCLE_WIDTH - 4);
            }
        };
 
        final RatingPopupMenu codePopup = new RatingPopupMenu(circle);
 
        //add the MouseAdapter; make it only respond to right clicks while
        //the machine is guessing with the circle lieing in the right row
        circle.addMouseListener(new MouseAdapter() {
 
            @Override
            public void mousePressed(MouseEvent event) {
                if ((event.isMetaDown())
                        && (!gameOver)
                        && (theGame.isMachineGuessing())
                        && (circleBelongsToPanel(circle, ratingCircles,
                                theGame.getMoveCount()))) {
                    codePopup.show(event.getComponent(), event.getX(),
                            event.getY());
                }
            }
        });
 
        circle.setForeground(SLOT_NOT_SET);      
        circle.setSize(new Dimension(RATING_CIRCLE_WIDTH,
                RATING_CIRCLE_WIDTH));
 
        return circle;
    }
 
    /**
     * Creates the button panel.
     * 
     * @return The newly created button panel.
     */
 
    private JPanel createButtonPanel() {
        JButton addMe = null;
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(1, 0, 3, 0));
 
        //for each operation, create a button and add it to the panel
        for (ButtonOperation op : ButtonOperation.values()) {
            addMe = createButton(op);
            buttonPanel.add(addMe);
        }
 
        return buttonPanel;
    }
 
    /**
     * Creates a button with the tooltip and ActionListener required by its
     * operation.
     * 
     * @param op The operation which the button has to perform when clicked.
     * @return The created button.
     */
    private JButton createButton(ButtonOperation op) {
        JButton button = null;
 
        switch(op) {
            case MOVE:
                button = new JButton("move");
                button.setToolTipText("Makes a move; rates the guess if the "
                        + "user is guessing or evaluates the machine's guess "
                        + "according to the user's rating in machine-mode.");
                button.addActionListener(createMoveListener());
                break;
 
            case NEW:
                button = new JButton("new");
                button.setToolTipText("Starts a new game without changing who "
                        + "is guessing.");
                button.addActionListener(createNewListener());
                break;
 
            case SWITCH:
                button = new JButton("switch");
                button.setToolTipText("Switches between user and machine as "
                        + "guesser and starts a new game.");
                button.addActionListener(createSwitchListener());
                break;
 
            case QUIT:
                button = new JButton("quit");
                button.setToolTipText("Ends the program.");
                button.addActionListener(new ActionListener() {
 
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.exit(0);
                    }
                });
                break;
 
            default:
                break;
        }
 
        button.setFont(new Font("Dialog", Font.PLAIN, 14));
        return button;
    }
 
    /**
     * Creates an ActionListener for the "move"-button.
     * 
     * @return Returns the adjusted ActionListener.
     */
    private ActionListener createMoveListener() {
        return new ActionListener() {
 
            @Override
            public void actionPerformed(ActionEvent e) {
                int moveCount = theGame.getMoveCount();
 
                //only react if the game is still going on
                if (!(moveCount < MastermindGame.MAX_MOVES) || gameOver) {
                    return;
                }
 
                boolean machineIsGuessing = theGame.isMachineGuessing();
 
                //check if the machine is guessing; if so, make a machine
                //move, else let the user play
                if (machineIsGuessing) {
                    makeMachineMove();
                } else {
 
                    //check whether the user has entered a valid color combo
                    //already; if so rate it, else update the description panel
                    if (!validateCode(moveCount)) {
                        updateDescr(getDescr(GameSit.INVALID_COLORCODE));
                        return;
                    }
 
                    //rate the user's guess
                    ColorCode humanGuess = readColorCode(moveCount);
                    theGame.humanMove(humanGuess);
                    moveCount = theGame.getMoveCount();
                    Rating moveRating = theGame.getRating(moveCount - 1);
                    updateRatingPanel(moveCount - 1, moveRating);
 
                    //update the description panel according to the user's
                    //performance
                    if (MastermindModel.SUCCESS.isEqualTo(moveRating)) {
                        updateDescr(getDescr(GameSit.USER_WON));
                        updateMovePanel(MastermindGame.MAX_MOVES,
                                theGame.getSecret());
                    } else if (moveCount == MastermindGame.MAX_MOVES) {
                        updateDescr(getDescr(GameSit.USER_LOST));
                        updateMovePanel(MastermindGame.MAX_MOVES,
                                theGame.getSecret());
                    }
                }
 
                repaint();
            }
        };
    }
 
    /**
     * Makes a machine move.
     */
    private void makeMachineMove() {
        int moveCount = theGame.getMoveCount();
 
        //if the secret code has been set, check whether the first move has
        //been chosen; if not, do so, else process ratings
        if (readColorCode(MastermindGame.MAX_MOVES).isValidCode()) {
            updateDescr(getDescr(GameSit.USER_MOVE_MACHINE_GUESSES));
            ColorCode firstMove = theGame.getGameState(0);
 
            if (firstMove == null) {
                firstMove = theGame.machineMove();
                updateMovePanel(moveCount, firstMove);
            } else {
                ColorCode curGuess = theGame.getGameState(moveCount);
                Rating curRating = readRating(moveCount);
                theGame.processEval(curGuess, curRating.getBlacks(),
                        curRating.getWhites());
 
                //if the machine's guess was successful, say "yay"
                //else, remove possibilities that are no longer possible
                if (MastermindModel.SUCCESS.isEqualTo(curRating)) {
                    updateDescr(getDescr(GameSit.USER_LOST));
                } else {                
                    moveCount = theGame.getMoveCount();
 
                    //if it was the last turn, say "aww machine fail"
                    //else, get a new machine guess
                    if (moveCount == MastermindGame.MAX_MOVES) {
                        updateDescr(getDescr(GameSit.USER_WON));
                    } else {
                        curGuess = theGame.machineMove();
                        //if there are possibilities left, print the first
                        //one else, the user cheated - call him a cheater
                        if (curGuess == null) {
                            updateDescr(getDescr(GameSit.USER_CHEATED));
                        } else {
                            updateMovePanel(moveCount, curGuess);
                        }
                    }
                }
            }
        }
    }
 
    /**
     * Creates an ActionListener for the "switch"-button.
     * 
     * @return The adjusted ActionListener.
     */
    private ActionListener createSwitchListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                theGame.switchGuesser();
                startNewGame();
            }
        };
    }
 
    /**
     * Creates an ActionListener for the "new"-button.
     * 
     * @return Return the adjusted ActionListener.
     */
    private ActionListener createNewListener() {
        return new ActionListener() {
 
            @Override
            public void actionPerformed(ActionEvent e) {
                startNewGame();
            }
        };
    }
 
    /**
     * Starts a new game by resetting everyting. This method is used by the
     * ActionListeners of the "new"-button and the "switch"-button.
     */
    private void startNewGame() {
        boolean machineIsGuessing = theGame.isMachineGuessing();
        gameOver = false;
        theGame = new MastermindModel();
 
        //if the machine is supposed to guess, switch the user
        //since a new MastermindModel starts out with the user
        //guessing; update the textPanel accordingly
        if (theGame.isMachineGuessing() != machineIsGuessing) {
            theGame.switchGuesser();
        }
 
        //update the description panel
        if (theGame.isMachineGuessing()) {
            updateDescr(getDescr(GameSit.USER_MOVE_SET_SECRET_PANEL));
        } else {
            updateDescr(getDescr(GameSit.USER_MOVE_USER_GUESSES));
        }
 
        gameOver = false;
 
        resetGameBoard();
        gameBoard.revalidate();
        secretPanel = resetMovePanel(secretPanel, MastermindGame.MAX_MOVES);
        secretPanel.revalidate();
 
        repaint();
    }
 
    /**
     * Updates the color panel for a given move with a given ColorCode.
     * 
     * @param moveCount The number of the move.
     * @param code The ColorCode that will be displayed.
     */
    private void updateMovePanel(int moveCount, ColorCode code) {
        Color[] theCodeColors = code.getColors();
 
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            moveCircles[moveCount][i].setForeground(theCodeColors[i]);
        }
 
        repaint();
    }
 
    /**
     * Updates the rating panel for a given move with a given Rating.
     * 
     * @param moveCount The number of the move.
     * @param rating The Rating that will be displayed.
     */
    private void updateRatingPanel(int moveCount, Rating rating) {
           int blacks = rating.getBlacks();
           int whites = rating.getWhites();
 
           for (int i = 0; i < blacks; i++) {
               ratingCircles[moveCount][i].setForeground(Color.BLACK);
           }
 
           for (int i = 0; i < whites; i++) {
               ratingCircles[moveCount][i + blacks].setForeground(Color.WHITE);
           }
 
           repaint();
    }
 
    /**
     * Updates the description panel with a given text.
     * 
     * @param newText The new text for the panel.
     */
    private void updateDescr(String newText) {
        changeTextLabel(descriptionPanel, newText,
                descriptionPanel.getBackground());
        descriptionPanel.revalidate();
        repaint();
    }
 
    /**
     * Gives back a String describing a given game situation.
     * Also, in the case of USER_WON and USER_LOST, gameOver is set to true.
     * 
     * @param situation The game situation.
     * @return Returns a String describing the game situation.
     */
    private String getDescr(GameSit situation) {
        String textDescribingSituation = null;
 
        switch(situation) {            
        case INVALID_COLORCODE:
            textDescribingSituation =
                "Pick a color for every slot!";
            break;
 
        case USER_CHEATED:
            textDescribingSituation =
                "You cheated! - Click 'new' or 'switch'.";
            gameOver = true;
            break;
 
        case USER_WON:
            textDescribingSituation =
                "You win! - Click 'new' or 'switch'.";
            gameOver = true;
            break;
 
        case USER_LOST:
            textDescribingSituation =
                "Computer wins! - Click 'new' or 'switch'.";
            gameOver = true;
            break;
 
        case USER_MOVE_MACHINE_GUESSES:
            textDescribingSituation =
                "Rate the guess and click 'move'.";
            break;
 
        case USER_MOVE_USER_GUESSES:
            textDescribingSituation =
                "Pick your guess and click 'move'!";
            break;
 
        case USER_MOVE_SET_SECRET_PANEL:
            textDescribingSituation =
                "Set the secret code and click 'move'!";
            break;
 
        default:
            break;
        }
 
        return textDescribingSituation;
    }
 
    /**
     * Reads a ColorCode entered by the user into the color code circles.
     * 
     * @param moveCount The current turn.
     * @return Returns a ColorCode representing the current turn.
     */
    private ColorCode readColorCode(int moveCount) {
        byte[] theCodeAsNumbers = new byte[MastermindGame.NUMBER_SLOTS];
        Arrays.fill(theCodeAsNumbers, ColorCode.COLOR_INVALID);
 
        //transform each slot into the number corresponding to its Color
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            Color foreground = moveCircles[moveCount][i].getForeground();
            theCodeAsNumbers[i] = (byte) ColorCode.colorToNumber(foreground);
        }
 
        return new ColorCode(theCodeAsNumbers);
    }
 
    /**
     * Reads a Rating entered by the user into the rating circles.
     * 
     * @param moveCount The current turn.
     * @return Returns a Rating representing the current turn.
     */
    private Rating readRating(int moveCount) {
        byte blacks = 0;
        byte whites = 0;
 
        for (JPanel ratingCircle : ratingCircles[moveCount]) {
 
            if (ratingCircle.getForeground() == Rating.RATING_COLORS[0]) {
                blacks++;
            }
 
            if (ratingCircle.getForeground() == Rating.RATING_COLORS[1]) {
                whites++;
            }
        }
 
        return (new Rating(blacks, whites));
    }
 
    /**
     * Checks whether a circle belongs to the panel of the current turn.
     * This method is used to control the matrix-like structure of the game
     * board.
     * 
     * @param circle The circle that is supposed to belong to the panel.
     * @param panel The panel.
     * @param moveCount The current turn.
     * @return Returns true if the circle belongs to the panel for the current
     *         turn, else false.
     */
    private boolean circleBelongsToPanel(JPanel circle, JPanel[][] panel,
            int moveCount) {
 
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            if (panel[moveCount][i] == circle) {
                return true;
            }
        }
 
        return false;
    }
 
    /**
     * Checks if the ColorCode that was set in a given row is valid.
     * 
     * @param moveCount The number of the row.
     * @return Returns true if the color combination set in the row is valid
     *         (which means it has no unset slots), else false.
     */
    private boolean validateCode(int moveCount) {
        boolean codeIsValid = false;
 
        //get the color code from the row moveCount into a  byte[]
        byte[] code = new byte[MastermindGame.NUMBER_SLOTS];
        Arrays.fill(code, ColorCode.COLOR_INVALID);
 
        for (int i = 0; i < MastermindGame.NUMBER_SLOTS; i++) {
            Color foreground = moveCircles[moveCount][i].getForeground();
            code[i] = (byte) ColorCode.colorToNumber(foreground);
        }
 
        //make that byte[] into a ColorCode and check if it's valid
        ColorCode move = new ColorCode(code);
        codeIsValid = move.isValidCode();        
        return codeIsValid;
    }
}

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS