循环制作程序冻结

时间:2014-11-09 20:16:04

标签: java

我已被指派制作黑杰克游戏。我希望在圆形结束时按下按钮可重放。我已经设置了它,所以我有一个名为initGame()的方法,每个玩家和经销商各自玩一张牌,并启用玩家[]按钮。然后它运行runGame(),它应该检查玩家是否完成了游戏(超过21 /按住)。

当所有玩家都被取消时,然后将运行设置为false,启用resetbutton,然后运行initGame()。我有点希望它像这样循环。但是,当initNewGame()工作正常时,游戏第二次运行runGame()时冻结。

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);  
            }  
        }                           
    }  
} 

2 个答案:

答案 0 :(得分:3)

您的问题是由于您的while循环阻止了GUI的事件线程,冻结了GUI。但更重要的是......

你看起来像是一个Swing GUI(你不能告诉我们,所以我根据有一个ActionListener来猜测)。如果是这样,您需要重新考虑您的程序流程和结构,以使其符合事件驱动的编程原则。你应该摆脱那个while (running)循环,而是让你的班为其轮到的玩家提供一个字段,并让程序在每个玩家转弯后更改该字段的值。

举一个非常简单的例子,这里有一个小型GUI,一次显示一个活跃的玩家。如果单击活动播放器,则下一个播放器变为活动状态。没有涉及while循环,而是在需要时更改程序的状态:

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;
   }

}

答案 1 :(得分:0)

问题是你调用了initNewGame();从事件处理程序代码中。 您应该使用与第一个initNewGame调用中相同的线程或创建一个新线程。