我做了一个非常像扫雷的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);
}
}
}
答案 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)
,然后每次都要经历双循环......