GUI与黑白棋游戏,拒绝等待玩家移动 java

我编写了一个黑白棋程序,使用一个由按钮组成的二维数组填充GUI。程序中包含多个方法,其中包括validMoves()方法,该方法会将有效移动的按钮设置为setEnabled(true),并显示一个红点,以便用户知道哪些按钮是活跃的。当你选择要移动的棋子时,它还会翻转正确的棋子。我遇到的问题是GUI不会等待玩家进行移动。我编写了一个AI,它基本上与玩家完全相同,它会找到有效的移动,找出哪个移动能翻转最多的棋子,并以”x*y”的格式返回,我的代码会将这个字符串分割成x和y,然后进行移动并翻转棋子。我尝试了thread.sleep()、wait()和while (!hasMoved)以及其他许多方法,但它就是不愿意合作。使用wait()时,我遇到了无限循环,因为GUI存在但里面什么都没有。然而,当我注释掉wait()时,它显示得完全正确。

package reversi;/* * 需要检查边缘的bug // 它会超出边界 * 刷新分数不工作 * * 在某人移动后添加清除所有准备状态 */import java.util.logging.Level;import java.util.logging.Logger;import javax.swing.JApplet;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.Timer;/** * @author 13ponchera * 黑白棋游戏的棋盘 */public class ReversiBoard extends JApplet{    private int score1;    private int score2;    private int turn;    private Icon p1 = new ImageIcon("images/p1.png");    private Icon p2 = new ImageIcon("images/p2.png");    private Icon bGround = new ImageIcon("images/bGround.png");    private Icon ready = new ImageIcon("images/ready.png");    // 帮助动作监听器确定轮到哪个玩家    private int x; // 按钮的数量    private JButton[][] buttons;    private JPanel settingPanel =            new JPanel();    private JButton newGame =            new JButton("新游戏?");    private JLabel score1A;    private JLabel score2A;    private JPanel gameBoard =            new JPanel();    private AI ai = new AI(bGround,p1,p2);    private boolean hasMoved;    private Timer t;    /**     * 初始化方法     * 在小程序加载到浏览器后调用     * 设置所有内容     */    public  void init()    {        score1 = 0;        score2 = 0;        // 设置查看器显示分数        score1A = new JLabel("玩家: " + score1);        score2A = new JLabel("电脑:" + score2);        // 将组件添加到设置面板        settingPanel.add(newGame);            newGame.addActionListener(new NewGameListener());        settingPanel.add(score1A);//初始化为0        settingPanel.add(score2A);        // 创建任意大小的游戏棋盘,只要是偶数        String a = JOptionPane.showInputDialog                (null, "请输入一个偶数作为x");            x = Integer.parseInt(a) + 2;        if ((x % 2 == 0) && (x > 4))        {            gameBoard = new JPanel(new GridLayout(x, x, 4, 4));            buttons = new JButton[x][x];        }// 在x上加2,然后将边缘设置为新图片        else        {            // 请求新的数字,直到输入的数字是偶数            while ((x % 2 != 0) && (x < 4))            {                String responce = JOptionPane.showInputDialog                        (null, "必须是偶数的行和列 \n\t请输入x");                x = Integer.parseInt(responce) + 2;            }            gameBoard = new JPanel(new GridLayout(x, x, 4, 4));            buttons = new JButton[x][x];        }        // 为每个位置创建按钮并将它们放入二维数组        for (int c = 0; c < x; c++)        {            for (int d = 0; d < x; d++)            {                buttons[c][d] = new JButton();                buttons[c][d].setIcon(bGround);                    // 添加默认背景图片                buttons[c][d].addActionListener                        (new ButtonListener(buttons[c][d],c,d));                    // 添加通用按钮监听器                buttons[c][d].setEnabled(false);                    // 按钮不可点击,除非是有效移动                gameBoard.add(buttons[c][d]);                buttons[c][d].setIcon(bGround);                buttons[c][d].setDisabledIcon(bGround);                    // 将按钮添加到JPanel            }        }        // 使边缘颜色不同        // 将包含所有按钮的JPanel添加到内容窗格        buttons[x/2][x/2]                .setIcon(p1);        buttons[x/2][x/2]                .setDisabledIcon(p1);        buttons[(x/2) - 1][(x/2) - 1]                .setIcon(p1);        buttons[(x/2) - 1][(x/2) - 1]                .setDisabledIcon(p1);                        refreshTable();                // 使中间上左和下右的棋子为白色        buttons[(x/2) - 1][(x/2)]                .setIcon(p2);        buttons[x/2][(x/2) - 1]                .setIcon(p2);        buttons[(x/2) - 1][(x/2)]                .setDisabledIcon(p2);        buttons[x/2][(x/2) - 1]                .setDisabledIcon(p2);                        refreshTable();                // 使中间上右和下左的棋子为黑色        getContentPane()                .add(gameBoard, BorderLayout.CENTER);        getContentPane();//刷新小程序        // 在敲击键盘两天后        getContentPane()                .add(settingPanel, BorderLayout.SOUTH);                // 将设置面板(新游戏按钮和分数)添加到内容窗格        refreshTable();        t = new Timer();        hasMoved = false;        validMoves();        refreshTable();        synchronized(t)        {            while(!hasMoved)            {                try                {                    t.wait(50);                }                catch (InterruptedException ex)                {                    Logger.getLogger(ReversiBoard.class.getName())                        .log(Level.SEVERE, null, ex);                }            }        }        refreshTable();        aiTurn();        // 使边缘图片不同    }    /**     * 刷新表格以显示图片     */    public  void refreshTable()    {        for (int a = 0; a < x; a++)        {            for (int b = 0; b < x; b++)            {                buttons[a][b].repaint();            }        }        setScores();        score1A.setText                ("玩家: " + score1);        score2A.setText                ("电脑: " + score2);        gameBoard.repaint();        settingPanel.repaint();    }    /**     * 查找所有有效移动并设置按钮启用状态和可识别的图片     */    public  void validMoves()    {        int c = 0;        int d = 0;        // 临时值,以便搜索可以不被打断        for(int a = 1; a < x - 1; a++)        {            for(int b = 1; b < x - 1; b++)            {                // 查看每个棋子                if (buttons[a][b].getIcon() ==bGround)                {                    // 如果是背景棋子,看看是否有敌方棋子相邻                   if (buttons[a + 1][b].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a + 1;                       while ((buttons[c][b].getIcon() == p2)                               && (c < x)                               && (c > 0))                       {                           if (buttons[c + 1][b].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                             //JOptionPane.showMessageDialog(null,"");                           }                           c++;                       }                   }                   // 查看是否有敌方棋子相邻                   if (buttons[a - 1][b].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a - 1;                       while ((buttons[c][b].getIcon() == p2)                               && (c < x)                               && (c > 0))                       {                           if (buttons[c - 1][b].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                            //JOptionPane.showMessageDialog(null,"");                           }                           c--;                       }                   }                   if (buttons[a][b + 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = b + 1;                       while ((buttons[a][c].getIcon() == p2)                               && (c < x)                               && (c > 0))                       {                           if (buttons[a][c + 1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                            //JOptionPane.showMessageDialog(null,"");                           }                           c++;                       }                   }                   if (buttons[a][b - 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = b - 1;                       while ((buttons[a][c].getIcon() == p2)                               && (c < x)                               && (c > 0))                       {                           if (buttons[a][c - 1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                                //JOptionPane.showMessageDialog(null,"");                           }                           c--;                       }                   }                   // 开始检查对角线                   if (buttons[a + 1][b + 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a + 1;                       d = b + 1;                       while ((buttons[c][d].getIcon() == p2)                               && (c < x)                               && (c > 0)                               && (d < x)                               && (d > 0))                       {                           if (buttons[c + 1][d + 1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                              // JOptionPane.showMessageDialog(null,"");                           }                           c++;                           d++;                       }                   }                   if (buttons[a - 1][b - 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a - 1;                       d = b - 1;                       while ((buttons[c][d].getIcon() == p2)                               && (c < x)                               && (c > 0)                               && (d < x)                               && (d > 0))                       {                           if (buttons[c - 1][d -1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                             //JOptionPane.showMessageDialog(null,"");                           }                           c--;                           d--;                       }                   }                   if (buttons[a - 1][b + 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a - 1;                       d = b + 1;                       while ((buttons[c][d].getIcon() == p2)                               && (c < x)                               && (c > 0)                               && (d < x)                               && (d > 0))                       {                           if (buttons[c - 1][d + 1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                           // JOptionPane.showMessageDialog(null,"");                           }                           c--;                           d++;                       }                   }                   if (buttons[a + 1][b - 1].getIcon() == p2)                   {                       // 继续检查那个方向                       // 直到到达棋盘末端或碰到友方棋子                       // c 是找到的位置的坐标                       c = a + 1;                       d = b - 1;                       while ((buttons[c][d].getIcon() == p2)                               && (c < x)                               && (c > 0)                               && (d < x)                               && (d > 0))                       {                           if (buttons[c + 1][d - 1].getIcon() == p1)                           {                               buttons[a][b].setEnabled(true);                               buttons[a][b]                                       .setIcon(ready);                           // JOptionPane.showMessageDialog(null,"");                           }                           c++;                           d--;                       }                   }                }            }        }        refreshTable();        /*try        {            Thread.sleep(50); // 30秒 NA        }        catch (InterruptedException ex)        {            Logger.getLogger(ReversiBoard.class.getName())                    .log(Level.SEVERE, null, ex);        }*/    }    /**     * 计算每个玩家的分数     */    /**     *     * @return boolean 如果游戏结束     */    public  boolean winner()    {        refreshTable();        if (!anyMove(1) && !anyMove(0))            return true;            //joptionpan 显示赢家(如果score1 > score 2).... 和相反情况        return false;    }    /**     * @param player 1 为玩家1,0 为电脑     * @return boolean 如果有移动     */    public  void clearReady()    {        for (int a = 0; a < x; a++)        {            for (int b = 0; b < x; b++)            {                if (buttons[a][b].getIcon() == ready)                {                    buttons[a][b].setIcon(bGround);                    buttons[a][b].setEnabled(false);                    buttons[a][b].setDisabledIcon(bGround);                }            }        }    }    private  void makeMove(String move)    {        int temp = 0;        char[] f = move.toCharArray();        for(int i = 0; i < f.length; i++)        {            if (f[i] == ('*'))                temp = i;        }        int x = Integer.parseInt(move.substring(0,temp));        int y = Integer.parseInt(move.substring(temp + 1));        buttons[x][y].setIcon(p2);        buttons[x][y].setEnabled(false);        buttons[x][y].setDisabledIcon(p2);        flip(1,x,y);    }    private void aiTurn()    {        String move = ai.makeMove(buttons);            // 字符串move是一个用*分隔的坐标字符串        makeMove(move);        turn++;    }    class ButtonListener implements ActionListener    {        private JButton a;        private int x;        private int y;        private ButtonListener(JButton jButton, int c, int d)        {            a = jButton;            x = c;            y = d;        }        public  void actionPerformed(ActionEvent e)        {            // 必须区分p1和p2            switch (turn % 2)            {                case 0:                    a.setIcon(p1);                    a.setEnabled(false);                    a.setDisabledIcon(p1);                    flip(0,x,y);                    turn++;                    clearReady();                    hasMoved = true;                    /*synchronized(t)                    {                        t.notifyAll();                    }*/                    refreshTable();                    break;                case 1:                    a.setIcon(p2);                    a.setEnabled(false);                    a.setDisabledIcon(p2);                    flip(1,x,y);                    turn++;                    clearReady();                    hasMoved = true;                    /*synchronized(t)                    {                        t.notifyAll();                    }*/                    refreshTable();                    break;            }        }    }}

回答:

请看下面的GUI应用程序应该如何表现(或多或少):

  1. 创建小部件
  2. 向小部件注册监听器
  3. 等待用户操作
  4. 更新GUI以显示用户的移动
  5. 调用AI进行移动并显示
  6. 返回到第3点

你已经在init方法中完成了第1和第2点。你应该删除该方法的最后一部分(包含while(!hasMoved)循环的块):这是第3点,由init完成后的小程序处理。你不需要做任何事情。

当用户点击一个JButton(如果按钮是启用的),ButtonListeneractionPerformed方法会被调用:这是第4点的开始,你应该更新你的小部件(你的代码中的refreshTable()),并让AI移动(aiTurn(),第5点)。当actionPerformed方法完成后,JApplet会自动返回到第3点,你不需要做任何事情。

我对Applets不太了解,所以我不能更详细。你应该搜索与你的行为相似的JApplet示例/教程。记住,你的代码中不应该有等待用户输入的无限循环:它由JApplet处理。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注