1

I've been assigned to make a Black Jack game. I want it to be replayable by pressing a button when the round is over. I've set it up so that I have a method named initGame() that plays each player and the dealer a card each, and enables players[] buttons. It then runs runGame(), which is supposed to check if a player is done playing (over 21/pressed stay).

When all players are deone it then sets running to false, enabling the resetbutton, which then runs initGame(). I kind of want it to loop around like this. However, the game freezes the second time runGame() is ran, when initNewGame() works fine.

private void initNewGame(){  
    dealer.addCard();  
    for(int i = 0; i < numberofplayers; i++){  
        players[i].addCard();                                                                     //draws card, adds score and paints card to the board  
        players[i].setStatus(false);                                                              //makes the buttons usable in the players[] class  
    }  
    runGame();  
}    

/* 
 * runGame() is meant to check if the players all have played out their hand, to then allow the dealer to play his. After that it sets running = false, allowing the player to either use the shuffle button or start a new game 
 */     
private void runGame(){  
    while(running){     
        int count=0;                                                                    
        for(int i = 0; i<numberofplayers; i++){                                       //loops through all the player checking their status  
            if(players[i].getStatus()) count++;  
        }                           
        if(count==numberofplayers){                                                  //checks if all players have >=21 or have pressed stay  
            dealer.addCard();                                                        //plays the dealers hand  
            if(dealer.getPoints() >=19){                                             //stops when dealer have >=19  
                running = false;                                                     //stops entire loop                                                           
            }                                
        }  
    }  
}  

class ButtonListener implements ActionListener  
{  
    public void actionPerformed(ActionEvent e){  
        if(!running){                                                               //won't allow players to reset while a round is playing   
            if(e.getSource().equals(resetbutton)){                                  //Checks for rese/new game button  
                System.out.println("reset");  
                dealer.setPoints(0);                                                //sets dealers hand to 0  
                dealer.paintText();                                                 //updates delaers painted score  
                dealer.clearCards();                                                //clear the painted cards   
                for(int i = 0; i < numberofplayers; i++){  
                    players[i].setPoints(0);                      
                    players[i].clearCards();                              
                    players[i].paintText();  
                }                      
                gui.repaint();  

                running = true;                                                     //allows the runGame() to start  
                initNewGame();                                                      //this one works the second time  
            }else if(e.getSource().equals(shufflebutton)){                 
                d1.shuffleDeck();  
                System.out.println(running);  
            }  
        }                           
    }  
} 
GameDroids
  • 5,584
  • 6
  • 40
  • 59
AlexVestin
  • 2,548
  • 2
  • 16
  • 20
  • Does it reach the `running = false`? What happens if you put a breakpoint 2 IF's up and step? – mattias Nov 09 '14 at 20:20
  • The program becomes unresponsive, however it doesnt leave an exception. The runGame() loops continues, though – AlexVestin Nov 09 '14 at 20:20
  • 1
    Try investigating where the problem is. Put prints or breakpoints in problem places in the code to see where exactly the program is looping. – Mojo Risin Nov 09 '14 at 20:21
  • It does reach the running = false statement, stopping the loop once, when I try to restart it it freezes – AlexVestin Nov 09 '14 at 20:21
  • I've tried to some investigating, and the loop keeps runnning ( I get prints from inside all parts of the runGame() loop, except the one I shouldnt – AlexVestin Nov 09 '14 at 20:23

2 Answers2

3

Your problem is due to your while loop blocking the GUI's event thread, freezing the GUI. But more importantly...

Yours looks to be a Swing GUI (you don't tell us, so I'm guessing based on the there being an ActionListener). If so, you need to re-think your program flow and structure so that it conforms to event-driven programming principles. You should get rid of that while (running) loop, and instead give your class a field for the Player whose turn it is, and have the program change the value of that field after each player takes a turn.

For a very simple example, here's a small GUI that shows one active player at a time. If the active player is clicked on, then the next player becomes active. There are no while loops involved but instead I change the state of the program when needed:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

@SuppressWarnings("serial")
public class CardGameGui extends JPanel {
   public static final String[] PLAYER_NAMES = {"John", "Bill", "Frank", "Andy"};
   private static final Color ACTIVE_BG = Color.pink;

   // a Map that allows us to associate a JLabel with a CardPlayer
   private Map<CardPlayer, JLabel> playerLabelMap = new HashMap<CardPlayer, JLabel>();
   private CardPlayers cardPlayers = new CardPlayers(PLAYER_NAMES);
   public CardPlayer currentPlayer = cardPlayers.getCurrentPlayer(); 

   public CardGameGui() {
      setLayout(new GridLayout(1, 0, 5, 0));

      for (CardPlayer cardPlayer : cardPlayers) {
         JLabel playerLabel = createPlayerLabel(cardPlayer);
         playerLabelMap.put(cardPlayer, playerLabel);
         add(playerLabel);
      }

      playerLabelMap.get(currentPlayer).setBackground(ACTIVE_BG);
      cardPlayers.addPropertyChangeListener(new CardPlayersListener());
   }

   private JLabel createPlayerLabel(CardPlayer player) {
      JLabel label = new JLabel(player.getName());
      label.setOpaque(true);
      int ebGap = 15;
      label.setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
      label.addMouseListener(new PlayerLabelListener());
      return label;
   }

   public void activateCurrentLabel(CardPlayer currentPlayer) {
      for (CardPlayer cardPlayer : cardPlayers) {
         playerLabelMap.get(cardPlayer).setBackground(null);
      }

      playerLabelMap.get(currentPlayer).setBackground(ACTIVE_BG);
   }


   private class CardPlayersListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (CardPlayers.CARD_PLAYER.equals(evt.getPropertyName())) {
            currentPlayer = cardPlayers.getCurrentPlayer();
            System.out.println(currentPlayer);
            activateCurrentLabel(currentPlayer);
         }
      }
   }

   private class PlayerLabelListener extends MouseAdapter {

      @Override
      public void mousePressed(MouseEvent mEvt) {
         JLabel playerLabel = (JLabel) mEvt.getSource();
         JLabel currentPlayerLabel = playerLabelMap.get(currentPlayer);

         if (playerLabel == currentPlayerLabel) {
            cardPlayers.incrementPlayerIndex();
         }
      }
   }

   private static void createAndShowGui() {
      CardGameGui mainPanel = new CardGameGui();

      JFrame frame = new JFrame("CardGame");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }


   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class CardPlayers implements Iterable<CardPlayer> {
   public static final String CARD_PLAYER = "card player";
   private List<CardPlayer> playerList = new ArrayList<>();
   private int currentPlayerIndex = 0;
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public CardPlayers(String[] playerNames) {
      for (String playerName : playerNames) {
         playerList.add(new CardPlayer(playerName));
      }
   }

   public CardPlayer getCurrentPlayer() {
      return playerList.get(currentPlayerIndex);
   }

   public void incrementPlayerIndex() {
      CardPlayer oldValue = getCurrentPlayer();
      currentPlayerIndex++;
      currentPlayerIndex %= playerList.size();
      CardPlayer newValue = getCurrentPlayer();
      pcSupport.firePropertyChange(CARD_PLAYER, oldValue, newValue);
   }

   @Override
   public Iterator<CardPlayer> iterator() {
      return playerList.iterator();
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

}


class CardPlayer {
   private String name;

   public CardPlayer(String name) {
      this.name = name;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Override
   public String toString() {
      return "CardPlayer: " + name;
   }

}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • It is indeed a Swing GUI, sorry for being unclear. I'm gonna look up a bit around event driven programming, thanks :) – AlexVestin Nov 09 '14 at 20:38
  • @AlexVestin: please have a look at the code I've posted and see if it might help. – Hovercraft Full Of Eels Nov 09 '14 at 20:40
  • I looked a bit at the code, and I think I understand (mostly) how it works. I'm going to need to look into actionlisteners/interfaces (aswell as layouts and maps) though. Thanks for the help! – AlexVestin Nov 09 '14 at 21:07
0

Problem is that you called initNewGame(); from within event handler code. You should use the same thread as in the first initNewGame call or create a new one.

FDIM
  • 1,981
  • 19
  • 21