2017-10-18 88 views
0

没关系,所以我正在进行一场桌上游戏。 第一个'while循环'检查游戏是否结束,内部'while循环'应该等待用户输入(squareSelector和rooSelector是我的mouselisteners,'k'和's'是应该输入的被听众返回) 然而,'while循环'崩溃了我的程序并阻止了我的侦听器工作。 我读了这个,发现swing是单线程的,所以我的听众在whileloop处于活动状态时无法工作。不过,我需要等待输入,以避免空指针。 关于如何解决这个问题的任何想法? (如在一个不同的方法,或者如何使我的循环等待输入)虽然循环阻止我的听众工作

的gameloop

while(currentPlayer.haveIWon() == false){ 
     //wait for input 
     while(!inputIsDone){ 
      System.out.println("waiting for move"); 
      System.out.println(squareSelector.isDone() + " " + rooSelector.isDone()) ; 
      checkInput() ; 
      if(squareSelector.isDone() && rooSelector.isDone()){ 
       inputIsDone = true ; 
      } 
     } 
     //update board 
     currentPlayer.performMove(k, s); 
     rooSelector.setDone(false); 
     squareSelector.setDone(false); 
     inputIsDone = false ; 
     //currentPlayer.setInput(false); 
     //repaint 
     Main.getState().getComponent().repaint(); 

    } 
    //display winnner thing 

的checkInput方法

public void checkInput(){ 
    if(rooSelector.getSelected() != null){ 
     k = rooSelector.getSelected() ; 
    } 
    if(squareSelector.getSelected() != null){ 
     s = squareSelector.getSelected() ; 
    } 
} 

如果你需要更多的代码来了解这是怎么回事让我知道,我会添加更多。

+0

不应该阻止[事件调度线程](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html)。 - 问题在于你的循环阻止了EDT处理输入事件。游戏循环(如果有必要的话)应该在其自己的线程中运行(例如通过[SwingWorker](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html))。 – Thomas

+0

在cheking输入明智的循环包括一种方法来防止通过饥饿杀死他人的Thread:Thread.yield()或Thread.sleep(1) – Doleron

+0

一般来说,游戏不会不断更新其UI(即没有动画)或世界(即不是“实时”)很少需要游戏循环。你声明你需要一个来防止NPE,但是这意味着设计缺陷或编码错误,而不是真正需要循环。 – Thomas

回答

0

Swing是单线程的。由于其设计,与GUI相关的所有内容都必须在Swing线程上完成,也称为事件分派线程。它基本上做了一件事:看事件队列,如果有某事,它会处理它,如果没有,就进入睡眠状态。每个鼠标移动,按键,重画等都是事件队列中的事件。

如果您的游戏只对GUI事件做出反应并且没有冗长的操作,则不必使用任何特殊的操作。你可以在没有while的情况下编写你的逻辑,以便它不会阻塞,只对事件做出反应。但是,这种可能性完全取决于您正在尝试实施的内容。

如果您有任何长时间阻塞该线程的操作,则需要为此使用单独的线程。这样,其他线程不会影响您的GUI,但您需要非常小心地将数据从一个线程发送到另一个线程,或者在另一个线程上调用某些线程。