image memory game java

Image Memory Game using Java – part 1

This tutorial is about to learn how to create an image memory game using Java and Swing.

Introduction:

An Image memory game is about playing with your capabilities to use your memory to remember the exact place of the image. This a strategic and prediction game.

In this first part, we will make the complete game with some configuration interface and scoring. Then in the second part, we will continue the game to make it played in the local network with friends and family, using java socket.

Learn more about java socket in this tutorial, Also we will make all the configuration working as expected.

Subscribe to our YouTube channel to get notified about new tutorials.

Image Memory Game Preview:

This is a video preview of our application.

Image Preview:

 

Image game memory java

After this preview now it’s time to take action and start implementing our java game.

Graphic interface swing:

As you know there are multiple ways to create our interface by typing codes or by drag and drop using some tools in Eclipse or by default in NetBeans. So our application uses the first option, So let’s create our Mainframe.java class.

package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;

import model.Joueur;
import model.Personnage;
import model.Plateau;

import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.filechooser.FileFilter;

/**
 *
 * @author elgarnaoui.com
 */
public class MainFrame extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	// Variables declaration
	Card[] tiles = new Card[20];
    ImageIcon[] icons = new ImageIcon[10];
    int status, score;
    Card predict1, predict2;
    private boolean won, helping;
    
    private JPanel controlPanel;
    private JPanel gamePanel;
    private JLabel nbrRestantGamer;
    private JLabel nbrAvailableGamer;
    private JLabel courantGamer;
    private JButton load;
    private JButton play;
    private JPanel leftPanel;
    private JPanel edtionPanel;
	private JPanel joueurPanel;
	private JTextArea edition;
	private JMenuBar menuBar;
	private JMenu helpMenu;
	private JMenu showMenu;
	private JMenu settingMenu;
    
    private Joueur joueur;
    private List<Joueur> joueurs;
    private Personnage personnage;
    private Plateau plateau;
	private int nbrPersRest;
	private JDialog dialogInit;
	private JScrollPane scrollPane;
	private String basePath;
	private static final int baseSize = 128;
	private JPanel photo;
	private BufferedImage targetImg;
	private File targetFile;
	private JDialog dialogGamer;
	private JPanel photoPanel;
	
	
    public MainFrame() {
        initComponents();
        initIcons();
        initGame();
    }

    private void initGame() {
        score = 0;
        int x = 0;
        for (int i = 0; i < tiles.length; i++) {
            tiles[i] = new Card(icons[x], new ImageIcon(getClass().getResource("/images/gray.png")));
            tiles[i].addActionListener(this);
            gamePanel.add(tiles[i]);
            if ((i + 1) % 2 == 0) {
                x++;
            }
        }
        edition.setText(joueur.getPseudo() + "'s Score: " + score);
        shuffle();

    }

    private void initIcons() {
        Image img;
        for (int i = 0; i < icons.length; i++) {
            img = new ImageIcon(getClass().getResource("/images/" + i + ".jpg")).getImage();
            icons[i] = createIcon(img);
        }

    }

    private ImageIcon createIcon(Image img) {
        BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
        bi.createGraphics().drawImage(img, 0, 0, null);
        img = bi.getScaledInstance(80, 80, 1);
        return new ImageIcon(img);
    }

    private void showHelp() {
        //if tiles[0] would be null than all the tiles would be null here
        if (tiles[0] != null) {
            for (int i = 0; i < tiles.length; i++) {
                if (!tiles[i].isNoIcon()) {
                    tiles[i].showTile();
                    tiles[i].removeActionListener(this);
                }
            }
            score -= 50;
            edition.append("\n" +joueur.getPseudo() + "'s Score: " + score);
        }
    }

    private void hideHelp() {

        for (int i = 0; i < tiles.length; i++) {
            if (!tiles[i].isNoIcon()) {
                tiles[i].hideTile();
                tiles[i].addActionListener(this);
            }
        }

    }

    private void check() {

        if (predict1 != predict2 && predict1.getImage() == predict2.getImage()) {
            new Thread() {
                @Override
                public void run() {
                    for (int i = 0; i < 3; i++) {
                        try {
                            predict1.hideTile();
                            predict2.hideTile();
                            Thread.sleep(100);
                            predict1.showTile();
                            predict2.showTile();
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            System.out.println(ex);
                        }
                    }
                    for (int i = 0; i < tiles.length; i++) {
                        if (!tiles[i].isNoIcon()) {
                            won = false;
                            break;
                        } else {
                            won = true;
                        }
                    }
                    if (won) {
                        if (score > 0) {
                            JOptionPane.showMessageDialog(gamePanel, "You Won! Your Score is " + score);
                        } else {
                            new Thread() {
                                @Override
                                public void run() {
                                    
                                }
                            }.start();//loose sound
                            JOptionPane.showMessageDialog(gamePanel, "You Loose! Your Score is " + score);
                        }
                        initGame();
                    }
                }
            }.start();//animation
            predict1.removeActionListener(this);
            predict2.removeActionListener(this);
            score += 100;
            edition.append("\n" +joueur.getPseudo() + "'s Score: " + score);

        } else {
            predict1.hideTile();
            predict2.hideTile();
            score -= 10;
            edition.append("\n" + joueur.getPseudo() + "'s Score: " + score);
        }
    }

    private void shuffle() {
        gamePanel.removeAll();
        ArrayList<Integer> al = new ArrayList<Integer>();
        for (int i = 0; i < 20;) {
            int x = (int) (Math.random() * 20);
            if (!al.contains(x)) {
                al.add(x);
                i++;
            }
        }
        for (int i = 0; i < 20; i++) {
            gamePanel.add(tiles[al.get(i)]);
            tiles[al.get(i)].hideTile();
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * 
     */
    private void initComponents() {
    	joueurs = new ArrayList<Joueur>();
        leftPanel = new JPanel();
        joueurPanel = new JPanel();
        edtionPanel = new JPanel();
        gamePanel = new JPanel();
        controlPanel = new JPanel();
        
        nbrAvailableGamer = new JLabel();
        nbrRestantGamer = new JLabel();
        courantGamer = new JLabel();
        edition = new JTextArea();
        
        play = new JButton();
        load = new JButton();
        
        menuBar = new JMenuBar();
        settingMenu = new JMenu("Setting");
        showMenu = new JMenu("Show");
        helpMenu = new JMenu("?");
        
        
        joueur = new Joueur();
        joueur.setPseudo("John");
        joueurs.add(joueur);
        
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Image Game Memory");
        setIconImage(new ImageIcon(getClass().getResource("/images/mozart.jpg")).getImage());
        setLocationByPlatform(true);
        setName("Game Interface"); // NOI18N
        
        leftPanel.setLayout(new FlowLayout());
        leftPanel.setPreferredSize(new Dimension(230, 630));
        
        joueurPanel.setLayout(new GridLayout(3,1));
        joueurPanel.setPreferredSize(new Dimension(225, 130));
   
        nbrAvailableGamer.setFont(new java.awt.Font("Tahoma", 1, 11));
        nbrAvailableGamer.setHorizontalAlignment(JLabel.LEFT);
        nbrAvailableGamer.setText("Number of Gamers found: " + joueurs.size());
        nbrAvailableGamer.setBorder(null);
        joueurPanel.add(nbrAvailableGamer);
        
        nbrRestantGamer.setFont(new java.awt.Font("Tahoma", 1, 11));
        nbrRestantGamer.setHorizontalAlignment(JLabel.LEFT);
        nbrRestantGamer.setText("Number of Gamers Remaining: " +nbrPersRest);
        nbrRestantGamer.setBorder(null);
        joueurPanel.add(nbrRestantGamer);
        
        courantGamer.setFont(new java.awt.Font("bold", 1, 15));
        courantGamer.setHorizontalAlignment(JLabel.LEFT);
        courantGamer.setText("It's " + joueur.getPseudo() +" turn to play ! ");
        courantGamer.setBorder(null);
        joueurPanel.add(courantGamer);
        
        leftPanel.add(joueurPanel);
        
        edtionPanel.setLayout(new GridLayout(1,1));
        edtionPanel.setPreferredSize(new Dimension(225, 420));
        
        scrollPane = new JScrollPane(edition);
        scrollPane.setFont(new java.awt.Font("Tahoma", 1, 11));
        scrollPane.setBorder(null);
        edtionPanel.add(scrollPane);
        
        leftPanel.add(edtionPanel);
       
        JMenuItem item = new JMenuItem("Help", 'A');
        helpMenu.add(item);
        item.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				helpMouseClicked(e);
			}
		});
        
        JMenuItem item2 = new JMenuItem("Option", 'O');
        settingMenu.add(item2);
        item2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showInitDialog();
			}
		});
        
        JMenuItem item3 = new JMenuItem("Add Gamer", 'A');
        settingMenu.add(item3);
        item3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showGamerDialog();
			}
		});
        
        gamePanel.setPreferredSize(new java.awt.Dimension(630, 630));
        gamePanel.setLayout(new java.awt.GridLayout(6, 6, 5, 5));
        getContentPane().add(gamePanel, java.awt.BorderLayout.CENTER);

        controlPanel.setPreferredSize(new java.awt.Dimension(225, 45));
        controlPanel.setLayout(new java.awt.GridLayout(1, 2));
        
        play.setFont(new java.awt.Font("Tahoma", 0, 10));
        play.setForeground(new java.awt.Color(153, 153, 255));
        play.setText("Start");
        play.setToolTipText("Play new Game");
        play.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        play.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playActionPerformed(evt);
            }
        });
        controlPanel.add(play);
        
        load.setFont(new Font("Tahoma", 0, 10));
        load.setForeground(new Color(153, 153, 255));
        load.setText("Restart");
        load.setToolTipText("Load your favourite images");
        load.setCursor(new Cursor(java.awt.Cursor.HAND_CURSOR));
        load.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                loadActionPerformed(evt);
            }
        });
        controlPanel.add(load);
      
        leftPanel.add(controlPanel);
        menuBar.add(settingMenu);
        menuBar.add(showMenu);
        menuBar.add(helpMenu);
        setJMenuBar(menuBar);
        getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);
        pack();
    } 

    @SuppressWarnings("unused")
	private void closeMouseClicked(java.awt.event.MouseEvent evt) {
        if (evt.getButton() == MouseEvent.BUTTON1) {
            this.dispose();
        }
    }
    
    private void showInitDialog() {
    	dialogInit = new JDialog(this, "Init Dialog");
    	
    	dialogInit.setLayout(new GridLayout(1,2));
    	
    	JPanel left = new JPanel();
    	left.setLayout(new GridLayout(4,1));
    	left.setPreferredSize(new java.awt.Dimension(430, 120));
    	
    	Border border = BorderFactory.createTitledBorder("Choose the size of the game ");
        left.setBorder(border);
        
    	ButtonGroup groupe = new ButtonGroup();
        JRadioButton bouton1 = new JRadioButton("beginner (4 person, 2 families)",  true);
        groupe.add(bouton1);
        left.add(bouton1);
        JRadioButton bouton2 = new JRadioButton("Intermediate (10 person, 4 families)");
        groupe.add(bouton2);
        left.add(bouton2);
        JRadioButton bouton3 = new JRadioButton("Advanced (18 person, 6 families)");
        groupe.add(bouton3);
        left.add(bouton3);
        
        JRadioButton bouton4 = new JRadioButton("Expert (32 personn, 6 families)");
        groupe.add(bouton4);
        left.add(bouton4);
        
        
        JPanel right = new JPanel();
        right.setLayout(new GridLayout(4,1));
        right.setPreferredSize(new java.awt.Dimension(430, 120));
        
        Border border2 = BorderFactory.createTitledBorder("Choose the gamers ");
        right.setBorder(border2);
        
        JCheckBox btn1 = new JCheckBox("Lara");
        right.add(btn1);
        JCheckBox btn2 = new JCheckBox("John");
        right.add(btn2);
        JCheckBox btn3 = new JCheckBox("Med");
        right.add(btn3);
        
        dialogInit.add(left);
        dialogInit.add(right);
        
     
        dialogInit.setSize(550, 450); 
        dialogInit.setLocationRelativeTo(this);
        // set visibility of dialog 
        dialogInit.setVisible(true); 
	}
    
    private void showGamerDialog() {
    	dialogGamer = new JDialog(this, "Create Gamer");
    	
    	dialogGamer.setLayout(new GridLayout(1,2));
    	
    	JPanel left = new JPanel();
    	left.setLayout(new GridLayout(3,1));
    	left.setPreferredSize(new java.awt.Dimension(200, 120));
       
    	JPanel panelpseaudo = new JPanel();
    	panelpseaudo.setLayout(new GridLayout(2,1));
    	panelpseaudo.setPreferredSize(new java.awt.Dimension(200, 30));
    	JLabel pseudolbl = new JLabel("Give your ID :");
    	pseudolbl.setPreferredSize(new java.awt.Dimension(200, 10));
        JTextField pseudotxt = new JTextField();
        pseudotxt.setPreferredSize(new java.awt.Dimension(200, 20));
        panelpseaudo.add(pseudolbl);
        panelpseaudo.add(pseudotxt);
        
        JPanel panelfamily = new JPanel();
        panelfamily.setLayout(new GridLayout(2,1));
        panelfamily.setPreferredSize(new java.awt.Dimension(200, 30));
    	JLabel familylbl = new JLabel("What is your family's favorite characters? :");
    	familylbl.setPreferredSize(new java.awt.Dimension(200, 10));
        JTextField familytxt = new JTextField();
        familytxt.setPreferredSize(new java.awt.Dimension(200, 20));
        panelfamily.add(familylbl);
        panelfamily.add(familytxt);
        
        JPanel panelphoto = new JPanel();
        panelphoto.setLayout(new GridLayout(2,1));
        panelphoto.setPreferredSize(new java.awt.Dimension(200, 30));
    	JLabel photolbl = new JLabel("Choose your photo :");
    	photolbl.setPreferredSize(new java.awt.Dimension(200, 10));
        JButton photobtn = new JButton("Browse");
        photobtn.setPreferredSize(new java.awt.Dimension(200, 20));
        photobtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				browseButtonActionPerformed(e);
			}
		});
        panelphoto.add(photolbl);
        panelphoto.add(photobtn);
        left.add(panelpseaudo);
        left.add(panelfamily);
        left.add(panelphoto);
       
        
        JPanel right = new JPanel();
        right.setLayout(new FlowLayout());
        right.setPreferredSize(new java.awt.Dimension(400, 120));
        
        photo = new JPanel();
        photo.setPreferredSize(new Dimension(230, 248));
        photo.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
        
        JPanel p = new JPanel();
        p.setPreferredSize(new Dimension(250, 50));
        p.setLayout(new GridLayout(1,2));
        JButton btnCancel = new JButton("Cancel");
        JButton btnOk = new JButton("Submit");
        p.add(btnCancel);
        p.add(btnOk);
        right.add(photo);
        right.add(p);
        
        dialogGamer.add(left);
        dialogGamer.add(right);
        
     
        dialogGamer.setSize(530, 350); 
        dialogGamer.setLocationRelativeTo(this);
        //set visibility of dialog 
        dialogGamer.setVisible(true); 
	}
    
    private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
        JFileChooser fc = new JFileChooser(basePath);
        fc.setFileFilter(new JPEGImageFileFilter());
        int res = fc.showOpenDialog(null);
        // We have an image!
        try {
            if (res == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                setTarget(file);
            }else {
                JOptionPane.showMessageDialog(null,
                        "You must select one image to be the reference.", "Aborting...",
                        JOptionPane.WARNING_MESSAGE);
            }
        } catch (Exception iOException) {
        	
        }

    }

    public void setTarget(File reference) {
        try {
            targetImg = rescale(ImageIO.read(reference));
        } catch (IOException ex) {
        }
        
        photo.setLayout(new BorderLayout(0, 0));
        JLabel l = new JLabel();
        l.setHorizontalAlignment(SwingConstants.CENTER);
        l.setIcon(new ImageIcon(targetImg));
        photo.add(l);
        dialogGamer.setVisible(true);
        
    }
    
    public BufferedImage rescale(BufferedImage originalImage){
        BufferedImage resizedImage = new BufferedImage(baseSize, baseSize, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, baseSize, baseSize, null);
        g.dispose();
        return resizedImage;
    }
    
    private void helpMouseClicked(ActionEvent e) { 
    	if (!helping) {
    		new Thread() {
    			@Override
    			public void run() {
    				try {
    					helping = true;
    					showHelp();
    					Thread.sleep(5000);
    					hideHelp();
    					helping = false;
    				} catch (InterruptedException ex) {
    					System.out.println(ex);
    				}
    			}
    		}.start();
    	}
    }

    @SuppressWarnings("unused")
	private void titleKeyPressed(java.awt.event.KeyEvent evt) {
        if (evt.getKeyCode() == KeyEvent.VK_LEFT) {
            setLocation(getX() - 5, getY());
        }
        if (evt.getKeyCode() == KeyEvent.VK_RIGHT) {
            setLocation(getX() + 5, getY());
        }
        if (evt.getKeyCode() == KeyEvent.VK_UP) {
            setLocation(getX(), getY() - 5);
        }
        if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
            setLocation(getX(), getY() + 5);
        }
    }

    private void loadActionPerformed(java.awt.event.ActionEvent evt) {
		
        initGame();
    }

    private void playActionPerformed(java.awt.event.ActionEvent evt) {
        initGame();
    }

    @SuppressWarnings("unused")
	private void titleMouseDragged(java.awt.event.MouseEvent evt) {
        setLocation(evt.getXOnScreen() - 300, evt.getYOnScreen());
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                //do animation here if want
                //sleep here
                new MainFrame().setVisible(true);
            }
        });
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if (status == 0) {
            predict1 = (Card) e.getSource();
            predict1.showTile();
            status++;
        } else if (status == 1) {
            status++;
            predict2 = (Card) e.getSource();
            new Thread() {
                @Override
                public void run() {
                    try {
                        predict2.showTile();
                        Thread.sleep(500);
                        check();
                        Thread.sleep(600);
                        status = 0;
                    } catch (Exception e) {
                        System.out.println(e);
                    }
                }
            }.start();

        }
    }
}
class JPEGImageFileFilter extends FileFilter implements java.io.FileFilter{
	
	public boolean accept(File f){
		if (f.getName().toLowerCase().endsWith(".jpeg")) return true;
		if (f.getName().toLowerCase().endsWith(".jpg")) return true;
		if(f.isDirectory())return true;
		return false;
	}
	
	public String getDescription(){
		return "JPEG files/";
	}

}

As you noticed. This is the Main class that contains all functions and elements needed by our memory game to be works as expected.

Now we will create the other class named Card.java:

package view;

import javax.swing.ImageIcon;
import javax.swing.JButton;

/**
 *
 * @author elgarnaoui.com
 */
class Card extends JButton {

    ImageIcon icon1;
    ImageIcon icon2;
    private boolean noIcon;
    private boolean hidden;

    public Card(ImageIcon icon1, ImageIcon icon2) {
        this.icon1 = icon1;
        this.icon2 = icon2;
        setSize(100, 100);
        setFocusable(false);
    }

    public synchronized void showTile() {
        setIcon(icon1);
        hidden = false;
    }

    public synchronized void hideTile() {
        setIcon(icon2);
        hidden = true;
    }

    public synchronized void setNoIcon() {
        setIcon(null);
        noIcon = true;
    }

    public ImageIcon getImage() {
        return icon1;
    }

    public synchronized boolean isNoIcon() {
        return noIcon;
    }

}

This class is simple Java POJO to describe the Card Object used by our memory game.

Conclusion:

In this tutorial, we make a memory game using java and swing. In the next part, we will continue our work by making this game played with friends in the local network. And also we will make the configurations work as expected.

So, subscribe to our YouTube channel and our social media page to get notified of new tutorials coming soon.

To support us share this post with friends in social media, and if you have questions, let us know in the comment section.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *