3 Replies - 2926 Views - Last Post: 08 November 2011 - 08:08 PM

#1 pbl   User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8379
  • View blog
  • Posts: 31,956
  • Joined: 06-March 08

A small memory game

Posted 22 July 2009 - 05:06 PM

Description: You have to remember the numbers displayed
import java.awt.*;
import java.awt.event.*;
import java.util.*;			// for Random and ArrayList

import javax.swing.*;        // obviously a lot of swing
import javax.swing.event.MouseInputListener;

/*
 * You can't imagine how many post in the forum request for ready to go Game
 * I saw that one on the net yesterday so decide to spend an hour or 2 to write in Java
 * I didn't make a tutorial out of it... no time to do so but here for fun
 * A little trivia game
 * a few numbers from 0 to 9 circled by circle are showed a few seconds
 * then the value disappear and only the circles are displayed
 * You have then to click on the circles in order of the numbers that where shown
 */
public class GuessWhereAreTheNumbers extends JFrame implements Runnable, ActionListener {
	// number of rows and colums
	private static final int NB_ROWS = 5, NB_COLS = 7;
	// the labels that will represent sometimes a number sometimes a circle
	private CircleLabel[][] label = new CircleLabel[NB_ROWS][NB_COLS];
	// a Random object to determine the displayed numbers and their location
	private Random random = new Random();
	// the panel that hold the radio button and the button
	private BottomPanel bottomPanel;
	// the Button to start a game
	private JButton button = new JButton("Go !");
    // the label at the top to say if you win or fail
	private JLabel statusLabel = new JLabel("n");
	// the array of the labels in the game (the ones that hold a number from 0 to 9)
	private CircleLabel[] cl;
	// the number of labels correctly clicked
	private int nbClicked;
	
	GuessWhereAreTheNumbers() {
		super("Guess where are the numbers");
		setBackground(Color.WHITE);
		// the status label at the top
		statusLabel.setHorizontalAlignment(SwingConstants.CENTER);
		// just fancy color stuff
		statusLabel.setForeground(Color.BLUE);
		statusLabel.setBackground(Color.YELLOW);
		statusLabel.setForeground(Color.RED);
		// posted at the top of the JFrame
		add(statusLabel, BorderLayout.NORTH);
		// a JPanel with a grid to display all my labels
		JPanel panel = new JPanel(new GridLayout(NB_ROWS, NB_COLS));
		panel.setBackground(Color.WHITE);
		// put our labels into it
		for(int j = 0; j < NB_COLS; j++) {
			for(int i = 0; i < NB_ROWS; i++) {
				label[i][j] = new CircleLabel(i, j);
				panel.add(label[i][j]);
			}
		}
		// add the JPanel to the main frame
		add(panel, BorderLayout.CENTER);
		// the BottomPanel that holds the RadioButtons and the Button Go
		bottomPanel = new BottomPanel(this);
		// put it south
		add(bottomPanel, BorderLayout.SOUTH);
		// set size (a little more pixel on the Y axis for bottom and top panel) and default close operation
		setSize(NB_COLS * 50, NB_ROWS * 50 + 20);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setVisible(true);
		
	}
	
	// the thread that actually display the numbers and then hides them
	public void run() {
		// while the game runs make the button "GO" unavailable
		button.setEnabled(false);
		// number of label clicked
		nbClicked = 0;
		// erase the status label from the last game
		statusLabel.setText("n");
		// fill an ArrayList with all the available labels so we can picj them randomly
		ArrayList<CircleLabel> al = new ArrayList<CircleLabel>();
		for(int j = 0; j < NB_COLS; j++) {
			for(int i = 0; i < NB_ROWS; i++) {
				// reset label no text to display no circle to draw
				label[i][j].setValue(-1);
				// add to the arrayList
				al.add(label[i][j]);
			}
		}
		// get the number of numbers/circles to display (depending of the JButton selected in the bottomPanel)
		int nbToShow = bottomPanel.getNbCircle();
		// an array of the labels which will be displayed
		cl = new CircleLabel[nbToShow];
		// another ArrayList to determine the value that will be shown in the label
		ArrayList<Integer> oneToNine = new ArrayList<Integer>();
		for(int i = 0; i <= 9; i++)
			oneToNine.add(i);
		// pickup randomly nbToShow labels
		for(int i = 0; i < nbToShow; i++) {
			cl[i] = al.remove(random.nextInt(al.size()));
			// get a random value for it
			int val = oneToNine.remove(random.nextInt(oneToNine.size()));
			// set these value to the label
			cl[i].setValue(val);
		}
		// wait for the user to remember the number
		try {
			Thread.sleep(1500L);    // this is 1.5 second you can change it
		}
		catch (Exception e) {
			throw new IllegalStateException("Thread.Sleep() failed for " + e);
		}
		// now display the circle only
		for(int i = 0; i < nbToShow; i++) {
			cl[i].setCircleOnly();
		}
		// sort the labels by their values so I can check if they are clicked in the good order
		Arrays.sort(cl);
	}
	
	// we'll be called when the button "GO" will be clicked
	public void actionPerformed(ActionEvent e) {
		Thread thread = new Thread(this);
		thread.start();
	}
	// just to start the application
	public static void main(String[] args) {

		// one instance of our stuff
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				new GuessWhereAreTheNumbers();
			}
		});
	}
	
	// a special version of JLabel. It can display a number or a circle or an X or nothing
	// it has a mouseInputListener and implements Comparable so they can be sorted in order of Value
	class CircleLabel extends JLabel implements MouseInputListener, Comparable<CircleLabel> {
		// tne number it holds (-1) in no value
		int value;
		// the String representation of the number to display
		String valueToDisplay = "";
		// if I should display the X wrong answer
		boolean displayX = false;
		// my coordinates within the Panel
		int x, y;
		
		// constructor
		CircleLabel(int x, int y) {
			// init at nothing
			super("");
			// save position on grid
			this.x = x;
			this.y = y;
			// do not display the X
			displayX = false;
			// no value
			valueToDisplay = "";
			value = -1;
			this.setHorizontalAlignment(SwingConstants.CENTER);
			// and the mouse listener
			this.addMouseListener(this);
		}
		// to set the value of the label
		void setValue(int val) {
			// value in int
			value = val;
			// special case when value is -1
			if(value == -1)
			{			
				valueToDisplay = "";	// don't display any number
			}
			else {				
				// as a String so repaint can use it
				valueToDisplay = "" + val;
			}
			setText(valueToDisplay);		// value used by repaint
			displayX = false;				// init we do not display an X over the label
			// set foreground value to BLUE in case last game set it to RED
			setForeground(Color.BLUE);
		}

		// now display only circle
		void setCircleOnly() {
			// text reset to nothing
			setText("");
		}
		
		// the paint method: we overload the standard one in case we have to draw an X
		public void paint(Graphics g) {
			// always call my father in case I have text to display
			super.paint(g);
			// if an empty label, not selected for that game I exit
			if(value == -1)
				return;
			// draw a circle around it
			// get size of label
			Dimension dim = getSize();
			// get size of circle 1/6 of label size
			int width = dim.width / 6;
			int height = dim.height / 6;
			// draw the circle in black
			g.setColor(Color.BLACK);
			g.drawOval(width, height, width * 5, height * 5);	
			// test if we have to display the X
			if(displayX) {
				// OK just another color to be fancier
				g.setColor(Color.GREEN);
				// from the leftmost uppercorner to rightmost lower corner
				g.drawLine(0, 0, dim.width, dim.height);
				// from rightmost upper corner to leftmost lower corner
				g.drawLine(dim.width, 0, 0, dim.height);
			}
		}
		
		// the only listener I really use
		@Override
		public void mouseClicked(MouseEvent e) {
			// if we click on a label that does not have a value ignore it
			if(value == -1)
				return;
			// validate that I am the good label
			if(cl[nbClicked].value == value) {
				// remove the circle and display the bumber
				setText(valueToDisplay);
				// ok we will check the next one
				nbClicked++;
				// check if we are done
				if(nbClicked == cl.length) {
					statusLabel.setText("You winn");
					// ok ready to start a new game
					button.setEnabled(true);
				}
				else {
					statusLabel.setText("" + nbClicked + " out of " + cl.length + " done.");
				}
					
			}
			else {				// bad click
				statusLabel.setText("You loosen");
				// display the values of the selected label this is done by setting them to their values
				// the method will reset valueToDisplay
				for(int i = 0; i < cl.length; i++) {
					cl[i].setValue(cl[i].value);
				}
				// have the culprit label to have an X over it and display it's number in red
				badChoice();
				// ok ready to start a new game
				button.setEnabled(true);
			}	
		}
		
		// use to say that it should 1) display an X 2) display the value in red
		void badChoice() {
			displayX = true;			// flag next repaint will have to paint the X
			setForeground(Color.RED);	// and the culprit will display it's value in RED
		}

		// unused MouseListener methods
		public void mouseEntered(MouseEvent e) {}
		public void mouseExited(MouseEvent e) {}
		public void mousePressed(MouseEvent e) {}
		public void mouseReleased(MouseEvent e) {}
		public void mouseDragged(MouseEvent arg0) {}
		public void mouseMoved(MouseEvent arg0) {}
		
		// a compareTo method to sort the label according to their instance variable value
		public int compareTo(CircleLabel otherCircleLabel) {
			// just return if < or > to the one we compare
			return value - otherCircleLabel.value;
		}	
	}
	
	// the panel that will be put South to select number of Circle to display and the go button
	class BottomPanel extends JPanel {
		// 3 radio buttons for 4, 5, 6 circles
		JRadioButton[] radio = new JRadioButton[3];
		
		// Constructor receives as parameter our JFrame which is the listener
		BottomPanel(ActionListener al) {
			// 1 row and 5 columns: the title, 3 radio, the button, and empty label
			super(new GridLayout(1,6));
			// add a background color
			setBackground(Color.YELLOW);
			// add a label to explain what the RadioButtons are for
			add(new JLabel("Nb Circles:"));
			// a buttonGroup so only 1 radio can be selected at the same time
			ButtonGroup bg = new ButtonGroup();
			// add our RadioButton
			for(int i = 0; i < radio.length; i++) {
				// label of Radio index + 4
				radio[i] = new JRadioButton("" + (i+4));
				radio[i].setBackground(Color.YELLOW);
				// add RadioButton to the group and then to the panel
				bg.add(radio[i]);
				add(radio[i]);
			}
			// make the firt one selected
			radio[0].setSelected(true);
			// add the button
			button.addActionListener(al);
			add(button);	
			// an empty label
			add(new JLabel(""));
		}
		
		// returns the number of circles to draw depending of the JRadioButton selected
		int getNbCircle() {
			// loop to see which JRadioButton is selected
			for(int i = 0; i < radio.length; i++) {
				if(radio[i].isSelected()) {
					return i+4;
				}
			}
			// should not happen but Java compiler wants the method to return an int
			// unless we throw an exception
			throw new IllegalStateException("No Radio selected ???");
		}
		
	}
}



Is This A Good Question/Topic? 0
  • +

Replies To: A small memory game

#2 Rykker   User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 27
  • Joined: 03-October 09

Re: A small memory game

Posted 03 October 2009 - 06:53 AM

hey there is an error at line number 215....just add a coment to that line rest the code is fantastic....good work
Was This Post Helpful? 0
  • +
  • -

#3 m-e-g-a-z   User is offline

  • Winning
  • member icon


Reputation: 497
  • View blog
  • Posts: 1,457
  • Joined: 19-October 09

Re: A small memory game

Posted 26 July 2010 - 12:49 AM

It's not an error, as pbl implements the MouseInputListener interface, he has to override the mouseClicked method that's inherited.
Was This Post Helpful? 0
  • +
  • -

#4 pbl   User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8379
  • View blog
  • Posts: 31,956
  • Joined: 06-March 08

Re: A small memory game

Posted 08 November 2011 - 08:08 PM

Should be redone with a SwingTimer rather than a Thread
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1