记忆游戏实现 [英] Memory Game implementation

查看:28
本文介绍了记忆游戏实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始玩一个非常基本的记忆游戏.

I have started on a really basic memory game.

private void tbtnCard3ActionPerformed(java.awt.event.ActionEvent evt) {                                          
    tbtnCard3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
    if(tbtnCard5.isSelected()){
        score++;
        lblScore.setText(""+score);
    }
}                                         

private void tbtnCard4ActionPerformed(java.awt.event.ActionEvent evt) {                                          
     tbtnCard4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card7EWaste.png")));
    if(tbtnCard7.isSelected()){
        score++;
        lblScore.setText(""+score);
    }
}                                         

private void tbtnCard5ActionPerformed(java.awt.event.ActionEvent evt) {                                          
     tbtnCard5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
    if(tbtnCard3.isSelected()){
        score++;
        lblScore.setText(""+score);
    }
}                                         

使用 Java Swing,我已经用我需要的图像设置了图标.在底部,我有一个按钮调用 start 以便首先显示所有按钮,直到按下 start btn.

Using Java Swing, I have set the icons with the images I need. Over at the bottom I have a button call start so that at first all buttons are shown until start btn is pressed.

 private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {                                         
  tbtnCard1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png"))); 
  tbtnCard4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard6.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));   
  tbtnCard7.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard8.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard9.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard11.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard12.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard13.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard14.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard15.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png"))); 
  tbtnCard16.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard17.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
  tbtnCard18.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));   
  tbtnCard19.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));  
  tbtnCard20.setIcon(new javax.swing.ImageIcon(getClass().getResource("/BlankImage.png")));    
}  

我唯一的问题是在玩家从一组 2 张中选错了一张牌后,两张牌都应该回到空白图像.我该怎么做?

My only question is after a player picks a wrong card from a set of 2,both cards should go back to the blank image. How would I go about that?

推荐答案

以下是一个简单记忆游戏的示例逻辑:

Here is a sample logic for a simple memory game:

  1. 使用 JToggleButtons 来表示单元格.
  2. 将每个按钮的图标用于隐藏状态,以及选择图标,用于显示状态.
  3. 首先启用所有 JToggleButton 并且未选中(隐藏 状态).
  4. 当用户选择一个 JToggleButton 时,它会自动更改为 shown 状态.
  5. 向所有 JToggleButton 添加相同的侦听器,以便随时跟踪最后两个选定的按钮.如果找到匹配项,则您可以禁用匹配按钮,如果未找到匹配项,则只需取消选择它们即可.
  1. Use JToggleButtons to represent the cells.
  2. Use the icon of each button for the hidden state, and the selection icon for the shown state.
  3. Start with all JToggleButtons enabled and not selected (hidden state).
  4. When the user selects a JToggleButton it changes to shown state automatically.
  5. Add the same listener to all JToggleButtons which will track the last two selected buttons at any time. If a match is found then you can disable the matching buttons, if no match is found then simply unselect them.

为了在下面的演示代码中简单起见,我为上述所有目的使用了一个自定义的 Icon 实现,它只是绘制了一个某种颜色的圆角矩形.颜色用于将按钮标识为彼此匹配,即相同颜色的按钮表示选择了匹配.我只是在 隐藏 状态下为每个按钮使用了一个白色的圆角矩形,而在 显示 状态下使用了随机颜色.

For simplicity in the following demonstrating code, I used a custom Icon implementation for all above purposes which just draws a rounded rectangle of some color. The color is used to identify the buttons as matching with each other, ie same colored buttons means a match was selected. I just used a rounded rectangle of white color for each button at the hidden state, while random colors for the shown state.

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Random;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Main {
    
    private static class RoundRectIcon implements Icon {
        private final Color c;
        
        public RoundRectIcon(final Color c) {
            this.c = Objects.requireNonNull(c);
        }
        
        public Color getColor() {
            return c;
        }

        @Override
        public void paintIcon(final Component c,
                              final Graphics g,
                              final int x,
                              final int y) {
            g.setColor(this.c);
            g.fillRoundRect(x, y, getIconWidth() - 1, getIconHeight() - 1, getIconWidth() / 2, getIconHeight() / 2);
        }

        @Override
        public int getIconWidth() {
            return 50;
        }

        @Override
        public int getIconHeight() {
            return 50;
        }
    }
    
    private static class MemoryGameActionListener implements ActionListener {
        
        private final Timer revertTimer;
        private JToggleButton button1, button2;
        private int pairsCount;
        
        public MemoryGameActionListener(final int delay,
                                        final int pairsCount) {
            if (pairsCount <= 0)
                throw new IllegalArgumentException("Non positive pairsCount.");
            this.pairsCount = pairsCount;
            button1 = button2 = null;
            revertTimer = new Timer(delay, this);
            revertTimer.setRepeats(false);
        }
        
        @Override
        public void actionPerformed(final ActionEvent e) {
            revertTimer.stop();
            final Object source = e.getSource();
            if (source instanceof JToggleButton) {
                final JToggleButton button = (JToggleButton) source;
                if (button.isSelected()) {
                    if (button1 == null) //If we are in an initial state:
                        button1 = button; //Store the first clicked button.
                    else if (button2 == null) { //Else we have stored the first button, so store and check the second one...
                        button2 = button;
                        final RoundRectIcon icon1 = (RoundRectIcon) button1.getSelectedIcon(),
                                            icon2 = (RoundRectIcon) button2.getSelectedIcon();
                        if (Objects.equals(icon1.getColor(), icon2.getColor())) {
                            System.out.println("Pair of " + icon1.getColor() + " found!");
                            button1.setEnabled(false); //Don't let the user able to click it again.
                            button2.setEnabled(false); //Don't let the user able to click it again.
                            button1 = button2 = null; //A cycle is complete.
                            if (--pairsCount == 0)
                                JOptionPane.showMessageDialog(null, "You found every pair.", "You win", JOptionPane.INFORMATION_MESSAGE);
                        }
                        else {
                            System.out.println("Invalid match of " + icon1.getColor() + ", and " + icon2.getColor() + '.');
                            revertTimer.start(); //This timer will unselect the selected button pair after a delay.
                        }
                    }
                    else { //Else both buttons are stored, so this is the third one, so just ignore the previous buttons (if they did not match):
                        if (button1.isEnabled())
                            button1.setSelected(false);
                        if (button2.isEnabled())
                            button2.setSelected(false);
                        button1 = button; //Suppose now that the third clicked button is the first one.
                        button2 = null;
                    }
                }
                else { //Else the user unselected a button, so reset:
                    if (button1 != null) {
                        button1.setSelected(false);
                        button1 = null;
                    }
                    if (button2 != null) {
                        button2.setSelected(false);
                        button2 = null;
                    }
                }
            }
            else if (source == revertTimer) { //If a pair was found previously but it didn't match up, then reset:
                button1.setSelected(false);
                button2.setSelected(false);
                button1 = button2 = null;
            }
            else
                System.err.println("Unknown source " + source); //This should never happen.
        }
    }
    
    private static Color randomColor(final Random random) {
        final byte[] components = new byte[3];
        random.nextBytes(components);
        return new Color(components[0] & 0xFF, components[1] & 0xFF, components[2] & 0xFF);
    }
    
    private static HashSet<Color> randomUniqueColors(final int count) {
        final Random random = new Random();
        final HashSet<Color> colors = new HashSet<>(count);
        while (colors.size() < count) //If we produce the same color inside the loop, then 'colors.size()' will not increment.
            colors.add(randomColor(random));
        return colors;
    }
    
    private static JToggleButton createStandardToggleButton(final Color color,
                                                            final MemoryGameActionListener listener) {
        final JToggleButton toggle = new JToggleButton(new RoundRectIcon(Color.WHITE)); //Default (ie enabled + unselected) icon is just a white round rect.
        toggle.setSelectedIcon(new RoundRectIcon(color));
        toggle.setDisabledIcon(toggle.getSelectedIcon());
        toggle.setDisabledSelectedIcon(toggle.getSelectedIcon());
        toggle.addActionListener(listener);
        return toggle;
    }
    
    private static void createAndShowGUI() {
        
        final int rows = 4, cols = 4, delay = 1000;
        
        final int totalButtons = rows * cols; //The total number of buttons must be a multiple of 2 (because we use pairs of buttons).
        final int totalPairs = totalButtons / 2;
        final MemoryGameActionListener listener = new MemoryGameActionListener(delay, totalPairs);
        final JPanel grid = new JPanel(new GridLayout(0, cols, 5, 5));
        final ArrayList<JToggleButton> buttons = new ArrayList<>(totalButtons);
        randomUniqueColors(totalPairs).forEach(color -> {
            //Add the matching buttons to the list...
            buttons.add(createStandardToggleButton(color, listener));
            buttons.add(createStandardToggleButton(color, listener));
        });
        Collections.shuffle(buttons);
        buttons.forEach(button -> grid.add(button));
        
        final JFrame frame = new JFrame("Memory game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(grid);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(Main::createAndShowGUI);
    }
}

我首先生成所需颜色数量的Set,然后为每种颜色创建两个按钮,然后将它们打乱,最后将它们添加到JPanelJPanel>GridLayout.

I first generate a Set of the desired number of colors, then create two buttons for each color, then shuffle them and finally add them to a JPanel of GridLayout.

上面的示例代码可以很容易地调整以容纳您喜欢的任何Icon,当然包括ImageIcons 和其他自定义的.

The above example code can be easily tweaked to hold any Icon you like, which of course includes ImageIcons and other custom ones.

这篇关于记忆游戏实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆