0

我正在用 Java 创建一个纸牌游戏。我已经编写了整个游戏逻辑,包括所有规则等,并且我已经开始在该模型之上实现 GUI。

我有 5 个类,但我要谈论的只是“主要”或游戏类和“GUI”类。首先,为了构造手,我使用了我创建的 Object Type < Card > 的 ArrayLists。游戏通过“Play()”方法进行游戏,并且(此时)通过控制台向他显示人类玩家手,并要求他在 ArrayList 中进行整数选择以放下。我在 Main 类中有 main(String[] args) 并且为了调用类 GUI 并设置我使用的游戏板。

     public static void main(String[] args)
     {
        Deck deck = new Deck();     
        ai = new AI;

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                GUI gui = new GUI();
                gui.setVisible(true);
            }
        })

理想情况下,我希望游戏通过使用 Play() 方法并从 GUI 类调用方法来更新棋盘并返回人类玩家选择的卡片。目前我能做的最好的事情是,在设置电路板时,我通过实现一个按钮

   Button go = new Button("Update Hand");
   ButtonDisplay.add(go);

   go.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
                Thread queryThread = new Thread() {
            public void run() {
                 UpdateHand();
            }
            };
                queryThread.start();                      
                        }
        });

然后运行

  public void UpdateHand()
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                inPlay = main.inPlay;
                UpdateInPlay(inPlay, InPlayDisplay);
                HumanHand = main.humanplayer;
                HumanHandDisplay.removeAll();

单击后,将清除面板并重新绘制卡片 JLabels。

我的问题是,如何在 GUI 类中调用 Play() 方法?当我尝试从 Play() 方法运行 UpdateHand() 时,只需使用

gui.UpdateHand();

它在该 gui.UpdateHand() 行返回 NullPointerException,但仍会在我告诉它时将 UpdateHand() 方法内的变量打印到控制台,例如 ArrayList。正如我所说,我希望我的 Play() 方法不是在 gui 上有一个更新棋盘的按钮,而是在它循环其回合顺序时调用 UpdateMethod,然后当玩家需要选择卡片时,而不是使用我现在使用的控制台扫描仪,运行一个方法,将一个文本字段和一个按钮添加到板上,供用户输入他们的选择,然后将其返回到 Play() 方法以继续进行游戏计算.

谁能阐明我做错了什么以及如何实现我在这里指定的内容?

编辑:

根据要求,我的 2 个类的更多代码

GUI
public class GUI extends JFrame
{
public Main main;
private ArrayList<Card> AIHand;
     public GUI() {

     pane = this.getContentPane();
     pane.setLayout(new GridLayout(6,1,2,2));
     AIBackDisplay = new JPanel();
     //just more of the same for other panels here

     pane.setBackground(Color.GREEN);
     setTitle("Last Man Standing");
     pane.add(AIBackDisplay);
     pane.add(AIHandDisplay);
     pane.add(InPlayDisplay);
     pane.add(HumanHandDisplay);
     pane.add(HumanBackDisplay);
     pane.add(HumanFacedownDisplay);
     pane.add(ButtonDisplay);

       setSize(800, 700);
       setLocationRelativeTo(pane);
       setDefaultCloseOperation(EXIT_ON_CLOSE);


       UpdateFacedown(AIFacedown, AIBackDisplay); //these are methods called for original display
       UpdateFacedown(HumanFacedown, HumanBackDisplay);

然后我有通过按钮调用的 updateHand() 方法并执行此操作

                  for (int i = 0; i < (HumanHand.size()); i++)
                {
                    Card card = HumanHand.get(i);

                    BufferedImage cardImage = null;

                    try {

                        cardImage = ImageIO.read(new File("card/" + card + ".jpg"));
                    } catch (IOException e) {
        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    JLabel picLabel = new JLabel(new ImageIcon( cardImage ));
                    HumanHandDisplay.add(picLabel);

                } 

                HumanHandDisplay.updateUI();

我的主要课程有

public class Main {

    static AI ai;
    public static GUI gui;

发现 GUI 必须是静态的,否则我无法使用它来调用它

      Scanner sc = new Scanner (System.in);
                choice = sc.nextInt(); //what i'm using now
                //choice = gui.GUIReturn(); //what i'd like to use

即使 GUI 是静态的,它也不允许我运行 gui.GUIReturn() 出于某种原因,说它必须是静态的

4

1 回答 1

2

我认为我们可能需要更多代码来回答这个问题。对我来说,它看起来可能很简单,比如你的 GUI gui 变量的范围。在您展示的示例中,gui 的范围仅在您创建的 Runnable 对象的 run 方法中。

传统上,在 GUI 中调用某些东西的正确方法是使用Singleton 模式。基本上,让你打电话

GUI.getInstance().myMethod();

此外,稍微切线,如果这是您的 UpdateHand() 方法中的唯一代码,那么您的额外线程是浪费时间,因为

SwingUtilities.invokeLater(new Runnable(){ ... });

只需将 Runnable 放入事件队列中,等待轮到它运行。因此,如果这是您方法中唯一的事情,那么线程几乎会立即消失。虽然它可能不是那里唯一的代码,因为你没有结束括号,只是想我会注意到它。

最后,影响 GUI 的任何事情(除了一些事情......)都需要在 invokeLater 中完成。否则,您最终可能会遇到让您发疯的错误,因为它似乎不在您的代码中。

于 2012-04-07T01:38:05.420 回答