重启扫雷GUI程序

时间:2015-03-13 02:16:20

标签: java swing user-interface button graphics

我做了一个非常像扫雷的GUI游戏,尽管逻辑要少得多。基本上,用户点击一个空格,看看下面是否有黄金,如果没有黄金,它会显示一个X.如果有,它会显示一块金币。我想让游戏重新开始,一旦用户找到10个金币,所有数据都会被重置。但是,我的do while循环没有成功。我已经注释掉了导致我出现问题的代码部分。每次我用我已经注释掉的东西运行程序时,它会卡住并且在我点击第一个按钮时不会继续运行。否则,随着这些东西的注释,它的工作原理应该如何。

问题:如果用户发现10个金币,如何重新启动程序并重置数据值?另外,为什么我的12x12按钮网格设置显示与我设置2D按钮阵列的方式不成比例?

以下是do while注释后游戏的样子:

public class NuggetPanel extends JPanel {

    // variable declaration
    boolean restartGame = false;
    JButton[][] buttons = new JButton[12][12];
    JButton restart = new JButton("You win! Click to restart game");
    int count = 0;
    int goldFound = 0;
    JLabel clickCount = new JLabel("Number of digs: " + count);
    JLabel goldCount = new JLabel("Gold found: " + goldFound);


    // sets up the panel
    public NuggetPanel() {

        setLayout(new GridLayout(12, 12, 2, 2));
        JPanel LabelPane = new JPanel();


        //creates 2D array of buttons
        for (int i = 0; i < buttons.length; i++) {
            for (int j = 0; j < buttons[i].length; j++) {
                buttons[i][j] = new JButton("");
                buttons[i][j].addActionListener(new buttonListener());
                add(buttons[i][j]);
            }

        }



        //adds components
        LabelPane.add(clickCount);
        LabelPane.add(goldCount);
        LabelPane.add(restart);
        add(LabelPane);
        restart.setVisible(false);
    }

    // button is clicked
    private class buttonListener implements ActionListener {    

        @Override
        public void actionPerformed(ActionEvent e) {

//  do{

            // finds which button was clicked
            JButton buttonClicked = (JButton) e.getSource();

            restartGame = false;
            restart.setVisible(false);


            // sets up gold array
            Boolean[] randomGold = new Boolean[144];

            // fills gold array with 10 true elements
            for (int i = 0; i < randomGold.length; i++) {
                randomGold[i] = false;

                // sets 10 indexes in the array to true
                if (i == 10 || i == 20 || i == 30 || i == 40 || i == 50 || i == 60 || i == 70 || i == 80 || i == 90 || i == 100) {
                    randomGold[i] = true;
                }
            }

            // randomizes gold array
            Collections.shuffle(Arrays.asList(randomGold));

            // iterates through button array
            for (int i = 0; i < buttons.length; i++) {

                for (int j = 0; j < buttons[i].length; j++) {

                    if (buttonClicked == buttons[i][j]) {

                        // if there is a gold under the square, shows gold icon
                        if (randomGold[i] == true) {
                            buttons[i][j].setIcon(new ImageIcon("./src/Gold.jpg"));
                            buttons[i][j].removeActionListener(this);
                            goldFound++;
                            count++;
                            clickCount.setText("Number of digs: " + count);
                            goldCount.setText("Gold found: " + goldFound + "  ");

                        }

                        // if there is no gold under the square, shows X
                        else {
                            buttons[i][j].removeActionListener(this);
                            buttons[i][j].setIcon(new ImageIcon("./src/Missed.png"));
                            count++;
                            clickCount.setText("Number of digs: " + count);
                            goldCount.setText("Gold found: " + goldFound);
                        }

//                      if (goldFound == 10) {
//                          restart.setVisible(true);
//                      }
//
//                      if (buttonClicked == restart) {
//                          count = 0;
//                          goldFound = 0;
//                          clickCount.setText("Number of digs: " + count);
//                          for (int x = 0; i < buttons.length; i++)
//                          {
//                              for(int y = 0; j < buttons[i].length; j++)
//                              {
//                                  buttons[x][y].setIcon(null);
//                              }
//                          }
//                          restartGame = true;
//                      }

                        j = buttons[i].length - 1;
                        i = buttons.length - 1;

                    }

                }
            }
//      } while(restartGame = true);
    }
}
}

1 个答案:

答案 0 :(得分:2)

  

另外,为什么我的12x12按钮网格设置显示与我设置2D按钮阵列的方式不成比例?

这是一个双重问题。 JButton具有margin属性,这些属性通常不是正方形。此外,当您向GridLayout添加组件时,所有组件的大小都相同,因此当您将LabelPane添加到布局时,它会强制所有按钮至少具有该组件的大小。宽度。

相反,使用GridLayout将您的按钮放到单独的面板上,然后使用NuggetPanel将此标签和LabelPanel放到BorderLayout上,例如...

    public NuggetPanel() {

        setLayout(new BorderLayout());

        JPanel buttonPane = new JPanel(new GridLayout(12, 12, 2, 2));
        //creates 2D array of buttons
        for (int i = 0; i < buttons.length; i++) {
            for (int j = 0; j < buttons[i].length; j++) {
                // nb: I'd use a "blank" icon which was the same
                // size as the other icons and set it as the 
                // buttons icon, this will ensure that the 
                // buttons are always the right size...
                buttons[i][j] = new JButton("");
                buttons[i][j].setMargin(new Insets(5, 5, 5, 5));
                buttons[i][j].addActionListener(new buttonListener());
                buttonPane.add(buttons[i][j]);
            }

        }

        //adds components
        JPanel LabelPane = new JPanel();
        LabelPane.add(clickCount);
        LabelPane.add(goldCount);
        LabelPane.add(restart);

        add(buttonPane);
        add(LabelPane, BorderLayout.SOUTH);

        restart.setVisible(false);
    }
  

如果用户发现10个金币,如何重新启动程序并重置数据值?

这是一个更复杂的问题,需要您改变思路。

单击每个ANY按钮时将调用

actionPerfomed,但您正在做的是随机化黄金的位置......这将使用户几乎无法获胜。为什么?因为可以在按钮下面放一块金子,而这个按钮已经被检查过了......

    @Override
    public void actionPerformed(ActionEvent e) {

        // finds which button was clicked
        JButton buttonClicked = (JButton) e.getSource();

        restartGame = false;
        restart.setVisible(false);

        // sets up gold array
        Boolean[] randomGold = new Boolean[144];

        // fills gold array with 10 true elements
        for (int i = 0; i < randomGold.length; i++) {
            randomGold[i] = false;

            // sets 10 indexes in the array to true
            if (i == 10 || i == 20 || i == 30 || i == 40 || i == 50 || i == 60 || i == 70 || i == 80 || i == 90 || i == 100) {
                randomGold[i] = true;
            }
        }

        // randomizes gold array
        Collections.shuffle(Arrays.asList(randomGold));

相反,创建一个可用于重置或初始化游戏状态的方法......

    protected void reset() {
        // sets up gold array
        randomGold = new Boolean[144];

        // fills gold array with 10 true elements
        for (int i = 0; i < randomGold.length; i++) {
            randomGold[i] = false;

            // sets 10 indexes in the array to true
            if (i == 10 || i == 20 || i == 30 || i == 40 || i == 50 || i == 60 || i == 70 || i == 80 || i == 90 || i == 100) {
                randomGold[i] = true;
            }
        }

        // randomizes gold array
        Collections.shuffle(Arrays.asList(randomGold));

        for (int i = 0; i < buttons.length; i++) {
            for (int j = 0; j < buttons[i].length; j++) {
                // Reset the image icon with a blank image...
                buttons[i][j].setText("");
                buttons[i][j].setEnabled(true);
            }

        }
    }

这也应该在构造函数的末尾调用。这将确保游戏处于就绪状态......

使用buttons[i][j].removeActionListener(this);简单地将按钮设置为禁用,而不是使用buttons[i][j].setEnabled(false);,这样可以更轻松地重置按钮,因为您不需要关心按钮是否已经有与之关联的ActionListener(可能会导致您的actionPerformed方法多次被调用一个按钮:P)

actionPerformed方法结束时,您只需检查goldFound的数量,然后致电reset重置游戏......

if (goldFound == 10) {
    JOptionPane.showMessageDialog(NuggetPanel.this, "You win");
    reset();
}

附加...

请勿使用类似......

之类的内容从src目录加载资源
 buttons[i][j].setIcon(new ImageIcon("./src/Missed.png"));

一旦构建代码,这将失败。相反,您需要将资源作为嵌入式资源引用,并使用Class#getResource

 buttons[i][j].setIcon(new ImageIcon(getClass().getResource("/Missed.png")));

但坦率地说,这有点浪费,相反,你可以将图标定义为常量....

public static final ImageIcon MISSED_ICON = new ImageIcon(getClass().getResource("/Missed.png")));

然后在你需要的时候简单地引用它......

 buttons[i][j].setIcon(MISSED_ICON);

就我个人而言,我更喜欢ImageIO.read,因为它会抛出IOException,但它会使设置常量变得更加复杂......

另外,我可能会考虑使用某种List来管理按钮和&#34; gold&#34;这些位置只是使用List#indexOf(Object),然后每次都要经历双循环......