Java - 如何使用SwingWorker创建多线程游戏

6

我想创建一个[1个玩家对电脑]的游戏,并使用线程。

我们在棋盘上有一个10*10的两种颜色形状,如下所示:

enter image description here

当玩家点击蓝色圆圈时,它们的颜色变成灰色。

在另一侧,PC应该将所有红色矩形都变成灰色。

赢家是谁先把自己的形状全部清除掉。


玩家的代码很好用,但是,实现电脑端的游戏时出现了问题。正如我在这篇文章中所读到的那样,在GUI中实现线程应该使用SwingWorker。这是我第一次使用SwingWorkers,不知道如何才能正常工作。

这是我的代码:

主类

public class BubblePopGame {

public static final Color DEFAULT_COLOR1 = Color.BLUE;
public static final Color DEFAULT_COLOR2 = Color.RED;

public BubblePopGame() {
    List<ShapeItem> shapes = new ArrayList<ShapeItem>();

    int Total = 10;
    for (int i = 1; i <= Total; i++) {
        for (int j = 1; j <= Total; j++) {
            if ((i + j) % 2 == 0) {

                shapes.add(new ShapeItem(new Ellipse2D.Double(i * 25, j * 25, 20, 20),
                        DEFAULT_COLOR1));
            } else {
                shapes.add(new ShapeItem(new Rectangle2D.Double(i * 25, j * 25, 20, 20),
                        DEFAULT_COLOR2));
            }
        }
    }

    JFrame frame = new JFrame("Bubble Pop Quest!!");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ShapesPanel panel = new ShapesPanel(shapes);
    frame.add(panel);
    frame.setLocationByPlatform(true);
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new BubblePopGame();
        }
    });
}

}

形状项目类

public class ShapeItem {

private Shape shape;
private Color color;

public ShapeItem(Shape shape, Color color) {
    super();
    this.shape = shape;
    this.color = color;
}

public Shape getShape() {
    return shape;
}

public void setShape(Shape shape) {
    this.shape = shape;
}

public Color getColor() {
    return color;
}

public void setColor(Color color) {
    this.color = color;
}

}

ShapesPanel类

public class ShapesPanel extends JPanel {

private List<ShapeItem> shapes;
private Random rand = new Random();
private SwingWorker<Boolean, Integer> worker;

public ShapesPanel(List<ShapeItem> shapesList) {
    this.shapes = shapesList;
    worker = new SwingWorker<Boolean, Integer>() {            

        @Override
        protected Boolean doInBackground() throws Exception {
            while (true) {
                Thread.sleep(200);
                int dim = rand.nextInt(300);
                publish(dim);                
                return true;
           }
        }

        @Override
        protected void done() {
            Boolean Status;
            try {                    
                Status = get();
                System.out.println(Status);
                super.done();                    //To change body of generated methods, choose Tools | Templates.
            } catch (InterruptedException ex) {
                Logger.getLogger(ShapesPanel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(ShapesPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        @Override
        protected void process(List<Integer> chunks) {
            int mostRecentValue = chunks.get(chunks.size()-1);
            System.out.println(mostRecentValue);
                Color color2 = Color.LIGHT_GRAY;
                ShapeItem tmpShape = shapes.get(mostRecentValue);
                if(tmpShape.getColor()==Color.RED){
                    tmpShape.setColor(color2);
                }
                repaint();                
       }

    };
    worker.execute ();

    addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            Color color1 = Color.LIGHT_GRAY;
            for (ShapeItem item : shapes) {
                if (item.getColor() == Color.BLUE) {
                    if (item.getShape().contains(e.getPoint())) {
                        item.setColor(color1);
                    }
                }
            }
            repaint();
        }
    });
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g.create();

    for (ShapeItem item : shapes) {
        g2.setColor(item.getColor());
        g2.fill(item.getShape());
    }

    g2.dispose();
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(300, 300);
}

private Color getRandomColor() {
    return new Color(rand.nextFloat(), rand.nextFloat(),
            rand.nextFloat());
}

}


1
那么...问题出在哪里? - Caffeinated
工人没有正常工作。如您在截图中所见,没有一个矩形变成了灰色... - Mahdi Rashidi
2
您的doInBackground()在第一次循环迭代后结束。 - Durandal
1个回答

4
如果我正确理解了你的代码,你正在制作一个游戏,其中人类玩家必须尽可能快地单击所有形状,而PC也会随机点击形状。第一个清除所有形状的人获胜。
如果是这样,你可能需要调整你的 SwingWorker:
- 循环直到游戏结束。目前你的循环在第一次到达循环结尾时退出,因为有 return 语句。 - 因为你没有对 SwingWorker 的布尔返回值做任何处理,所以可以让它返回 void。 - 不需要在 done 方法中调用 get。该方法被调用时,SwingWorker 已经完成。你似乎只对中间结果感兴趣。 - 在 process 方法中,你可能想要循环所有值。请注意,process 方法并不是每次 publish 就调用一次。你 publish 的值会被分组,并在 EDT 可用时批量传递给 process 方法。

非常感谢@Robin,你的回答为我澄清了Swing Workers的问题,希望问题已经解决 :) - Mahdi Rashidi
1
@Mahdi Rashidi 获得返回异常或结果,请小心。 - mKorbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接