初学多线程,求教(九格子游戏)

东门吹雪 2011-09-02 11:35:11


/*九格子游戏。请编写多线程游戏,设计一个3*3的格子(每个格子对应一个按钮)。
* 每个格子上对应一个线程,格子上文字只能是A、X或H,而且刚好只有一个格子上是H。
* 其中,H表示人在该格子上,A表示当前的格子是安全的,X表示不安全。每个格子如果不是文字H,
* 则每过一段时间就切换其上的文字A与X。只能单击H所在的格子的上下左右按钮。如果单击的格子当时的文字是A,
* 则单击的格子的文字变成H,而H原来所在格子的文字变为A(然后进行A与X的文字切换)。如果单击的格子当时是
* 文字X,则gameover,如果文字H在每个格子上都出现过,则Pass。*/

/*題目要求是每个按钮对应一个线程,我只用了一个线程,就当着和main方法是多线程吧。
* 现在的问题是程序刚开始运行正常,过一段时间(可能需要3~4分钟)会抛出数组越界和空指针的异常,
* 我想可能是对按钮的处理出现的问题,由于我刚学一个月,周围也没人交流,所以望各位大虾大牛不吝赐教啊,
* 占用您宝贵的时间感到万分抱歉,THX*/

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;

class J_NineGrid extends JFrame
{
static JButton [][] b = {{new JButton("1"), new JButton("2"), new JButton("3")},
{new JButton("4"), new JButton("5"), new JButton("6")},
{new JButton("7"), new JButton("8"), new JButton("9")}};

int [][] flag= new int[3][3];
Container c = getContentPane();

public J_NineGrid()
{
super("NineGridGame");

c.setLayout(new FlowLayout());

int [] list = {1, 0, 1, 0, 1, 0, 1, 0, 2};
int [] rList = getList(list); // 随机序列,用于初始化面板
String bText;

for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
{
if (rList[i*3+j] == 1)
bText = "A";
else if (rList[i*3+j] == 0)
bText = "X";
else
bText = "H";

b[i][j].addActionListener(new ActionListener() // 响应按钮事件
{
int cx , cy; // 当前按下按钮的坐标
int bx , by; // H按钮的坐标
boolean tag;

public void actionPerformed(ActionEvent e)
{
JButton cButton = (JButton)e.getSource();
cx = Integer.parseInt(cButton.getName())/3;
cy = Integer.parseInt(cButton.getName())%3;

for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
{
if (b[i][j].getText() == "H")
{
bx = i;
by = j;
flag[i][j] = 1;
break;
}
}

if (cButton.getText() != "H")
{
if (Math.abs(bx-cx)+Math.abs(by-cy) == 1) // 判断是否是H按钮的上下左右按钮
{
if (cButton.getText() == "X")
System.out.println("Fail");
else if (cButton.getText() == "A")
{
cButton.setText("H");
b[bx][by].setText("A");
flag[cx][cy] = 1;
}
}
}

tag = true;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
{
if (flag[i][j] == 0)
tag = false;
}
if (tag)
System.out.println("Pass(@_@)");
}
});

b[i][j].setText(bText); // set button text
b[i][j].setName(""+(i*3+j)); // set button name
c.add(b[i][j]);
}
}

public void ChangeName()
{
String bText = "";
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
{
if(b[i][j].getText() == "A")
{
bText = "X";
}
else if(b[i][j].getText() == "X")
{
bText = "A";
}
else if(b[i][j].getText() == "H")
{
bText = "H";
}

b[i][j].setText(bText); // set button text
c.add(b[i][j]);
}
}

public int[] getList(int[] list) // 产生随机序列
{
int count = list.length;
int [] resultList = new int[count];
LinkedList<Integer> temp = new LinkedList<Integer>();
for (int i=0; i<count; i++)
{
temp.add((Integer)list[i]);
}

Random rand = new Random();
for (int i=0; i<count; i++)
{
int num = rand.nextInt(count - i);
resultList[i] = (Integer)temp.get(num);
temp.remove(num);
}

return resultList;
}
}

class T_ChangeName extends Thread
{
J_NineGrid game2;

public T_ChangeName(J_NineGrid game)
{
game2 = game;
}

public void run()
{
System.out.println("Begin");
for ( ; true; )
{
game2.ChangeName();
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}

public class J_NineGridGame
{
public static void main(String args[])
{
J_NineGrid game = new J_NineGrid();
game.setLocationRelativeTo(null);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setSize(150, 150);
game.setVisible(true);

T_ChangeName thread = new T_ChangeName(game);
thread.start();
}
}




---------------------------------------------------
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: No such child: 8
at java.awt.Container.getComponent(Container.java:294)
at javax.swing.JComponent.rectangleIsObscured(JComponent.java:4339)
at javax.swing.JComponent.paint(JComponent.java:1027)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5124)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
at javax.swing.JComponent._paintImmediately(JComponent.java:5072)
at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:785)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:602)
at java.awt.EventQueue$1.run(EventQueue.java:600)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
...全文
152 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
东门吹雪 2011-09-07
  • 打赏
  • 举报
回复
谢谢四楼的热心回复啊,但我重复发帖了,另一贴里多给你点分作为感谢啊,这篇就作无满意结贴处理咯,技术我们还是务实点好哦,ths!
阳明 to life 2011-09-02
  • 打赏
  • 举报
回复
哪一行出错的
softroad 2011-09-02
  • 打赏
  • 举报
回复
java.lang.ArrayIndexOutOfBoundsException: No such child: 8

数组越界了,自己调试吧。
完美灬缺陷 2011-09-02
  • 打赏
  • 举报
回复
帮顶下。
打油的程序员 2011-09-02
  • 打赏
  • 举报
回复
楼主好像重复发帖,那我也不客气了多刷点分

错误的地方有好几处,比如:

// ---------------------------------------------------------------------------------------------
public int[] getList(int[] list) // 产生随机序列
{
int count = list.length;
int[] resultList = new int[count];
LinkedList<Integer> temp = new LinkedList<Integer>();

for (int i = 0; i < count; i++) {
temp.add((Integer) list[i]);
}

// Random rand = new Random();
// for (int i = 0; i < count; i++) {
// int num = rand.nextInt(count - i);

// resultList[i] = (Integer)
// temp.get(num);//此时的temp长度可能变化,可能不变化,count-i是始终在变的,
// temp.remove(num); //remove后 此时的temp长度可能变化,可能不变化
// }

Collections.shuffle(temp);// 打乱它
for (int i = 0; i < count; i++) {
list[i] = temp.get(i);// 复制到resultList;
}
return resultList;
}
// ------------------------------------------------------------------------------------------








//我看上面的程序晕晕的,然后就没耐心了,干脆进行大幅度修改,修改后的程序如下:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class TestNineGridGame {
public static void main(String[] args) {
new GameFrame();
}
}

class GameFrame extends JFrame {
private JPanel gamePane = null;;

public GameFrame() {
super("NineGridGame");
// System.out.println("hi");
launch();
}

public void launch() {
setTitle("controlPane");
// setLayout(new FlowLayout());
gamePane = new GamePanel(this);
add(gamePane);
setPreferredSize(new Dimension(150, 140));
pack();
setVisible(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}

// ///////////////////////////////////////////////////////////////////////////////////////
class GamePanel extends JPanel implements ActionListener {
JFrame drawFrame;

enum Flag {
A, X, H
};

Flag flag;

private static final int BUTTON_ROW_SIZE = 3;
private static final int BUTTON_COL_SIZE = 3;
private static final int TIME_INTERVAL = 3000;// 3秒钟间隔
private JButton[][] buttons = null;;// 面板上有9个JButton
private String[][] texts = null;// 存放按钮对应的文本;
private Set<JButton> passButtons = null; // 产生一个H在数组中的任意位置,然后其他位置随机填充"A","X";
public GamePanel() {
Launch();
}

public GamePanel(JFrame drawFrame) {// 重载构造方法,接收传来的Frame
this.drawFrame = drawFrame; ;
Launch();
}

void Launch() {
setLayout(new FlowLayout());
passButtons = new HashSet<JButton>();// 存放显示过“H”的按钮,
texts = generateAXH();// 产生一个H在数组中的任意位置,然后其他位置随机填充"A","X";
buttons = new JButton[GamePanel.BUTTON_ROW_SIZE][GamePanel.BUTTON_COL_SIZE];
for (int i = 0; i < BUTTON_ROW_SIZE; i++) {// 面板上有9个JButton
for (int j = 0; j < BUTTON_COL_SIZE; j++) {
buttons[i][j] = new JButton(texts[i][j]);// 以随机产生的text初始化按钮
add(buttons[i][j]);// 按钮添加到面板上
buttons[i][j].addActionListener(this);// 每个按钮添加监听器,相当于每个按钮都有一个线程在监听鼠标
}
}
new Thread(new PaintThread()).start();
}

public String[][] generateAXH() {// 产生一个H在数组中的任意位置,然后其他位置随机填充"A","X";
String texts[][] = new String[BUTTON_ROW_SIZE][BUTTON_COL_SIZE];
int randomRow = (int) (Math.random() * BUTTON_ROW_SIZE);
int randomCol = (int) (Math.random() * BUTTON_COL_SIZE);
texts[randomRow][randomCol] = "H";
for (int i = 0; i < BUTTON_ROW_SIZE; i++) {
for (int j = 0; j < BUTTON_COL_SIZE; j++)
if (texts[i][j] == null) {
texts[i][j] = Math.random() < 0.5 ? "A" : "X";
}
}
return texts;
}

public void paintComponent(Graphics g) {// 重写paintComponent方法,
super.paintComponent(g);
for (int i = 0; i < GamePanel.BUTTON_ROW_SIZE; i++)
for (int j = 0; j < GamePanel.BUTTON_COL_SIZE; j++) {
if (buttons[i][j].getText().equals("A"))
buttons[i][j].setText("X");
else if (buttons[i][j].getText().equals("X")) {
buttons[i][j].setText("A");
}
}
}

public void actionPerformed(ActionEvent e) {// 实现每个按钮监听器的方法
JButton jb = (JButton) e.getSource();
if (jb.getText().equals("X")) {
prompt("gameOver");
System.exit(0);
}

int beforeRowOfH = 0;// 记录之前H的位置
int beforeColOfH = 0;// 记录之前H的位置
int nowRowOfH = 0;// 记录现在H的位置
int nowColOfH = 0;// 记录现在H的位置

for (int i = 0; i < BUTTON_ROW_SIZE; i++)
for (int j = 0; j < GamePanel.BUTTON_COL_SIZE; j++) {
if (buttons[i][j].getText().equals("H")) {
beforeRowOfH = i;
beforeColOfH = j;
}
if (buttons[i][j] == jb) {
nowRowOfH = i;
nowColOfH = j;
}
}

//行数相等列数差1 或者列数相等行数差1
if ((nowRowOfH == beforeRowOfH && (nowColOfH == beforeColOfH + 1 | nowColOfH == beforeColOfH - 1))|
(nowColOfH == beforeColOfH && (nowRowOfH == beforeRowOfH + 1 | nowRowOfH == beforeRowOfH - 1))) {
if (jb.getText().equals("A")) {
jb.setText("H");
passButtons.add(buttons[nowRowOfH][nowColOfH]);// 将显示过“H”的按钮放入set
if (passButtons.size() >= BUTTON_ROW_SIZE * BUTTON_COL_SIZE)
prompt("pass");// 判断是否通过了
buttons[beforeRowOfH][beforeColOfH].setText("A");
}
} else {// 非法点击按钮
prompt("只能单击H所在的格子的上下左右按钮");
}
}



public void prompt(String promptMessage) {
JOptionPane.showConfirmDialog(null, promptMessage, "友情提示",
JOptionPane.WARNING_MESSAGE);
}

private class PaintThread implements Runnable {// JPanel重画的线程
public void run() {
while (true) {
repaint();
// updateUI();
try {
Thread.sleep(GamePanel.TIME_INTERVAL);// /过一段时间,就重画面板
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
东门吹雪 2011-09-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 softroad 的回复:]
java.lang.ArrayIndexOutOfBoundsException: No such child: 8

数组越界了,自己调试吧。
[/Quote]

这个是程序运行了差不多3分钟才跳出来的,其中是一个无限循环,每隔2s执行一次,3分钟,我要按多少下呢,我已经试了,没调出来啊。

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧