1

我正在做的国际象棋中的计时器有问题。它工作“很好”,除了它计算两对二的秒数(2:00 > 1:58 > 1:56 等。但那是 1 秒的间隔,而不是 2 秒的间隔)

这是我定义、启动和结束计时器的代码:

private void setTime(){
    totalTime=20;
    whiteSec=0;
    whiteMin=totalTime;
    blackSec=0;
    blackMin=totalTime;
    ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              if(whiteActive){
                  if(whiteSec>0) whiteSec-=1;
                  else{
                      whiteMin-=1;
                      whiteSec=60;
                  }
                  if(whiteMin==0 && whiteSec==0) endGame();
                  else GUI.setPlayerTime(whiteMin, whiteSec);
              }else{
                  if(blackSec>0) blackSec-=1;
                  else{
                      blackMin-=1;
                      blackSec=60;
                  }
                  if(blackMin==0 && blackSec==0) endGame();
                  else GUI.setPlayerTime(blackMin, blackSec);
              }
          }
      };
    chessTimer = new Timer(1000, taskPerformer);
}

//开始

whiteActive = true;
setTime();
wCastling = true;
bCastling = true;
canEnPassant = false;
GUI.setPlayerTime(whiteMin, whiteSec); //this writes the time in some JLabels.
guiRefresh();
activePiece = null;
chessTimer.start();

//结尾

private void endGame(){
    GUI.endGame(checkMate);  //shows an endgame JOptionPane
    chessTimer.stop();
}

我会很感激任何帮助!

4

2 回答 2

4

虽然我不相信 Timer 可以启动两次,但多次调用setTime()会创建多个计时器,每个计时器都会独立地减少字段(直到第一个被垃圾收集,这可能会发生也可能不会发生)。如果连续两次调用该方法,两个 Timer 对象会共存一段时间,并且可能每秒递减两次;呼叫stop()将停止其中一个计时器并保留另一个计时器。

作为一个调试步骤(也是一个很好的实践),在创建新计时器之前检查您是否还没有计时器:

/* ... */
if (chessTimer != null) throw new IllegalStateException("setTime already called");
chessTimer = new Timer(1000, taskPerformer);

要修复它,跟踪重复调用,或通过将 IllegalStateException 替换为chessTimer.stop();.

于 2012-12-17T07:40:17.790 回答
1

来自http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html:此类不提供实时保证:它使用 Object.wait(long) 安排任务方法。

于 2012-12-17T07:08:12.317 回答