Java JButton ActionListener双人游戏

Java JButton ActionListener双人游戏,java,swing,jbutton,Java,Swing,Jbutton,我正在尝试用JavaSwing创建一个两人游戏 我有一个JButton 我的想法是在点击JButton时切换到另一个播放器。当玩家一点击JButton时,轮到玩家二了;当玩家点击两下时,轮到玩家一了 但是我的代码到目前为止不允许程序等待玩家2的点击。当玩家一键点击时,玩家二被认为已经点击 我如何让程序等待玩家2的点击来解决这个问题 boolean game = true; final boolean p1 = false; final boolean p2 = false; ... while

我正在尝试用JavaSwing创建一个两人游戏

我有一个
JButton

我的想法是在点击
JButton
时切换到另一个播放器。当玩家一点击
JButton
时,轮到玩家二了;当玩家点击两下时,轮到玩家一了

但是我的代码到目前为止不允许程序等待玩家2的点击。当玩家一键点击时,玩家二被认为已经点击

我如何让程序等待玩家2的点击来解决这个问题

boolean game = true;
final boolean p1 = false;
final boolean p2 = false;
...
while (game) {
    p1 = true;
    while (p1) {
        enterMoveButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                doSomething();
                p1 = false;
                p2 = true;
            }
        });
    }
    while (p2) {
        enterMoveButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                doSomething();
                p2 = false;
                p1 = true;
            }
        });
    }
}

你为什么不禁用未轮到的玩家的按钮,然后在轮到该玩家时启用,并禁用对手的按钮

button.setEnabled(false);
假设你有两个不同的按钮


祝你好运

为什么不禁用未轮到的玩家的
JButton
,然后在该玩家轮到时启用,并禁用对手的按钮

button.setEnabled(false);
假设你有两个不同的按钮

祝你好运

我建议改为使用。有关使用它们的信息,请参阅Java教程中的一节

我建议改为使用。有关使用它们的信息,请参阅Java教程中的一节

当玩家一键点击时,玩家二被认为已经点击

这是因为您使用addActionListener。调用此方法时,它不会替换上一个方法。它只需将另一个侦听器添加到单击按钮即可。单击它时,它将执行添加到按钮的所有侦听器

您可以通过定义两个ActionListener来解决此问题:

ActionListener a1 = new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent arg0) {
        doSomething();
        p1 = false;
        p2 = true;

    }   
};

ActionListener a2 = new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent arg0) {
        doSomething();
        p2 = false;
        p1 = true;
   }
};


while(game){
    p1 = true;
    while(p1){
        enterMoveButton.removeActionListener(a2);
        enterMoveButton.addActionListener(a1);
    }
    while(p2){
        enterMoveButton.removeActionListener(a1);
        enterMoveButton.addActionListener(a2);
    }
当玩家一键点击时,玩家二被认为已经点击

这是因为您使用addActionListener。调用此方法时,它不会替换上一个方法。它只需将另一个侦听器添加到单击按钮即可。单击它时,它将执行添加到按钮的所有侦听器

您可以通过定义两个ActionListener来解决此问题:

ActionListener a1 = new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent arg0) {
        doSomething();
        p1 = false;
        p2 = true;

    }   
};

ActionListener a2 = new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent arg0) {
        doSomething();
        p2 = false;
        p1 = true;
   }
};


while(game){
    p1 = true;
    while(p1){
        enterMoveButton.removeActionListener(a2);
        enterMoveButton.addActionListener(a1);
    }
    while(p2){
        enterMoveButton.removeActionListener(a1);
        enterMoveButton.addActionListener(a2);
    }

因为您正在编写Swing,所以不要执行
while(true)
循环,因为这样会阻塞事件线程EDT。相反,你应该使用摆动计时器,或者更可能在你的情况下,因为我猜你在玩基于回合的游戏(如果错误,请纠正我),使动作取决于事件。使用后者,而不是交换ActionListener,您只需通过单个字段更改程序状态,并根据此状态更改ActionListener的行为

关于后者的示例,请参见下面的代码。程序的状态由playerIndex int变量保持:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class ToggleGame extends JPanel {
   public static final String[] PLAYERS = {"Player 1", "Player 2"};

   // turnIndex is either 0 or 1, depending on whose turn it is.
   private int turnIndex = 0; 
   private JButton turnButton = new JButton(PLAYERS[turnIndex]);

   public ToggleGame() {
      add(new JLabel("Turn:"));
      add(turnButton);
      setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

      turnButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
            turnBtnAction(evt);
         }
      });
   }

   private void turnBtnAction(ActionEvent evt) {
      turnIndex++; // next player
      turnIndex %= PLAYERS.length; // mod 2
      turnButton.setText(PLAYERS[turnIndex]);

      doSomething(turnIndex);
   }

   private void doSomething(int index) {
      String msg = "It is now " + PLAYERS[index] + "'s turn!";
      String title = "Whose Turn Is It?";
      JOptionPane.showMessageDialog(this, msg , title, JOptionPane.INFORMATION_MESSAGE);
   }

   private static void createAndShowGui() {
      ToggleGame mainPanel = new ToggleGame();

      JFrame frame = new JFrame("ToggleGame");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

因为您正在编写Swing,所以不要执行
while(true)
循环,因为这样会阻塞事件线程EDT。相反,你应该使用摆动计时器,或者更可能在你的情况下,因为我猜你在玩基于回合的游戏(如果错误,请纠正我),使动作取决于事件。使用后者,而不是交换ActionListener,您只需通过单个字段更改程序状态,并根据此状态更改ActionListener的行为

关于后者的示例,请参见下面的代码。程序的状态由playerIndex int变量保持:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class ToggleGame extends JPanel {
   public static final String[] PLAYERS = {"Player 1", "Player 2"};

   // turnIndex is either 0 or 1, depending on whose turn it is.
   private int turnIndex = 0; 
   private JButton turnButton = new JButton(PLAYERS[turnIndex]);

   public ToggleGame() {
      add(new JLabel("Turn:"));
      add(turnButton);
      setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

      turnButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
            turnBtnAction(evt);
         }
      });
   }

   private void turnBtnAction(ActionEvent evt) {
      turnIndex++; // next player
      turnIndex %= PLAYERS.length; // mod 2
      turnButton.setText(PLAYERS[turnIndex]);

      doSomething(turnIndex);
   }

   private void doSomething(int index) {
      String msg = "It is now " + PLAYERS[index] + "'s turn!";
      String title = "Whose Turn Is It?";
      JOptionPane.showMessageDialog(this, msg , title, JOptionPane.INFORMATION_MESSAGE);
   }

   private static void createAndShowGui() {
      ToggleGame mainPanel = new ToggleGame();

      JFrame frame = new JFrame("ToggleGame");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

为什么不使用两个布尔变量,而只使用一个,比如:

boolean myturn = true; // at the start for Player 1 it's true.

@Override
public void actionPerformed(ActionEvent arg0) 
{
   if (myturn == true)
   {
      doSomething();  // Do whatever Player1 is suppose to do at his turn.
                      // Now since myturn will be false after this, so Player1
                      // won't be able to move till Player 2 takes his turn.
      myturn = false;
   }
   else if (myturn == false)
   {
      doThisInstead(); // Do whatever Player2 is suppose to do at his turn.
                       // Here again myturn will will change to true, now Player2
                       // won't be able to move till Player1 makes his next move.
      myturn = true;
   }
}
下面是解释我刚才所说内容的代码:

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

public class ButtonTest extends JFrame implements ActionListener
{
  private JPanel panel;
  private JButton button;
  private JLabel label;
  private String player1 = "I am player one.";
  private String player2 = "I am player two.";
  private boolean myturn = true;

  public ButtonTest()
  {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    panel = new JPanel();
    button = new JButton(player1);
    label = new JLabel(player1);
    button.addActionListener(this);

    panel.add(label);
    panel.add(button);

    setContentPane(panel);
    pack();
  }

  public void actionPerformed(ActionEvent ae)
  {
     if (myturn == true)
    {
      button.setText(player2);
      label.setText(player2);
      myturn = false;
    }
    else if (myturn == false)
    {
      button.setText(player1);
      label.setText(player1);
      myturn = true;
    }
  }

  public static void main(String... args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        new ButtonTest().setVisible(true);
      }
    });
  }
}
一个变量可以为您实现这一点,而不是使用两个不同的变量

希望这能有所帮助。
关于

为什么不使用两个布尔变量,而只使用一个,例如:

boolean myturn = true; // at the start for Player 1 it's true.

@Override
public void actionPerformed(ActionEvent arg0) 
{
   if (myturn == true)
   {
      doSomething();  // Do whatever Player1 is suppose to do at his turn.
                      // Now since myturn will be false after this, so Player1
                      // won't be able to move till Player 2 takes his turn.
      myturn = false;
   }
   else if (myturn == false)
   {
      doThisInstead(); // Do whatever Player2 is suppose to do at his turn.
                       // Here again myturn will will change to true, now Player2
                       // won't be able to move till Player1 makes his next move.
      myturn = true;
   }
}
下面是解释我刚才所说内容的代码:

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

public class ButtonTest extends JFrame implements ActionListener
{
  private JPanel panel;
  private JButton button;
  private JLabel label;
  private String player1 = "I am player one.";
  private String player2 = "I am player two.";
  private boolean myturn = true;

  public ButtonTest()
  {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    panel = new JPanel();
    button = new JButton(player1);
    label = new JLabel(player1);
    button.addActionListener(this);

    panel.add(label);
    panel.add(button);

    setContentPane(panel);
    pack();
  }

  public void actionPerformed(ActionEvent ae)
  {
     if (myturn == true)
    {
      button.setText(player2);
      label.setText(player2);
      myturn = false;
    }
    else if (myturn == false)
    {
      button.setText(player1);
      label.setText(player1);
      myturn = true;
    }
  }

  public static void main(String... args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        new ButtonTest().setVisible(true);
      }
    });
  }
}
一个变量可以为您实现这一点,而不是使用两个不同的变量

希望这能有所帮助。
关于

您确定要在(true)循环时永久使用原始海报的
?这些都行不通。与其交换侦听器,为什么不通过一个字段简单地更改程序状态,并根据此状态更改ActionListener的行为。您是对的,如果它在主线程中运行,那么一段时间(true)循环是不好的。可以在单独的线程中运行它。对于实现一个游戏,我认为有一段时间(真的)循环来保持游戏运行是正常的。但如果游戏取决于用户的输入并等待用户的输入,那么他当然不需要while(true)循环。您确定要使原始海报永久使用while(true)
循环吗?这些都行不通。与其交换侦听器,为什么不通过一个字段简单地更改程序状态,并根据此状态更改ActionListener的行为。您是对的,如果它在主线程中运行,那么一段时间(true)循环是不好的。可以在单独的线程中运行它。对于实现一个游戏,我认为有一段时间(真的)循环来保持游戏运行是正常的。但如果游戏取决于用户的输入并等待用户的输入,那么他当然不需要一段时间(真)循环。请注意,
p1
p2
是最终的,这排除了后续的更改。请注意,
p1
p2
是最终的,这排除了后续的更改。