Java Thread.sleep导致我以前调用的方法取消

时间:2013-06-14 23:07:09

标签: java thread-sleep

标题可能不正确,但我想不出别的什么来命名这个问题。

我的问题是我写的一些Java代码让我疯了。基本上我正在尝试制作一个“卡片记忆”游戏,其中我有4X4网格布局;当你点击一个它翻转,然后你点击第二个,它翻转,如果它们是同一张卡它会消失,如果它们是不同的卡,它会翻转它们。

除了一个小细节外,这个工作正常。当你点击第一张卡片时它会翻转,然后当你点击第二张卡片时它翻转它并快速检查它的值,以至于你无法判断第二张卡片在它们消失之前是否完全翻转或第一张卡片是翻过来。所以我添加了

try{Thread.sleep(2000);}catch(InterruptedException ex) {}

我翻了第二张卡片后。那么现在很明显,第二张卡根本不会翻转。我点击第一张卡,它翻转,我点击第二张卡,它等待2秒(线程睡眠),然后它确定相等,并隐藏或翻转第一张卡。所有这些都没有显示第二张卡是什么。

我要添加下面的所有代码。对不起,我很抱歉,但我不知道哪个部分是相关的。

Card.java

import objectdraw.*;
import java.awt.Image;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Card {

  private int value;
  private VisibleImage imageFront, imageBack;

  public Card(int val, Location p, double w, double h, DrawingCanvas c) {

    value = val;
    String urlStr = "images/" + val + ".png";
    BufferedImage img = null, imgb = null;
    try {
      img = ImageIO.read(new File(urlStr));
      imgb = ImageIO.read(new File("images/card-back.png"));
    } catch(IOException ex) {}
    imageFront = new VisibleImage(img,p,w,h,c);
    imageFront.hide();
    imageBack = new VisibleImage(imgb,p,w,h,c);

  }

  public void flip() {
    if(imageFront.isHidden()) {
      imageFront.show();
      imageBack.hide();
    } else {
      imageBack.show();
      imageFront.hide();
    }
  }

  public Boolean contains(Location p) {
    if(imageFront.isHidden()) {
      return imageBack.contains(p);
    } else {
      return imageFront.contains(p);
    }
  }

  public void moveTo(double x, double y) {
    imageFront.moveTo(x,y);
    imageBack.moveTo(x,y);
  }

  public int getValue() {
    return value;
  }

  public void hide() {
    imageFront.hide();
    imageBack.hide();
  }

}

Grid.java

import objectdraw.*;

public class Grid {

  private static final int ROWS = 4;
  private static final int COLS = 4;

  private Card[] cards = new Card[COLS * ROWS];

  public Grid(double cardW, double cardH, DrawingCanvas c) {

    int cnt = 0;
    Location p1 = new Location(0,0);
    Location p2 = new Location(0,(ROWS/2)*cardH);
    for(int i = 0; i < ROWS; i++) {

      for(int j = 0; j < COLS; j++) {

        // Set up 2 of the same card, one at cnt and one at cnt + cards.length/2
        if(cnt < cards.length/2) {

          cards[cnt] = new Card(cnt+1,p1,cardW,cardH,c);
          p1.translate(cardW,0);
          cards[cnt + cards.length/2] = new Card(cnt+1,p2,cardW,cardH,c);
          p2.translate(cardW,0);
          cnt++;

        }

      }

        p1.translate(-(cardW * COLS),cardH);
        p2.translate(-(cardW * COLS),cardH);

    }

  }

  private static int sel = -1;

  public void select(Location p) {

    for(int i = 0; i < cards.length; i++) {

      // Find the correct card
      if(cards[i].contains(p)) {

        if(sel == -1) {

          // This is the first card selected
          System.out.printf("\nThis is the first card selected");
          cards[i].flip();
          sel = i;
          break;

        } else {
          System.out.printf("\nThis is the second card");

          // They selected the same card
          if(i == sel) {
            break;
          } else {

            // This is the second card selected and it's unique
            // Flip it and check if they match. If they do, then hide both,
            // if they don't then flip both back
            cards[i].flip();

            if(cards[i].getValue() == cards[sel].getValue()) {
              try {
                remove(cards[i], cards[sel]);
              } catch(InterruptedException ex) {}
              sel = -1;
              break;
            } else {
              cards[i].flip();
              cards[sel].flip();
              sel = -1;
              break;
            }

          }

        }

      }

    } // for loop

  }

  public void remove(final Card card1, final Card card2) throws InterruptedException {
    new Thread() {
      public void run() {
        sleep(2000);
        card1.hide();
        card2.hide();
      }
    }.start();
  }

}

Client.java

import objectdraw.*;

public class Client extends WindowController {

  public static void main(String[]args) {
    new Client().startController(310,460);
  }

  Grid board;
  public void begin() { 
    board = new Grid(75,102,canvas);
  }

  public void onMouseClick(Location p) {
    board.select(p);
  }

}

作为参考,所有这些都来自objectdraw library

1 个答案:

答案 0 :(得分:1)

我会将select()remove()逻辑分开。正好在这里:

if(cards[i].getValue() == cards[sel].getValue()) {
    remove(cards[i], cards[sel]); //call the remove

remove()会启动一个Thread并删除想要的值:

public void remove(final Card card1, final Card card2) {
    new Thread() {
        @Override
        public void run() {
            try {
                sleep(2000);
            } catch (InterruptedException e) {
            }
            card1.hide();
            card2.hide();
        }
    }.start();
}

所以这样你就不会阻止UI线程(用户可以看到翻转),新线程会在两秒后隐藏卡片。