/* * Filename: GameInterface.java * Created on March 10, 2006 * ULID: sawhite2 Course: * * ITK 168 Section: 4 Instructor: White */ import javax.swing.*; import java.awt.*; import java.awt.event.*; /** * Graphical User Interface for the Master Mind game. * * This class has a private inner-class called GuessPanel used * to hold the buttons for the guessed pattern. * * All buttons are fully functional. * * @author Shirley White */ public class GameView implements ActionListener { /** width of the frame initialized to 600 */ public static final int WIDTH = 600; /** height of the frame initialized to 600 */ public static final int HEIGHT = 600; // panels // main panel private JPanel panel = new JPanel(); // subpanel to hold color choices private JPanel colorPanel = new JPanel(); // subpanel array to hold 6 guesses private GuessPanel[] guessPanels = new GuessPanel[6]; private JFrame frame = new JFrame(); // button array for color choices private JButton[] colorButtons = new JButton[6]; private JButton checkButton = new JButton("Check Guess"); private JLabel correctColorLabel = new JLabel(); private JLabel correctPlaceLabel = new JLabel(); private JLabel winnerLabel = new JLabel(); private JButton newGameButton = new JButton("Start New Game"); private Game game; /** * Default constructor sets up the frame. */ public GameView(Game game) { this.game = game; // set main panel layout to add each component in a new row panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); // fill main panel // setup and add color choice buttons panel this.setUpColorChoices(); panel.add(colorPanel); // setup add 6 guess panels for(int i=0; i<6; i++) { guessPanels[i] = new GuessPanel(i+1); panel.add(guessPanels[i]); } // setup and add button to check the guess checkButton.setEnabled(false); checkButton.addActionListener(this); panel.add(checkButton); // add guess details panel.add(this.correctColorLabel); panel.add(this.correctPlaceLabel); panel.add(this.winnerLabel); // setup and add new game button this.newGameButton.addActionListener(this); panel.add(this.newGameButton); // display frame frame.setBounds(10, 10, WIDTH, HEIGHT); frame.setContentPane(panel); frame.setTitle("Master Mind"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } /* * Private method to build the 6 color choice buttons. * Called in the constructor. */ private void setUpColorChoices() { // set colors panel layout to fill all components in one row colorPanel.setLayout(new BoxLayout(colorPanel, BoxLayout.X_AXIS)); //build buttons for(int i=0; i<6; i++) { colorButtons[i] = new JButton(" "); } colorButtons[0].setBackground(Color.RED); colorButtons[1].setBackground(Color.BLUE); colorButtons[2].setBackground(Color.GREEN); colorButtons[3].setBackground(Color.YELLOW); colorButtons[4].setBackground(Color.ORANGE); colorButtons[5].setBackground(Color.PINK); // add action listener to each button for(int i=0; i<6; i++) { colorButtons[i].addActionListener(this); } // add color bottons to colors panel for(int i=0; i<6; i++) { colorPanel.add(colorButtons[i]); } } /** * Method to enable the color choice buttons. */ public void enableColors() { for(int i=0; i<6; i++) { this.colorButtons[i].setEnabled(true); } } /** * Method to disable the color choice buttons. */ public void disableColors() { for(int i=0; i<6; i++) { this.colorButtons[i].setEnabled(false); } } /** * Method to update the view every time the Game class * object changes. * * i.e. When a new guess is made, perhaps winning the game. */ public void update() { if(this.game.isLost()) { this.winnerLabel.setText("Sorry you lose."); this.correctColorLabel.setText(" "); this.correctPlaceLabel.setText(" "); this.checkButton.setEnabled(false); } else { this.enableColors(); this.correctColorLabel.setText("Correct Colors: " + this.game.getNumCorrectColor()); this.correctPlaceLabel.setText("Correct Placement: " + this.game.getNumCorrectPlace()); if(this.game.isWon()) { this.winnerLabel.setText("Congratulations you win!!!"); this.disableColors(); } } } /** * This method acts as the controller in our MVC architecture. * * This method processes all clicks of the color buttons, the * button to check the guess, or the button to start a new * game - updating the Game object as necessary. */ public void actionPerformed(ActionEvent e) { // index variable to use in guessPanels array int index = this.game.getNumGuesses(); JButton clicked = (JButton) e.getSource(); if(clicked.equals(this.checkButton)) { this.game.handleGuess(guessPanels[index].buildGuess()); this.checkButton.setEnabled(false); } else if(clicked.equals(this.newGameButton)) { this.game.reset(); } else { // disable this color so it cannot be chosen again during this guess // this actually introduces a bug because if you do not use this // color at this time you will not be able to use it for this // guess. // also if you overwrite this color (changing it to a diferent // color in the guess) you cannot choose to use it again for // this guess. // for simplicity, we chose to leave this bug in the program. clicked.setEnabled(false); this.guessPanels[index].setChoice(clicked.getBackground()); this.guessPanels[index].enableButtons(); } } /** * This method is used to clear the feedback messages and to * clear any guesses when a new game is started. */ public void clearView() { this.correctColorLabel.setText(""); this.correctPlaceLabel.setText(""); this.winnerLabel.setText(""); this.enableColors(); this.checkButton.setEnabled(false); // clear all guess panels for(int i=0; i<6; i++) { this.guessPanels[i].setInitialBGColor(); this.guessPanels[i].disableButtons(); } } /* * GuessPanel is a private inner class used only in the GameView * class. * * This class is used to create a subpanel to hold the 3 colors * in a single pattern guess. * * The buttons are fully functional. */ private class GuessPanel extends JPanel implements ActionListener { // buttons for current guess private JButton one = new JButton(" "); private JButton two = new JButton(" "); private JButton three = new JButton(" "); // holds the color choice that was last clicked by the user private Color choice; /** * Default constructor sets up the guess panel. * * @param num The guess number - ranging from 1 to 10 inclusive */ public GuessPanel(int num) { this.setInitialBGColor(); // setup guess panel - with buttons initially disabled this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); this.add(new JLabel("Guess " + num + " ")); this.add(one); this.add(two); this.add(three); // disable buttons this.disableButtons(); // add action listener one.addActionListener(this); two.addActionListener(this); three.addActionListener(this); } /** * Method to set the color of all buttons to a light gray. * This is the start color - indicating the user has not fully setup * the guess yet. */ public void setInitialBGColor() { one.setBackground(Color.LIGHT_GRAY); two.setBackground(Color.LIGHT_GRAY); three.setBackground(Color.LIGHT_GRAY); } /** * This method is used to guild a Guess ojbect from the colors the user * has set the 3 buttons to. * @return Returns a Guess object with the 3 column characters set to * match the color choices entered by the user. */ public Guess buildGuess() { return new Guess(this.getColorLetter(one), this.getColorLetter(two), this.getColorLetter(three)); } /* * Private method called by buildGuess. * * Used to determine the color letter to use based on the button color * set by the user. */ private char getColorLetter(JButton column) { char letter; if(column.getBackground().equals(Color.RED)) letter = 'r'; else if(column.getBackground().equals(Color.BLUE)) letter = 'b'; else if(column.getBackground().equals(Color.GREEN)) letter = 'g'; else if(column.getBackground().equals(Color.YELLOW)) letter = 'y'; else if(column.getBackground().equals(Color.ORANGE)) letter = 'o'; else letter = 'p'; return letter; } /** * * @return Returns the last color chosen by the user. */ public Color getChoice() { return this.choice; } /** * * @param choice The last color chosen by the user. */ public void setChoice(Color choice) { this.choice = choice; } /** * Method to enable all buttons. Recall the buttons are initially * disabled so only one choice can be filled at a time. */ public void enableButtons() { // enable guess buttons one.setEnabled(true); two.setEnabled(true); three.setEnabled(true); } /** * Method to disable all buttons. Recall the buttons are initially * disabled so only one choice can be filled at a time. */ public void disableButtons() { one.setEnabled(false); two.setEnabled(false); three.setEnabled(false); } /** * This method responds to all button clicks in this class. * * When a color is set, the other buttons are disabled to make * sure no 2 buttons ahve the same color in the pattern. * * When all 3 buttons have colors set, the checkButton is enabled. * However the user can still change colors before submitting the * guess. */ public void actionPerformed(ActionEvent e) { JButton clicked = (JButton) e.getSource(); if (clicked.equals(one)) { clicked.setBackground(choice); two.setEnabled(false); three.setEnabled(false); } else if(clicked.equals(two)) { clicked.setBackground(choice); one.setEnabled(false); three.setEnabled(false); } else if(clicked.equals(three)) { clicked.setBackground(choice); one.setEnabled(false); two.setEnabled(false); } if(!one.getBackground().equals(Color.LIGHT_GRAY) && !two.getBackground().equals(Color.LIGHT_GRAY) &&!three.getBackground().equals(Color.LIGHT_GRAY) ) { clicked.setEnabled(false); checkButton.setEnabled(true); // disable buttons this.disableButtons(); } } }// end inner class GuessPanel }// end outer class GameView