/*九格子游戏。请编写多线程游戏,设计一个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)

解决方案 »

  1.   

    java.lang.ArrayIndexOutOfBoundsException: No such child: 8数组越界了,自己调试吧。
      

  2.   

    楼主好像重复发帖,那我也不客气了多刷点分错误的地方有好几处,比如:// ---------------------------------------------------------------------------------------------
        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();
            }
            }
        }
        }
    }
      

  3.   

    谢谢四楼的热心回复啊,但我重复发帖了,另一贴里多给你点分作为感谢啊,这篇就作无满意结贴处理咯,技术我们还是务实点好哦,ths!