Java-在中写入标准?
我有一个应用程序,在这个应用程序中,让鼠标单击事件模拟用户键入特定字符串以进行标准输入将非常方便。所以我想知道,有没有一种方法可以在代码中编写标准的代码?我意识到这是一个有点黑客,但它会为我需要做的工作非常好 编辑(响应气垫船的编辑2): 谢谢。我理解代码是如何阻止人类玩家在不应该移动的时候移动棋子的。我不明白的是你是如何设想主游戏循环的。你介意写代码告诉我你是怎么想的吗?您是否正在想象一个繁忙的等待循环,它不断生成新的计算机移动并调用您的Java-在中写入标准?,java,swing,stdin,Java,Swing,Stdin,我有一个应用程序,在这个应用程序中,让鼠标单击事件模拟用户键入特定字符串以进行标准输入将非常方便。所以我想知道,有没有一种方法可以在代码中编写标准的代码?我意识到这是一个有点黑客,但它会为我需要做的工作非常好 编辑(响应气垫船的编辑2): 谢谢。我理解代码是如何阻止人类玩家在不应该移动的时候移动棋子的。我不明白的是你是如何设想主游戏循环的。你介意写代码告诉我你是怎么想的吗?您是否正在想象一个繁忙的等待循环,它不断生成新的计算机移动并调用您的Move()方法(大多数情况下,在等待人类玩家移动时被拒
Move()
方法(大多数情况下,在等待人类玩家移动时被拒绝)?像这样的
public void gameLoop()
{
while (gameNotOver)
{
Move compMove = generateComputersNextMove();
move(blackPlayer, compMove); // where the blackPlayer is the computerPlayer
}
}
你说:
基本上,我希望我的代码在某一点阻塞,然后等待用户单击JFrame中的特定JLabel。一旦用户单击JLabel,我希望代码在获得所单击的JLabel的id后继续。我不知道该怎么做。我以前的方法是,在代码中的那个点上,用户只需输入一个id(Scanner的next()方法会为您阻塞)
您不想阻塞程序(不是在事件驱动程序中),而是想更改GUI的状态,并基于此状态对用户输入做出响应。您尝试的解决方案是一种线性思维方式,不能很好地与Swing或其他事件驱动GUI配合使用
例如,作为一个简单的例子,考虑给程序一个布尔变量,
private boolean labelClicked = false;
单击JLabel后,在JLabel的鼠标侦听器中将其更改为true。然后,仅当布尔值为true时才响应其他用户输入
或者另一种可能的解决方案:如果您想在按下JLabel后激活JButton,则禁用JButton,并从JLabel的鼠标侦听器中调用JButton上的setEnabled(true)
关键是思考事件驱动编程。在本论坛中提出类似问题的另一个关键不是问我们特定于代码的问题,而是问我们特定于行为的问题。这里真正的问题不是如何在中写入标准,而是如何让程序暂停并等待用户输入——这是一个很大的区别 最后,如果您需要更具体、更好的建议,请向我们详细介绍您的问题,如果有任何问题让人困惑,请提出问题。祝你好运 编辑1
您可能会有几个类,包括管理此应用程序的GUI类和非GUI类,非GUI类可以包括:
- 玩家等级:这可以是人或计算机
- 棋盘类:国际象棋棋盘的逻辑(非gui)表示
- Piece类:所有具体片段都派生自的抽象类
- ChessAI类:这是你的人工智能类,为计算机计算出下一个最好的移动应该是什么
- 游戏类:可能是本次讨论中最重要的类,因为这将控制游戏流程并决定轮到谁移动李>
turn
的玩家字段,该字段将保存对轮到谁的引用。假设游戏类包含两个玩家变量,humanPlayer和computerPlayer。回合变量将容纳一个或另一个对象,玩家的反应将取决于回合所容纳的对象
Game类将有一个循环,一个游戏循环,在告诉humanPlayer对象和computerPlayer对象轮到他们移动之间交替进行
所以说,现在轮到计算机了,计算下一个最佳动作需要一段时间。如果同时人类玩家试图在GUI上拖动棋子,GUI将通知游戏类人类尝试移动,游戏类将检查是否轮到人类(通过检查If(turn==humanPlayer)
),如果不是轮到人类,游戏将通知GUI,GUI会将工件设置回原来的位置,可能会弹出一条警告消息
计算机请求游戏移动其棋子后,游戏将告诉GUI移动计算机的棋子,然后游戏将设置turn=humanPlayer,现在允许人类玩家移动。在humanPlayer尝试移动后,GUI将告诉游戏该玩家尝试的移动。游戏将检查它是否是一个有效的移动,如果是的话,将告诉computerPlayer它现在应该移动
请注意,当我说“tell”时,我的意思是它将调用该对象上的公共方法
编辑2我的意思是这样的:
public class Game {
private Player whitePlayer;
private Player blackPlayer;
private Player turn;
private Board board = new Board(); // non-GUI logical board
private Gui gui; // the Swing GUI that displays all
public Game(String humanPlayerName, boolean humanWhite) {
if (humanWhite) {
whitePlayer = new HumanPlayer(humanPlayerName, this);
blackPlayer = new ComputerPlayer("Computer", this);
} else {
whitePlayer = new ComputerPlayer("Computer", this);
blackPlayer = new HumanPlayer(humanPlayerName, this);
}
}
public void start() {
whitePlayer.setMyTurn(true); // tell white player to move
}
public void move(Player playerMakingMove, Move move) {
// only respond if the right player is making the move
if (turn == playerMakingMove) {
// check if its a valid move
// if so, tell GUI to make move
// check if game over
turn.setMyTurn(false); // current player's turn is over
turn = (turn == blackPlayer) ? whitePlayer : blackPlayer; // swap players
turn.setMyTurn(true); // tell other player, it's his turn
turn.makeMove(); // *** added
} else {
// send message that it's not their turn to move
}
}
}
因此,如果人类玩家尝试移动,GUI将为人类玩家移动(…),但游戏对象不会响应,除非实际上轮到人类
编辑3makeMove()
方法添加到播放器
请注意,游戏的move(…)
方法可能是所有需要的游戏循环,特别是如果ComputerPlayer的makeMove(…)
方法告诉AI引擎创建下一个最佳移动,然后再次调用游戏的move(…)方法:
abstract class Player {
private String name;
private boolean myTurn = false;
protected Game game;
public Player(String name, Game game) {
this.name = name;
this.game = game;
}
public abstract void makeMove();
public boolean isMyTurn() {
return myTurn;
}
public void setMyTurn(boolean myTurn) {
this.myTurn = myTurn;
}
public String getName() {
return name;
}
}
class HumanPlayer extends Player {
public HumanPlayer(String name, Game game) {
super(name, game);
}
@Override
public void makeMove() {
// TODO: ask GUI to inform player that it's his turn to move and accept the move
}
}
class ComputerPlayer extends Player {
private ChessAi chessAi = new ChessAi();
public ComputerPlayer(String name, Game game) {
super(name, game);
}
@Override
public void makeMove() {
game.move(this, chessAi.calcBestMove());
}
}
两个玩家在计算出移动后都会调用game.move(…)
,这使得游戏提示下一个玩家移动。。。。直到比赛结束
请注意,这不是一个正在运行的程序,也不意味着是,但更多的是一个模型来说明可能的游戏逻辑。我没有做过类似的事情,可能有更好更干净的方法来做,但我只想了解在事件驱动GUI程序中实现基于回合的逻辑的方法
编辑4编译并运行以下简单的事件驱动GUI:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventDrivenGui extends JPanel {
private static final Color GO_COLOR = Color.green;
private static final Color STOP_COLOR = Color.red;
private static final int SIDE = 300;
private static final int TIMER_DELAY = 4 * 1000; // change light every 4 seconds
private boolean go = false;
private JButton button = new JButton("Button");
public EventDrivenGui() {
add(button);
button.addActionListener(new ButtonListener());
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Color color = go ? GO_COLOR : STOP_COLOR;
g2.setColor(color);
g2.fillOval(0, SIDE / 3, SIDE, SIDE);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(SIDE, (4 * SIDE) / 3);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
if (go) {
JOptionPane.showMessageDialog(EventDrivenGui.this, "Button is Active");
}
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// toggle go. if true, now false, and visa versa
go = !go;
repaint(); // redraw oval
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
EventDrivenGui mainPanel = new EventDrivenGui();
JFrame frame = new JFrame("EventDrivenGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}
你会看到有一个JButt