0

我正在用java编写一个国际象棋程序。到目前为止一切都很好,但我在更新我的 UI 时确实遇到了问题。

这是 ChessBoard 类中的一段代码,它扩展了 JPanel。当用户尝试移动时调用它:

if ( isLegalMove( aMove ) ) { // If the move's legal
    makeMove( aMove ); // Make that move
    select = null; // Reset some info
    drag = null;
    toggleTurn(); // Change turns
    generateMoves( 0 ); // Get legal moves for CPU
    repaint(); // Redraw board
    thread.run(); // Run chess algorithm
}

该线程在我的 ChessBoard 实例上调用“运行”。找到移动的算法可能需要几秒钟来决定移动。

我想让我的 UI 更新以反映用户的移动,然后运行算法。这就是我在单独的线程上运行算法的原因。但是我的用户界面在计算机也采取行动之前不会更新。

因此,如果用户单击一个空间将一块棋子发送到那里,屏幕会冻结,然后棋子突然移动了,但计算机也移动了,又轮到玩家了。

任何帮助将不胜感激。

4

2 回答 2

4

thread.run()将在当前线程上执行线程的run方法中的代码。你想要thread.start()

相关JavaDoc

repaint 方法实际上不会立即重新绘制。它基本上告诉 JPanel 它应该很快重新绘制自己。然后你继续在同一个线程上计算 AI 的移动,这将冻结窗口,因为 Swing 不是多线程的。

于 2012-08-30T01:25:37.820 回答
1

首先,线程不能重入(我稍后会解释)。

thread.run()不会导致线程在单独的线程中执行,它只是调用run线程的方法(在当前Threads 上下文中。

您需要做的是在您的内部设置一个条件循环Thread,您可以触发它以执行您需要的逻辑。

public class ChessThread extends Thread { // I prefer Runnable, that's me
    protected static final Object NEXT_MOVE_LOCK = Object();

    public ChessThread() {
        setDaemon(true); // This will allow the JVM to exit without the need to terminate the thread...
    }

    public void doNextMove() {
        // Notify the "wait" that we want to continue calculating the next move
        synchronized (NEXT_MOVE_LOCK) {
            NEXT_MOVE_LOCK.notify();
        }
    }       

    public void run() { 
        while (true) {
            // Wait for the "next move" request
            synchronized (NEXT_MOVE_LOCK) {
                try {
                    NEXT_MOVE_LOCK.wait();
                } catch (InterruptedException exp) {
                }
            }
            // Calculate the next move...
        }
    }
}

现在,Threads 是不可重入的,这意味着一旦 run 方法完成,该实例Thread就不能重新启动。

因此使用thread.start()不止一次将不起作用(不记得它是否引发异常)(因此我更喜欢的原因Runnable

所以。你想要做的是Thread在你的程序加载时开始,当你需要时,调用thread.doNextMove()它来计算你需要的东西。

现在,还要记住,SwingThread不安全的。也就是说,您永远不应该从Thread事件调度线程(或 EDT)之外的任何地方更新 UI

您可能还想通读Swing 中的并发

,Java中的并发

于 2012-08-30T01:33:50.517 回答