// LOTS OF STUFF TO IMPORT FROM SWING AND FROM AWT
import javax.swing.JFrame; // Swing is newer graphics package
import javax.swing.JPanel;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.border.*;
import javax.swing.JComponent;
import java.awt.Container; // Abstract windowing toolkit
import java.awt.Graphics;
import java.awt.event.WindowAdapter; // For WindowListener()
import java.awt.event.WindowEvent;
import java.awt.Font;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.event.*; // For the WindowEvent object
import java.util.Random;
//////////////////////////// CLASS WITH MAIN ////////////////////////////
public class Madhawa_Mastermind
{
public static void main (String[] args)
{
// Set up my window to display the output of the program
// Create the window -- top level container for all other objects
Mastermind mastermind = new Mastermind();
mastermind.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
/////////////////////////////// END MAIN ////////////////////////////////
///////////// CLASSES WITH WINDOWS GENERATED FROM THE MENU ///////////////
/*************************************************************************
* This class builds the about JFrame. *
*************************************************************************/
class AboutScreen extends JFrame
{
AboutScreen()
{
setTitle("About");
setLocation(300, 300);
setSize(300, 200);
JPanel pane = (JPanel) getContentPane(); // Returns reference to a container object & JPanel is subclass---Container -> JComponent -> JPanel
pane.add(new JTextArea("MASTERMIND GAME\n\nCreated in August 2009\n by K. Cogswell\nVersion 2.00: January 2011"));
setResizable(false);
setVisible(true);
}
}
/*************************************************************************
* This class builds the instruction JFrame *
*************************************************************************/
class InstructionsScreen extends JFrame
{
InstructionsScreen()
{
setTitle("Instructions");
setLocation(300, 300);
setSize(300, 200);
JPanel pane = (JPanel) getContentPane(); // Returns reference to a container object & JPanel is subclass---Container -> JComponent -> JPanel
pane.add(new JTextArea(" MASTERMIND GAME\n\nThere are 4 coloured pegs chosen to guess. \n"+
" Pick 4 colours to guess and then press the guess \n"+
" button. You will be given four circles as a \n"+
" response. Any black circles indicate that you have\n"+
" a correctly coloured peg in a correct position.\n"+
" Any yellow circle indicates that you have a peg the \n"+
" correct colour in the wrong position. Try to guess \n"+
" all four coloured pegs in the correct position."));
setResizable(false);
setVisible(true);
}
}
///////////////////// END OF CLASSES FOR MENU WINDOWS ////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// M A S T E R M I N D C L A S S //
///////////////////////////////////////////////////////////////////////////////////////
/*************************************************************************
* This class builds the JFrame object of the mastermind game. *
*************************************************************************/
class Mastermind extends JFrame implements ActionListener
{
// Creates the centre panel to add to the contentPane in the constructor
PlayingBoard pegs = new PlayingBoard();
// Declare variables for the combo boxes
JComboBox guess1 = new JComboBox(pegs.colours);
JComboBox guess2 = new JComboBox(pegs.colours);
JComboBox guess3 = new JComboBox(pegs.colours);
JComboBox guess4 = new JComboBox(pegs.colours);
JLabel endOfGameMessage = new JLabel(" ");
// Array to store the colours to guess
Color[] secretPattern = new Color[4];
// The gameOver flag is used to store the state that the game is in
// This flag prohibits the player from continuing to guess
// Once they complete the game
boolean gameOver = false;
/*************************************************************************
* CONSTRUCTOR for the Mastermind class -- design the window *
*************************************************************************/
Mastermind()
{
// Set values for the Mastermind JFrame
setTitle("Mastermind");
setSize(300, 600); // width is first argument, height is second
// Set up the pattern to guess
makeSecretPattern();
// System.out.println(secretPattern[0]+" "+secretPattern[1]+" "+secretPattern[2]+" "+secretPattern[3]+" ");
// Adding a MenuBar
JMenuBar menuBar;
JMenu menu,menu2;
JMenuItem menuItem0,menuItem1,menuItem2,menuItem3,menuItem4;
// Creating the menu bar
menuBar = new JMenuBar();
// Building the first menu.
menu = new JMenu("File");
menuBar.add(menu);
menu.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
// Building the second Menuitem for the first menu
menuItem0 = new JMenuItem("New Game");
menu.add(menuItem0);
menuItem0.addActionListener(this);
menuItem0.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
// Building the second Menuitem for the first menu
menuItem2 = new JMenuItem("Exit");
menu.add(menuItem2);
menuItem2.addActionListener(this);
menuItem2.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
// Building the second menu.
menu2 = new JMenu("Help");
menuBar.add(menu2);
menu2.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
// Building the first Menuitem for the first menu
menuItem3 = new JMenuItem("About");
menu2.add(menuItem3);
menuItem3.addActionListener(this);
menuItem3.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
// Building the first Menuitem for the first menu
menuItem4 = new JMenuItem("Instructions");
menu2.add(menuItem4);
menuItem4.addActionListener(this);
menuItem4.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
/////////////////// TOP PANEL -- Create the northPanel ///////////////////
JLabel blankLine = new JLabel(" ");
JLabel question = new JLabel("What colours would you like to guess?");
// Put the combo boxes together and add them to the button panel
JPanel northPanel = new JPanel();
northPanel.setLayout(new GridLayout(4,1));
northPanel.add(menuBar);
northPanel.add(blankLine);
northPanel.add(question);
JPanel myGuess = new JPanel();
myGuess.setLayout(new GridLayout(1,4,10,10));
myGuess.add(guess1);
myGuess.add(guess2);
myGuess.add(guess3);
myGuess.add(guess4);
northPanel.add(myGuess);
////////////////// BOTTOM PANEL -- Create the southPanel /////////////////
JPanel southButtonPanel = new JPanel();
southButtonPanel.setLayout(new FlowLayout());
JButton guessButton = new JButton("Make Guess");
JButton resetButton = new JButton("Reset");
southButtonPanel.add(guessButton);
southButtonPanel.add(resetButton);
guessButton.addActionListener(this);
resetButton.addActionListener(this);
JPanel southPanel = new JPanel();
southPanel.setLayout(new GridLayout(2,1));
southPanel.add(endOfGameMessage);
southPanel.add(southButtonPanel);
/////////////////////////////// CONTENT PANE //////////////////////////////
JPanel pane = (JPanel) getContentPane();
pane.setLayout(new BorderLayout(10,10));
// Add 3 panels created above to the contentPane
pane.add("North", northPanel);
pane.add("Center", pegs);
pane.add("South", southPanel);
// Pack();
setLocationRelativeTo(null);
setVisible(true);
} // END OF CONSTRUCTOR
/*************************************************************************
* ACTION LISTENER EVENTS for the Mastermind Class *
*************************************************************************/
public void actionPerformed (ActionEvent e)
{
if (e.getActionCommand().equals("About"))
new AboutScreen();
if (e.getActionCommand().equals("Exit"))
System.exit(0);
if (e.getActionCommand().equals("Instructions"))
new InstructionsScreen();
if (e.getActionCommand().equals("Reset") || e.getActionCommand().equals("New Game"))
{
pegs.guessNumber = 0;
pegs.blankScreen();
makeSecretPattern();
endOfGameMessage.setText(" ");
gameOver = false;
}
if (e.getActionCommand().equals("Make Guess"))
{
if (gameOver)
endOfGameMessage.setText(" Press RESET to play a new game.");
else if (pegs.guessNumber < 10)
{
pegs.guessNumber++;
pegs.makeGuess(pegs.myColour[guess1.getSelectedIndex()], pegs.myColour[guess2.getSelectedIndex()], pegs.myColour[guess3.getSelectedIndex()], pegs.myColour[guess4.getSelectedIndex()]);
if(pegs.correctGuess(secretPattern))
{
Font font = new Font("Verdana", Font.BOLD, 18);
endOfGameMessage.setFont(font);
endOfGameMessage.setForeground(Color.BLUE);
endOfGameMessage.setText(" YOU WON! GREAT GAME");
gameOver = true;
}
}
else // Player ran out of guesses before secret pattern was found
{
// Print the guesses message
pegs.showAnswer(secretPattern);
endOfGameMessage.setText(" Sorry, you ran out of guesses");
gameOver = true;
}
}
} // END OF ACTION PERFORMED
/*************************************************************************
* SET UP A COLOUR PATTERN TO GUESS *
* this is done within the Mastermind Class *
*************************************************************************/
public void makeSecretPattern()
{
int k=0;
Random generate = new Random();
// Choose colours to set (random selection)
k = generate.nextInt(6);
secretPattern[0] = pegs.myColour[k];
k = generate.nextInt(6);
secretPattern[1] = pegs.myColour[k];
k = generate.nextInt(6);
secretPattern[2] = pegs.myColour[k];
k = generate.nextInt(6);
secretPattern[3] = pegs.myColour[k];
// Print the secret colour pattern for debugging purposes
System.out.print("The secret pattern: ");
pegs.printColourPattern(secretPattern);
System.out.println();
}
} // END OF CLASS Mastermind
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// P L A Y I N G B O A R D C L A S S //
///////////////////////////////////////////////////////////////////////////////////////
/*************************************************************************
* This class controls the guesses and contains the paint method to *
* paint the pegs. *
*************************************************************************/
class PlayingBoard extends JComponent // Guesses is a subclass of JComponent so we inherit paint() method
{
public int guessNumber = 0;
public static final Color BROWN = new Color(0x40, 0x40, 0x00);
public String[] colours = {"blue", "red", "green", "yellow", "brown", "pink"};
public Color [] myColour = {Color.blue, Color.red, Color.green, Color.yellow, BROWN, Color.pink};
static final int ROWS = 11;
static final int COLS = 4;
private boolean reset = false;
private Color[][] allGuesses = new Color[ROWS][COLS]; // 11 rows of 4
private Color[][] responses = new Color[ROWS][COLS];
private boolean showTheAnswer = false;
private boolean FILL = true;
private boolean NO_FILL = false;
/*************************************************************************
* CONSTRUCTOR method for the PlayingBoard class. *
*************************************************************************/
public PlayingBoard()
{
}
/*************************************************************************
* Method to print the colour pattern for debugging purposes. *
*************************************************************************/
public void printColourPattern(Color[] patternToPrint)
{
for (int i=0 ; i<4 ; i++)
for (int j=0 ; j< myColour.length ; j++)
if (myColour[j] == patternToPrint[i])
System.out.print (colours[j] + " ");
System.out.println();
}
/*************************************************************************
* Wrapper method used to incorporate the colour and fill attribute *
* into the drawing of the rectangle. *
*************************************************************************/
private void rect (Graphics g, boolean fill, Color c, int x, int y, int width, int height)
{
g.setColor(c);
if (fill)
g.fillRect(x, y, width, height);
else
g.drawRect(x, y, width, height);
}
/*************************************************************************
* Wrapper method used to incorporate the colour and fill attribute *
* into the drawing of the oval. *
*************************************************************************/
private void oval (Graphics g, boolean fill, Color c, int x, int y, int xRadius, int yRadius)
{
g.setColor(c);
if (fill)
g.fillOval(x, y, xRadius, yRadius);
else
g.drawOval(x, y, xRadius, yRadius);
}
/*************************************************************************
* Wrapper method used to incorporate the colour and font size for *
* a new text item. *
*************************************************************************/
private void writeText (Graphics g, int fontSize, String str, Color c, int x, int y)
{
g.setColor(c);
Font largeSerifFont = new Font("Serif", Font.PLAIN, fontSize);
g.setFont(largeSerifFont);
g.drawString(str, x, y); // 20 pixels from the left and 350 pixels below the top
}
/*************************************************************************
* Method to ASSIGN COLOURS TO THE ARRAY method for the *
* PlayingBoard class. *
*************************************************************************/
public void makeGuess(Color guess1, Color guess2, Color guess3, Color guess4)
{
allGuesses[guessNumber-1][0] = guess1;
allGuesses[guessNumber-1][1] = guess2;
allGuesses[guessNumber-1][2] = guess3;
allGuesses[guessNumber-1][3] = guess4;
repaint();
}
/*************************************************************************
* Display the correct colour combination *
*************************************************************************/
public void showAnswer(Color[] secretPattern)
{
showTheAnswer = true;
allGuesses[ROWS-1][0] = secretPattern[0];
allGuesses[ROWS-1][1] = secretPattern[1];
allGuesses[ROWS-1][2] = secretPattern[2];
allGuesses[ROWS-1][3] = secretPattern[3];
repaint();
}
/*************************************************************************
* Print some DEBUGGING messages *
*************************************************************************/
private void debugMessage(int[] responsePegs, Color[] secretPattern)
{
System.out.print("Guess: ");
printColourPattern(allGuesses[guessNumber-1]);
System.out.print("Actual: ");
printColourPattern(secretPattern);
System.out.println("Pegs set: "+responsePegs[0]+responsePegs[1]+responsePegs[2]+responsePegs[3]);
System.out.println();
}
/*************************************************************************
* Record the black and grey pegs that are determined to be the answer. *
* Called from "correctGuess()" method below. *
*************************************************************************/
private void recordResponses(int[] responsePegs)
{
// Clear out the responses array
for (int i = 0 ; i<4 ; i++)
responses[guessNumber-1][i]=null;
// Set up the responses array
for (int i = 0; i<4; i++)
{
if( responsePegs[i] == 2) responses[guessNumber-1][i] = Color.black;
else if( responsePegs[i] == 1) responses[guessNumber-1][i] = Color.gray;
else responses[guessNumber-1][i] = Color.white;
}
}
/*************************************************************************
* Check to see what they got right and set the grey and black pegs. *
*************************************************************************/
public boolean correctGuess(Color[] secretPattern)
{
int sum = 0;
int[] responsePegs = new int[4]; // Set flag to 2 if correct colour and position
// Set flag to 1 if correct colour
boolean[] pegCounted = {false, false, false, false};
// BLACK PEG LOGIC - check each peg to see if the position matches the colour
//---------------------------------------------------------------------------
for(int i = 0;i < 4 ; i++)
{
if (allGuesses[guessNumber-1][i] == secretPattern[i])
{
responsePegs[i]=2;
pegCounted[i]=true;
}
// GREY COLOR LOGIC
// ----------------
// Check for number of correct colour guesses
for(int j = 0; j<4; j++)
{
if(allGuesses[guessNumber-1][i] == secretPattern[j] && pegCounted[i] == false)
{
responsePegs[i]=1;
pegCounted[i]=true;
}
}
}
// For debugging, print out some information
debugMessage(responsePegs, secretPattern);
// Copy the pegs needed into the responses ARRAY
recordResponses(responsePegs);
// WINNING COMBINATION - return true if correct, false if incorrect
// ----------------------------------------------------------------
int count = 0;
for(int i = 0 ; i<4 ; i++)
{
if (responsePegs[i]==2)
count++;
if (count == 4)
return true;
}
return false;
} // End of correctGuess method
/*************************************************************************
* RESET BUTTON WAS PRESSED, SO BLANK THE SCREEN *
*************************************************************************/
public void blankScreen()
{
guessNumber = 0;
repaint();
reset = false;
}
/*************************************************************************
* PAINT THE SCREEN WITH ALL OF THE GUESSES MADE *
*************************************************************************/
public void paint (Graphics g) // Graphic object g stores all information on the graphic
{
try
{
// Draw a box around the peg board
rect (g, NO_FILL, Color.black, 10, 0, 270, 373);
if (!reset && guessNumber !=0 )
{
for (int j=0 ; j < guessNumber ; j++)
{
for (int i=0;i<=3;i++)
oval(g, FILL, allGuesses[j][i], (i+5)*15, 30*(j+1), 10, 20);
for (int k=0 ; k<=3; k++)
{
if (responses[j][k] == null)
{
oval(g, NO_FILL, Color.darkGray, (k+10)*15, 30*(j+1)+5, 10, 10);
}
else
{
oval(g, NO_FILL, Color.darkGray, (k+10)*15, 30*(j+1)+5, 10, 10);
oval(g, FILL, responses[j][k], (k+10)*15, 30*(j+1)+5, 10, 10);
}
}
}
}
// Show the answer if the player gives up or runs out of guesses
if (showTheAnswer)
{
// 20 pixels from the left and 350 pixels below the top
writeText(g, 14, "Answer:", Color.orange.darker(), 20, 350);
// Paint the 4 hidden colours
for (int i=0;i<=3;i++)
oval(g, FILL, allGuesses[ROWS-1][i], (i+5)*15, 30*(11), 10, 20);
// Reset the flag
showTheAnswer = false;
}
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
writeText(g, 40, "Index is out of bounds.", Color.orange.darker(),
}
}
}
///////////////////////////// END OF PLAYINGBOARD CLASS /////////////////////////////