2015-06-11 69 views
1

我決定做一些有趣的事情,作爲閱讀編程書籍的休息時間,並且我遇到了困難。這是我的第一個揮杆計劃,並準備好結束它!Java搖擺和線程睡覺

問題:我顯然不明白線程如何與Swing配合使用。我正在編寫黑色插孔遊戲的GUI,並且我首先完成了所有功能,例如當玩家擊中時向屏幕上繪製新牌,在玩家決定停留後顯示莊家擊中等等。這一切都有效。

當我添加邏輯來檢查用戶擊中時的情況,或者誰在用戶決定停留時獲勝時,遊戲會立即進入贏/輸屏幕,然後再繪製:用戶得到的那張牌胸圍,或;莊家在擊中時繪製的牌(如果有的話)。

我試圖在各個地方插入Thread.sleep,無濟於事。程序會在抽出卡片之前休眠,然後像上面一樣立即結束(即使它是在調用繪製之後以及在計算獲勝者之前在邏輯上放置的)。

此外,我試圖遵循MVC範例,只是fyi。

P.S.我的程序在一個線程上運行,我沒有明確實例化另一個線程,但我隱約記得讀到Swing產生它自己的線程圖形的東西

對不起,這段長的介紹!下面是一些代碼:

模型類的相關方法

void hit() { 
    //run when button is clicked 
    player.hand.add(deck.deck.get(0)); 
    deck.deck.remove(0); 
} 

boolean isBust() { 
    if (player.getScore() > 21) 
     return true; 

    return false; 

} 

void dealerHit() { 
    while (dealer.getScore() < 17) { //could implement soft 17 rules for more difficulty 
     dealer.hand.add(deck.deck.get(0)); 

     setChanged(); 
     notifyObservers(); 
     deck.deck.remove(0); 


     //Here was one attempt 
     try { 
      TimeUnit.SECONDS.sleep(1); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

boolean isWin() { 

    //and another 
    try { 
     TimeUnit.SECONDS.sleep(1); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    if ((player.getScore() > dealer.getScore() && player.getScore() <= 21) || dealer.getScore() > 21) 
     return true; 

    return false; 
} 

void stay() { 
    dealerHit(); 
    isWin(); 
} 

視圖類

void addHitListener(ActionListener HitListener) { 
    hit.addActionListener(HitListener); 
} 

void addStartListener(ActionListener StartListener) { 
    start.addActionListener(StartListener); 
} 

void addStayListener(ActionListener StayListener) { 
    stay.addActionListener(StayListener); 
} 

void display() { 
    JFrame myFrame = new JFrame("BlackJack"); 
    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    myFrame.setContentPane(this); 
    myFrame.setPreferredSize(new Dimension(700,550)); 

    myFrame.pack(); 
    myFrame.setVisible(true); 
} 

void addCards(Player p, Dealer d) { 
    topPanel.remove(start); 

    pcardPanel.add(playerlabel); 
    dcardPanel.add(dealerlabel);   

    for (Card c : p.hand) { 
     ImageIcon cc = new ImageIcon(c.img); 
     JLabel cC = new JLabel(cc); 

     //cC.setAlignmentX(alignmentX); use to get X alignment of card 1 & 2 for splits 
     //cC.setAlignmentY(alignmentY); same for Y, then increment by .3f 

     pcardPanel.add(cC); 


    } 

    for (Card c : d.hand) 
     dcardPanel.add(new JLabel(new ImageIcon(c.img))); 

    topPanel.add(new JLabel("Options: ")); 
    topPanel.add(hit);        
    topPanel.add(stay);        

    validate(); 
    repaint(); 
} 

void endGame(boolean isWin) { 

    //I think I tried here, too 

    removeAll(); 
    setBackground(new Color(0, 122, 0)); 

    if (isWin == true) 
     add(new JLabel("You won!")); 
    else 
     add(new JLabel("You Lost")); 

    validate(); 
    repaint(); 
} 

public void hitPlayer(Player p) { 
    JLabel hits = new JLabel(new ImageIcon(p.hand.get(p.hand.size()-1).img)); 
    //hits.setAlignmentY(alignmentY); 

    pcardPanel.add(hits); 

    validate(); 
    repaint(); 
} 

public void hitDealer(Dealer d) { 
    dcardPanel.add(new JLabel(new ImageIcon(d.hand.get(d.hand.size()-1).img))); 
    validate(); 
    repaint(); 
} 

控制器類:

public class Controller implements Observer { 

BlackJack game; 
Table t; 

Controller(BlackJack game, Table t) { 
    this.game = game; 
    this.t = t; 

    this.game.addObserver(this); 
    this.t.addHitListener(new HitListener()); 
    this.t.addStartListener(new StartListener()); 
    this.t.addStayListener(new StayListener()); 

} 

public void go() { 
    t.display(); 
} 

public void update(Observable obj, Object observed) { 
    t.hitDealer(game.getDealer()); 
} 

class HitListener implements ActionListener { 

    public void actionPerformed(ActionEvent e) { 

     game.hit(); 

     t.hitPlayer(game.getPlayer()); 

     if (game.isBust() == true) 
      t.endGame(false); 

    } 
} 

class StartListener implements ActionListener { 

    public void actionPerformed(ActionEvent e) { 
     t.addCards(game.getPlayer(), game.getDealer()); 
    } 
} 

class StayListener implements ActionListener { 

    public void actionPerformed(ActionEvent e) { 
     game.stay(); 
     //doStay(); 

     if (game.isWin() == true) 
      t.endGame(true); 
     else 
      t.endGame(false); 
    } 
} 

我只是有一個想法,因爲我m在actionPerformed方法中這樣做,這可能是睡眠似乎影響GUI線程的原因,而不是繪製卡(s)然後睡覺。我敢打賭就是這樣。但我要吃晚餐,希望有人比我更聰明可以伸出援助之手!在此先感謝

P.P.S.如果有任何拼寫錯誤(我認爲不存在),只要知道它是編譯和工作的!並沒有任何警告,如果有幫助

+0

[併發在Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/),[如何使用Swing定時器](http://docs.oracle.com/javase/tutorial /uiswing/misc/timer.html),[Worker Threads and SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) – MadProgrammer

回答

3

揮杆的確是一個單線程庫,最喜歡的UI。還有許多優化,使其工作速度很快。舉個例子 - 大多數作品都被緩存並一起展示。即使情況並非如此,你仍然依賴於系統的速度,這不是一個好主意。

如果你想延遲動作,你需要use swing's timer(不要與其他計時器類混淆)。該類有一個動作監聽器,當定時器到期時會關閉。在你的情況下,你會發現勝利/蕭條的情況,啓動計時器(例如在2秒鐘內開火)並像往常一樣繼續繪圖。

+1

這就像一個魅力! –

1

這是有點太長,我閱讀和理解......但我想你的問題是因爲你正在處理在Event Dispatching Thread的一切。

當您在GUI上繪製某些東西然後進行更多處理時,只有當整個線程完成處理時,繪圖纔會實際反映在GUI上。這就是爲什麼您在Thread.sleep方法之前沒有看到您的圖紙。

相反,您應該使用SwingWorker將處理和GUI更新拆分爲不同的線程。

看這個https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

+0

每個說的答案都沒有錯,但是因爲似乎OP想要在「擊中」和「結束遊戲」狀態之間插入一個延遲,一個Swing「Timer」可能是一個更好的解決方案......只是說;) – MadProgrammer