×

Search anything:

Memory Game in Java

Binary Tree book by OpenGenus

Open-Source Internship opportunity by OpenGenus for programmers. Apply now.

Memory games are popular brain-training exercises designed to challenge and improve our memory and cognitive abilities. These games typically involve matching pairs of identical items hidden among a set of cards or tiles, which are then shuffled and placed face down. Players must remember the position of each item and make matches by turning over two cards at a time. The objective is to find all the matching pairs by memorizing the location of the items in the shortest time and with the fewest attempts.

In this article at OpenGenus, we will explore the concept of memory games and analyze a sample implementation of a memory game in Java using the provided code. This implementation demonstrates how a simple GUI-based memory game can be created using Java's Swing library. The game features a grid of buttons, each assigned a random color from a predefined set of colors. Players must find matching pairs by flipping over the buttons and remembering their locations.

Table of Contents

  1. The Structure of the Memory Game Implementation
  2. Implementation of the Memory Game Logic
  3. How to Play the Game
  4. Improvements and suggestions
  5. Conclusion

The Structure of the Memory Game Implementation

The provided Java code defines a MemoryGame class that creates a graphical user interface (GUI) to display the memory game. The implementation follows the Model-View-Controller (MVC) design pattern, where the game logic, UI elements, and user interactions are separated into distinct components.

The core components of the memory game implementation are as follows:

  1. Model: The model represents the game's data and state. In this implementation, the model is relatively simple, as it primarily involves managing the color assignments for the buttons.

  2. View: The view represents the visual presentation of the game. In this implementation, the view is built using Swing components, such as JFrame, JPanel, and JButton. These components create the graphical layout for the game, including the grid of buttons.

  3. Controller: The controller manages the game's logic and user interactions. It handles actions like button clicks, checking for matching pairs, updating the score, and restarting the game. In this implementation, each button on the grid has an associated AbstractAction, which is a custom class that handles the button's behavior when clicked.

Implementing the Memory Game Logic

The MemoryGame class begins with the main method, which initializes the game and starts the GUI by calling the runGame method. The runGame method sets up the main application frame, initializes the colors, creates the grid of buttons, and establishes the game's visual layout.

private static final int APPLICATION_SIZE = 400;
    private static final Color BACKGROUND = new JLabel().getBackground();
    private int score = 0;
    public static void main(String[] args) {
        new MemoryGame().runGame();
    }
    private void runGame() {
        JFrame application = new JFrame("color game");
        application.setTitle("Memory Game ");
        JLabel scoreLabel = new JLabel("score: " + score);
        JLabel timeLabel = new JLabel("time: " + formatTime(timeElapsed));
        List<Color> colors = Arrays.asList(Color.BLUE, Color.CYAN, Color.RED, Color.YELLOW, Color.GREEN, Color.BLACK);
        fieldCells = initializeGame(colors); // Store the original game board state
        JPanel gameFiled = initializeView(fieldCells);
        bindViewToModel(colors, fieldCells, scoreLabel);
        JPanel gameControl = setupController(colors, fieldCells, application, scoreLabel, timeLabel);
        application.getContentPane().add(gameFiled);
        application.getContentPane().add(gameControl, BorderLayout.SOUTH);
        application.setSize(APPLICATION_SIZE, 400);
        application.setVisible(true);

        Timer timer = new Timer(1000, e -> {
            timeElapsed++;
            timeLabel.setText("time: " + formatTime(timeElapsed));
        });
        timer.start();
    }

The initializeGame method is responsible for creating the list of buttons and assigning two buttons to each color in random order. This method ensures that each color has two matching buttons in the grid.

private List<JButton> initializeGame(Collection<Color> colors) {
        List<JButton> fieldCells = new ArrayList<>();
        for (Color color : colors) {
            fieldCells.add(new JButton()); // two buttons per color
            fieldCells.add(new JButton());
        }
        return fieldCells;
    }

Next, the initializeView method organizes the buttons in a 4x4 grid layout. Each button is set with a background color corresponding to BACKGROUND, which is initialized to the background color of a JLabel.

private JPanel initializeView(List<JButton> fieldCells) {
        JPanel gameFiled = new JPanel(new GridLayout(4, 0));
        for (JButton fieldCell : fieldCells) {
            fieldCell.setBackground(BACKGROUND);
            fieldCell.setEnabled(true);
            gameFiled.add(fieldCell);
        }
        return gameFiled;
    }

The setupController method creates the control panel at the bottom of the frame, containing the "Restart" and "Quit" buttons. The "Restart" button allows the player to reset the game and shuffle the colors, while the "Quit" button terminates the application.

private JPanel setupController(List<Color> colors,
            List<JButton> fieldCells,
            JFrame application,
            JLabel scoreLabel) {
        JPanel gameControl = new JPanel(new GridLayout(1, 0));
        gameControl.add(new JButton(new AbstractAction("restart") {
            @Override
            public void actionPerformed(ActionEvent e) {
                bindViewToModel(colors, fieldCells, scoreLabel);
            }
        }));
        gameControl.add(scoreLabel);
        gameControl.add(new JButton(new AbstractAction("quit") {
            @Override
            public void actionPerformed(ActionEvent e) {
                application.dispose();
            }
        }));
        return gameControl;
    }

The main logic of the memory game lies in the createButtonAction method. This method defines the behavior of the buttons when clicked. The ColorAction class, an implementation of AbstractAction, handles the flipping of buttons and checking for matching pairs. It maintains the state of each button, whether it is flipped or not, and performs the necessary actions when a pair of buttons is clicked.

In the createButtonAction method, the clicked buttons are stored in a HashSet, and when two buttons are flipped, their colors are checked to determine whether they form a matching pair. If they do, the player's score is increased, and the buttons remain disabled. If the colors do not match, the buttons are flipped back to their original state, and the score is decreased.

private AbstractAction createButtonAction(Collection<JComponent> clickedButtons, Color color, JLabel scoreLabel) {
        @SuppressWarnings("serial")
		AbstractAction buttonAction = new AbstractAction() { // Controller
            Collection<JComponent> clickedPartners = new HashSet<>(); // also Model
            @Override
            public void actionPerformed(ActionEvent e) {
                JComponent thisButton = (JComponent) e.getSource();
                clickedPartners.add(thisButton);
                clickedButtons.add(thisButton);
                thisButton.setBackground(color);
                thisButton.setEnabled(false);
                if (2 == clickedButtons.size()) { // is second clicked
                    if (2 == clickedPartners.size()) { // user found partner
                        score += 10;
                    } else {
                        JOptionPane.showMessageDialog(thisButton, "no match");
                        for (JComponent partner : clickedButtons) {
                            partner.setBackground(BACKGROUND);
                            partner.setEnabled(true);
                        }
                        score--;
                    }
                    clickedButtons.clear();
                    clickedPartners.clear();
                    scoreLabel.setText("score: "+ score);
                }
            }
        };
        return buttonAction;
    }

How to Play the Game

When the game starts, a grid of face-down buttons appears, each concealing one of several distinct colors. The player clicks two buttons in succession, which reveals the colors. If the revealed colors match, the buttons remain face up and the player scores points 10. Otherwise, the buttons flip back over, and a penalty point is deducted 1 point.

Screen-Shot-2023-08-06-at-5.40.41-PM

In this picture example, the two cards are not the same color. The game will notify the player that the two cards are not matching. When the player click "OK", they will be deducted one point.

Screen-Shot-2023-08-06-at-5.43.39-PM
Screen-Shot-2023-08-06-at-5.45.40-PM

In this image, the player lost 4 points, and when there is a match, they are added 10 points.

Screen-Shot-2023-08-06-at-5.46.27-PM

The game continues as players strategically remember the locations of colors and try to uncover matching pairs. The score is calculated based on successful matches and errors. Additionally, a timer displays the elapsed time, creating an element of urgency. Players can restart the game at any time to reset the grid, the timer, and the score.

The game combines memory, visual recognition, and decision-making skills, offering an engaging and challenging experience as players aim to achieve the highest score while revealing all color pairs.

Improvements and Suggestions

While the current implementation provides a basic memory game experience, there are several ways to enhance and expand the game:

  1. Difficulty Levels: Implement multiple difficulty levels by increasing the grid size or adding more colors. As the grid size increases, the game becomes more challenging, stimulating the player's memory even further.

  2. Timer: Add a timer to track the player's performance. Timing the game increases the sense of urgency and encourages players to improve their memory and matching speed.

  3. Sounds and Visual Effects: Incorporate sound effects and animations when the player makes matches or flips the cards, making the game more engaging and enjoyable.

  4. High Scores: Implement a scoring system to track and display high scores, motivating players to achieve better results in subsequent games.

  5. Single-Player vs. Multiplayer: Create options for single-player and multiplayer modes. In a multiplayer mode, players can take turns finding matching pairs.

  6. Different Card Themes: Introduce various card themes, such as animals, fruits, or numbers, to add variety and appeal to different age groups and interests.

Conclusion

Memory games are an excellent way to exercise and improve cognitive abilities, especially memory, concentration, and attention. The sample memory game implementation in Java demonstrates a basic GUI-based memory matching game. Players can enjoy flipping over the buttons and finding matching pairs of colors, accompanied by a simple scoring system.

To expand and enhance the game, developers can introduce various features such as difficulty levels, timers, sound effects, and multiple card themes. These additions will increase the game's challenge and enjoyment, making it suitable for players of all ages.

Overall, memory games are not only fun and entertaining but also valuable tools for maintaining and improving mental agility and memory skills. Whether played for leisure or as part of a cognitive training regimen, memory games offer a rewarding and engaging experience for players worldwide.

Memory Game in Java
Share this