做了个小游戏,有bug,半天也没找到
本帖最后由 huijiaba99 于 2012-11-01 15:37:05 编辑 是个数字记忆游戏,现在的问题出在,第一关过关后,自动跳到第二关,却不能正确显示数字了。
初接触JAVA,找了很久还是没有搞定,希望大神能帮忙检查一下…
因为代码略长,我分成了2层楼。(整个代码是一个文件)
代码如下:
import java.awt.*;
import java.awt.event.*;
import java.util.*; // for Random and ArrayList
import javax.swing.*; // obviously a lot of swing
import javax.swing.event.MouseInputListener;
// 游戏玩法:点击开始游戏后,会出现若干个圈子,每个圈子内显示一个1-N的数字,
// 记住这些数字,因为在若干秒后,数字会消失,你需要做的,就是按从小到大的顺序,
// 依次点击这些圈子,如果顺序正确,恭喜你,过关了~~
class GameConfig extends JDialog implements ActionListener
{
private JLabel lblSetTime = new JLabel("设置时间(单位秒):");
private JLabel lblSetLim = new JLabel("设置数字范围:1 - ");
private JTextField txtTime=new JTextField(Double.toString(GuessWhereAreTheNumbers.remtime));
private JTextField txtLim=new JTextField(Integer.toString(GuessWhereAreTheNumbers.lim));
private JButton btnCon = new JButton("确定");
private JButton btnReset = new JButton("重置");
GameConfig()
{
//super("配置游戏");
JPanel panel = new JPanel(new GridLayout(3, 2)); // grid布局用玉显示各种label
panel.setBackground(Color.WHITE);
panel.add(lblSetTime);
panel.add(txtTime);
panel.add(lblSetLim);
panel.add(txtLim);
panel.add(btnCon);
panel.add(btnReset);
add(panel,BorderLayout.CENTER);
setModal(true);
btnCon.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
// 保存设置
GuessWhereAreTheNumbers.remtime=Double.parseDouble(txtTime.getText());
GuessWhereAreTheNumbers.lim=Integer.parseInt(txtLim.getText());
dispose();
}
});
}
@Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
}
}
public class GuessWhereAreTheNumbers extends JFrame implements Runnable,
ActionListener
{
private static final int NB_ROWS = 5, NB_COLS = 7; // 共有几行几列
static double remtime = 1.5; // 记忆时间
static int lim = 9; // 范围9-99
static int score = 0; // 得分,初始为0
static int cirnum = 4;
private CircleLabel[][] label = new CircleLabel[NB_ROWS][NB_COLS]; // 这个标签代表圈(带有数字的或者不带数字的)
private Random random = new Random(); // 随机显示数字和数字的位置
private BottomPanel bottomPanel; // Panel1,用于放多选按钮和开始按钮
private JButton btnStart = new JButton("开始游戏"); // 开始按钮
private JButton btnConf = new JButton("配置游戏");
private JButton btnRank = new JButton("排行榜");
private JButton btnHelp = new JButton("游戏帮助"); // 帮助
private JButton btnExit = new JButton("退出游戏"); // 退出按钮
private JLabel statusLabel = new JLabel("\n"); // 显示成功、失败的标签
// the array of the labels in the game (the ones that hold a number from 0
// to 9)
private CircleLabel[] cl; // 显示数字的标签
private int nbClicked; // the number of labels correctly clicked
GuessWhereAreTheNumbers()
{
super("猜数字~~");
setBackground(Color.RED); // 默认是白色的
// 顶部状态标签
statusLabel.setHorizontalAlignment(SwingConstants.CENTER);
// 设置颜色
statusLabel.setForeground(Color.BLUE);
statusLabel.setBackground(Color.YELLOW);
add(statusLabel, BorderLayout.NORTH); // 放在最上方
JPanel panel = new JPanel(new GridLayout(NB_ROWS, NB_COLS)); // grid布局用玉显示各种label
panel.setBackground(Color.WHITE);
// 把labels填入panel
for (int j = 0; j < NB_COLS; j++)
{
for (int i = 0; i < NB_ROWS; i++)
{
label[i][j] = new CircleLabel(i, j);
label[i][j].setFont(new Font("宋体", 1, 50)); // (1是粗体,0是平常的),字号40
panel.add(label[i][j]);
}
}
add(panel, BorderLayout.CENTER); // 显示在布局的最中间
bottomPanel = new BottomPanel(this); // 底部用于放置单选按钮和按钮的button
add(bottomPanel, BorderLayout.SOUTH); // 显示在布局的最底部
// set size (a little more pixel on the Y axis for bottom and top panel)
// and default close operation
setSize(NB_COLS * 80, NB_ROWS * 80 + 50); // 设置窗口尺寸,上面的状态栏和下面的按钮多占用一部分空间
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 点击X后会释放内存
setVisible(true);
}
// 显示数字并隐藏数字的线程
public void run()
{
btnStart.setEnabled(false); // 游戏开始后,设置“开始游戏”按钮失效
nbClicked = 0; // label被点击次数
// erase the status label from the last game
statusLabel.setText("\n"); // 清除上局游戏的状态
// fill an ArrayList with all the available labels so we can picj them
// randomly
ArrayList<CircleLabel> al = new ArrayList<CircleLabel>();
for (int j = 0; j < NB_COLS; j++)
{
for (int i = 0; i < NB_ROWS; i++)
{
label[i][j].setValue(-1); // 清空标签上的文本
al.add(label[i][j]); // 装入al
}
}
// get the number of numbers/circles to display (depending of the
// JButton selected in the bottomPanel)
int nbToShow = cirnum; // 获取用户选择的数字数量
// an array of the labels which will be displayed
cl = new CircleLabel[nbToShow]; // 显示的label数量
// another ArrayList to determine the value that will be shown in the
// label
ArrayList<Integer> oneToNine = new ArrayList<Integer>(); // 放在圈中的数字
for (int i = 0; i <= lim; i++)
{
oneToNine.add(i);
}
// pickup randomly nbToShow labels 选N个数字出来
for (int i = 0; i < nbToShow; i++)
{
cl[i] = al.remove(random.nextInt(al.size()));
// get a random value for it
int val = oneToNine.remove(random.nextInt(oneToNine.size()));
// set these value to the label
cl[i].setValue(val);
}
// wait for the user to remember the number
try
{
Thread.sleep((int) remtime * 1000); // 等待时间
} catch (Exception e)
{
throw new IllegalStateException("Thread.Sleep() failed for " + e);
}
// 然后数字消失,只显示圈圈
for (int i = 0; i < nbToShow; i++)
{
cl[i].setCircleOnly();
}
// sort the labels by their values so I can check if they are clicked in
// the good order
Arrays.sort(cl); // 排序~~
}
// we'll be called when the button "GO" will be clicked
public void actionPerformed(ActionEvent e) // 开始游戏,启动此线程
{
Thread thread = new Thread(this);
thread.start();
}
// just to start the application
public static void main(String[] args)
{
// one instance of our stuff
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GuessWhereAreTheNumbers();
}
});
}
// a special version of JLabel. It can display a number or a circle or an X
// or nothing
// it has a mouseInputListener and implements Comparable so they can be
// sorted in order of Value
class CircleLabel extends JLabel implements MouseInputListener,
Comparable<CircleLabel>
{
// tne number it holds (-1) in no value
int value;
// the String representation of the number to display
String valueToDisplay = "";
// if I should display the X wrong answer
boolean displayX = false;
// my coordinates within the Panel
int x, y;
// constructor
CircleLabel(int x, int y)
{
super("");
// save position on grid
this.x = x;
this.y = y;
// do not display the X
displayX = false;
// no value
valueToDisplay = "";
value = -1;
this.setHorizontalAlignment(SwingConstants.CENTER);
// and the mouse listener
this.addMouseListener(this);
}
// to set the value of the label
void setValue(int val)
{
// value in int
value = val;
if (value == -1)
{
valueToDisplay = ""; // 清空标签内的数字
} else
{
// as a String so repaint can use it
valueToDisplay = "" + val;
}
setText(valueToDisplay); // value used by repaint
displayX = false; // init we do not display an X over the label
// set foreground value to BLUE in case last game set it to RED
setForeground(Color.BLUE);
}
// now display only circle
void setCircleOnly()
{
// text reset to nothing
setText("");
}
// the paint method: we overload the standard one in case we have to
// draw an X
public void paint(Graphics g)
{
// always call my father in case I have text to display
super.paint(g);
// if an empty label, not selected for that game I exit
if (value == -1)
{
return;
}
// draw a circle around it
// get size of label
Dimension dim = getSize();
// get size of circle 1/6 of label size
int width = dim.width / 6;
int height = dim.height / 6;
// draw the circle in black
g.setColor(Color.BLACK);
g.drawOval(width, height, width * 5, height * 5);
// test if we have to display the X
if (displayX)
{
// OK just another color to be fancier
g.setColor(Color.GREEN);
// from the leftmost uppercorner to rightmost lower corner
g.drawLine(0, 0, dim.width, dim.height);
// from rightmost upper corner to leftmost lower corner
g.drawLine(dim.width, 0, 0, dim.height);
}
}
[解决办法]
测试了以下,进入下一轮应启动线程,而不是简单的run().
修改一下,我测试可以了。
把类CircleLabel的方法 public void mouseClicked(MouseEvent e)里的语句run() 改成:
new Thread(GuessWhereAreTheNumbers.this).start();
[解决办法]
首先赞同一下3楼的。那个run()感觉应该是一个静态的方法,里面包含启动一个新线程的方法。
代码很整洁,个人感觉应该是照着例子写的吧?(别介意,只是感觉,新手写的代码一般都很乱的)
我也是一个新手,同样也在做一个射击类型的小游戏。在网上等待别人帮忙调错是很慢的,技术上的却是得请别人帮忙,可逻辑上的错误一般是自己可以解决的。
你说“第一关过关后,自动跳到第二关,却不能正确显示数字了。”
那你就加一个system.out.println("测试");语句放到运行第二关的线程程序中,看看控制台是否打印就知道是不是线程未启动的错误了。如果运行,那就是Jpanel显示的问题。
另外说明一下,对于错误的描述尽可能的多一些,这样利于判断错误的原因。
[解决办法]
自己学会调试!才是王道,我弄得qq半个月了,每天一个错误,要很久久 才会调试出来正如楼上说的
System.out.println("hello");
看程序进入了那部分,