How do I get my black Jack game to pause a few seconds before showing the next card

40 Views Asked by At

I have this black jack game that I've been working on and I want the game to pause before it shows the next card like the dealer is dealing it. I have a method called dealersTurn that sorts out the dealers turn

public static void dealersTurn() throws InterruptedException {
        if(game.getDealerHand().hasAce()){
            while(!game.getDealerHand().didBust() && game.getDealerHand().getTotal() +10 < 17){
                Thread.sleep(2000);
                game.dealCard(game.getDealerHand());
                view.updateDealerPanel();
            }
            while(!game.getDealerHand().didBust() && game.getDealerHand().getTotal() + 10 > 21 && game.getDealerHand().getTotal() < 17){
                Thread.sleep(2000);
                game.dealCard(game.getDealerHand());
                view.updateDealerPanel();
            }
        }
        else {
            while(!game.getDealerHand().didBust()&& game.getDealerHand().getTotal() < 17){
                Thread.sleep(2000);
                game.dealCard(game.getDealerHand());

                view.updateDealerPanel();

            }
        }

    }

I tried using thread.sleep but instead of pausing in between dealing cards it pauses for what seems like the total amount of time that was paused for all the cards and then it shows all of the cards that were dealt all at once.

I thought it might be somethig with the view.updateDealerPanel but I can't figure it out

public void updateDealerPanel(){
        dealerPanel.setVisible(false);
        dealerPanel.removeAll();
        dealerPanel.setLayout(new FlowLayout());
        for(Card card : game.getDealerHand().getCards()){
            JLabel cardPic = new JLabel(new ImageIcon(card.getImg()));
            dealerPanel.add(cardPic);
        }
        JLabel tot = new JLabel("Total: " + game.getDealerHand().getTotalString());
        dealerPanel.add(tot);
        dealerPanel.setVisible(true);
    }

please help thank you

1

There are 1 best solutions below

0
gmifflen On

Like @MadProgrammer commented, using a Swing Timer is probably the best way to go about your problem.

Here's how you could add a Swing Timer to your code, as well as simplifying all those while loops:

public static void dealersTurn() {
  Timer timer = new Timer(2000, null);
  timer.addActionListener(e -> {
    // if the dealer has already busted; stop the timer
    if (game.getDealerHand().didBust()) {
      ((Timer) e.getSource()).stop();
      return;
    }

    boolean shouldDeal = false;
    if (game.getDealerHand().hasAce()) {
      // dh has an ace and total is less than 17 with ace counting as 11
      shouldDeal = game.getDealerHand().getTotal() + 10 < 17;
    } else {
      // else dh does not have an ace and total is less than 17
      shouldDeal = game.getDealerHand().getTotal() < 17;
    }

    if (shouldDeal) {
      game.dealCard(game.getDealerHand());
      view.updateDealerPanel(); // update after dealing a card
    } else {
      ((Timer) e.getSource()).stop(); // stop if no more cards can be dealt
    }
  });
  timer.setRepeats(true);
  timer.start();
}

though, another option, and the one I thought to first, was to use SwingWorker for background processing, alongside SwingUtilities.invokeLater().

This option would look something like this:

public static void dealersTurn() {
  new SwingWorker<Void, Void>() {
    @Override
    protected Void doInBackground() throws Exception {
      while (!game.getDealerHand().didBust() && shouldDealCard()) {
        Thread.sleep(2000);
        SwingUtilities.invokeLater(() -> {
          game.dealCard(game.getDealerHand());
          view.updateDealerPanel();
        });
      }
      return null;
    }

    private boolean shouldDealCard() {
      int total = game.getDealerHand().getTotal();
      boolean hasAce = game.getDealerHand().hasAce();
      return (hasAce && total + 10 < 17) || (!hasAce && total < 17)
          || (total + 10 > 21 && total < 17);
    }
  }.execute();
}

as you can see, this option is a lot uglier, and bloated compared to just using a Swing Timer. I just added it in case you wanted a different choice from the Timer :)