java - 如何让线程按顺序打印java

标签 java multithreading

有些人可能之前看过这段代码,我继续了它,现在我遇到了空指针和indexOutOfBound异常的问题。有时会出现索引越界错误,具体取决于玩家数量或手牌大小。

这是代码,主要的 CardGame 类

public class CardGame
{
   static Player[] players;
   static int handSize;
   static Queue<Card>[] playingDeckArray;
   static int playersNum;

   public static void main(String[] args){
        Scanner reader = new Scanner(System.in);

        System.out.println( "\nHello, how many players would you like" );
        playersNum = Integer.parseInt(Checks.userInputCheck( "\\d" ));
        System.out.println( "\nHow many cards should each player begin with" );
        int handSize = Integer.parseInt(Checks.userInputCheck( "\\d" ));
        System.out.println( "\nWhich strategy would you like to use 1 or 2" );
        int strategy = Integer.parseInt(Checks.userInputCheck( "[12]$" ));

        Logger.createDeck( playersNum, handSize );

        makePlayers( playersNum, handSize, strategy );

        makePlayingDecks( playersNum );

        dealInitialHand( playersNum, players, handSize );

        makePlayerOutputs();

        //Player.startPauseThread();

        for ( int i = 0; i < players.length; i++){
           logInitialHand(players[i]);
        }

        for ( int i = 0; i < players.length; i++){
           isWinner( players[i]);
        }

        for ( int i = 0; i < players.length; i++){
            new Thread(players[i]).start();
        }
   }

   private static void makePlayers(  int noPlayers, int noCardsInHand, int strategyChosen){
       players = new Player[noPlayers];
       for( int i = 0; i < noPlayers; i++){
           players[i] = new Player( strategyChosen, noCardsInHand, i+1 );
           players[i].fillHand();
       }

   }

   private static void dealInitialHand(int noPlayers, Player[] players, int noCardsInHand ){
       System.out.println( "\nPlease enter the name of the deck file" );
       File theDeck = new File (Checks.userInputCheck( "deckfile.txt" ) );

       int line = 0;

       try{
           Scanner fileScanner = new Scanner( theDeck );
           for( int h = 0; h < noCardsInHand; h++){
               for( int p = 0; p < noPlayers; p++){
                    line = Integer.parseInt( fileScanner.nextLine() );
                    players[p].setHand( line, h );
               }
           }

           for( int t = 0; t < noCardsInHand; t++){
               for( int i = 0; i < playingDeckArray.length; i++ ){
                   line = Integer.parseInt( fileScanner.nextLine() );
                   playingDeckArray[i].add( new Card(line) );
                }
               }

            }catch (Exception e) {
           e.printStackTrace();
       }

       seePlayerHands();
   }

   private static void makePlayingDecks( int noPlayers ){
       playingDeckArray = new Queue[noPlayers];
       for( int i = 0; i < playingDeckArray.length; i++ ){
           playingDeckArray[i] = new ConcurrentLinkedQueue<Card>();
           System.out.println( playingDeckArray[i] );
        }

   }

   private static void seePlayerHands(){
       for ( int i = 0; i < players.length; i++){
          System.out.println( players[i].getPlayerName() + "'s hand is currently" );
          players[i].seeHand();
        }
   }

   private static void makePlayerOutputs(){
       for ( int i = 0; i < players.length; i++){
           Logger.createPlayerOutputs( players[i].getPlayerName());
        }
   }

   private static void logInitialHand( Player player ){
       Logger.addToOutput( player.getPlayerName(), ( player.getPlayerName() + "'s initial hand is " ) );
       Logger.addToOutput( player.getPlayerName(), player.getHand() );
   }

   private static void isWinner( Player player ){
        boolean winner = true;
        int first = player.hand[0].getCardValue();

        for (Card element : player.hand) {
           if (element.getCardValue() != first) {
               winner = false;
            }
        }

        if ( winner == true ){
            Logger.addToOutput( player.getPlayerName(), ( player.getPlayerName() + " has won the game with a hand of " ) );
            Logger.addToOutput( player.getPlayerName(), player.getHand() );
            System.out.println( player.getPlayerName() + " has won the game with a hand of " );
            player.seeHand();
            System.exit(0);
        }
   }
}

玩家类 公共(public)类 Player 实现 Runnable { 卡牌[]手牌; 字符串玩家名称; int策略选择; int 玩家编号;

    private boolean running = true;
    private boolean paused = false;

    public void setPaused( boolean paused ){
        this.paused = paused;
    }

    public void run(){
        while(running){
            if(!paused){
              synchronized(this){  
                  playGame();
                }
         }
       }
    }

    private void playGame(){
        synchronized(this){
        switch(strategyChosen){
             case 1 : playStratOne();
             break;
             case 2 : playStratTwo();
             break;
            }
        }
    }

    public static void startPauseThread(){
     Thread add = new Thread( pauseInputThread );
     add.start();
   }


   static Thread pauseInputThread = new Thread(){
     private boolean running = true;
     private boolean paused = false;

      public void run(){ 
            while(running){
              if(!paused){
                  for(;;){
                    System.out.println("FEED ME");
                    Scanner reader = new Scanner(System.in);
                    String result = Checks.userInputCheck( "[pPrR]$" );
                       if( result == "p" ){
                           for ( int i = 0; i < CardGame.players.length; i++ ){
                            CardGame.players[i].setPaused( true );
                        }
                    }
                }
              }
            }
       }
      };

    private Player(){
    }

    private int getPlayerNumber(){
        return playerNumber;
    }

    public Player( int strategy, int cardsInHand, int playerNumber ){
        hand = new Card[cardsInHand];
        strategyChosen = strategy;
        this.playerNumber = playerNumber;
        playerName = "Player " + playerNumber;
    }

    public String getPlayerName(){
        return playerName;
    }

    public void fillHand(){
       for ( int i = 0; i < hand.length; i++){
            hand[i] = new Card(0);
       }
    }

    public void setHand( int value, int index ){
        hand[index].setCardValue( value );
    }

    public void seeHand(){
        for ( int i = 0; i < hand.length; i++){
            System.out.println( hand[i].getCardValue() );
        }
    }

    public String getHand(){
        String result = "";
        for ( int i = 0; i < hand.length; i++ ){
            result = result +  hand[i].getCardValue() + " \n" ;
        } 
        return result;
    }

    public int getHandValue( Card card ){
        return card.getCardValue();
    }

    private void playStratOne(){
        System.out.println("fuck");
    }

    private void playStratTwo(){
        synchronized(this){
            int index = 0;
            System.out.println( getPlayerName() + " discards a " + hand[index].getCardValue() + " to deck " + playerNumber );
            CardGame.playingDeckArray[playerNumber-1].add( new Card( getHandValue(hand[index])));

            for( int i = 1; i < hand.length+1; i++){
                if ( index == hand.length-1 ){
                    hand[index] = null;
                }else{
                    hand[index] = hand[index+i];
                    index = index + i; 
                }
            }
            if ( playerNumber == 1){
                System.out.println( getPlayerName() + " draws a " + ((CardGame.playingDeckArray[playerNumber + CardGame.playersNum - 2].poll()).getCardValue()) + " from deck " + ( CardGame.playersNum ) );
                hand[index] = CardGame.playingDeckArray[playerNumber + CardGame.playersNum - 2].poll();
            }else{
                System.out.println( getPlayerName() + " draws a " + (( CardGame.playingDeckArray[playerNumber - 2].poll()).getCardValue())  + " from deck " + ( playerNumber - 1 ) );
                hand[index] = CardGame.playingDeckArray[playerNumber - 2].poll();
            }

            System.out.println(getPlayerName()+ "'s hand is ");
            seeHand();
            for( int i = 0; i < CardGame.playingDeckArray.length; i++ ){
            }

            checkWinner();
        }
    }

    private void checkWinner(){
        boolean winner = true;
        int first = hand[0].getCardValue();

        for (Card element : hand) {
            if (element.getCardValue() != first) {
                winner = false;
            }
        }

        if ( winner == true ){
            Logger.addToOutput( getPlayerName(), ( getPlayerName() + " has won the game with a hand of " ) );
            Logger.addToOutput( getPlayerName(), getHand() );
            System.out.println( getPlayerName() + " has won the game with a hand of " );
            seeHand();
            System.exit(0);
        }
   }
}

卡片类

 public class Card
 { 
    int cardValue;

    private Card(){
    }

    public Card( int value ){
        cardValue = value;
    }

    public void setCardValue( int value ){
        cardValue = value;
    }

    public int getCardValue(){
        return cardValue;
    }

    public  int getCardValue( Card card ){
        return cardValue;
    }
}

游戏的目标是拥有一手所有相同值(value)的牌。

我想知道是否有办法让线程按顺序打印,而且我不明白为什么会出现 nullPointers 和 IndexOutOfBounds 错误

这是手牌大小为 2 的 2 人游戏的结果

Hello, how many players would you like
2
Thank You


How many cards should each player begin with
2
Thank You


Which strategy would you like to use 1 or 2
2
Thank You

The deck has been created 
It is called deckfile.txt 

Please enter the name of the deck file
deckfile.txt
Thank You

Player 1's hand is currently
1
3
Player 2's hand is currently
2
3
Player 1 discards a 1 to deck 1
Player 1 draws a 4 from deck 2
Player 2 discards a 2 to deck 2
Player 1's hand is 
Player 2 draws a 4 from deck 1
3
2
Player 2's hand is 
3
1
Player 1 discards a 3 to deck 1
Player 2 discards a 3 to deck 2
Player 1 draws a 2 from deck 2
Player 2 draws a 1 from deck 1
Player 1's hand is 
2
3
Player 1 discards a 2 to deck 1
Player 2's hand is 
1
3
Player 2 discards a 1 to deck 2
Player 2 draws a 2 from deck 1
Player 2's hand is 
3

这会产生 nullPointer 异常,当我玩手大小为 5 的 5 人游戏时

Player 1's hand is currently
1
4
1
4
8
Player 2's hand is currently
2
1
1
3
1
Player 3's hand is currently
3
2
10
6
2
Player 4's hand is currently
3
7
5
8
6
Player 5's hand is currently
4
4
2
1
4
Player 1 discards a 1 to deck 1
Player 2 discards a 2 to deck 2
Player 5 discards a 4 to deck 5
Player 3 discards a 3 to deck 3
Player 4 discards a 3 to deck 4

我收到了indexOutOfBounds异常

Exception in thread "Thread-8" Exception in thread "Thread-9" java.lang.ArrayIndexOutOfBoundsException: 6
at Player.playStratTwo(Player.java:132)
at Player.playGame(Player.java:38)
at Player.run(Player.java:27)
at java.lang.Thread.run(Thread.java:722)

抱歉,如果我要求太多,但我们将不胜感激。

最佳答案

让我们看一下下面的代码:

int index = 0;
System.out.println( getPlayerName() + " discards a " + hand[index].getCardValue() + " to deck " + playerNumber );
CardGame.playingDeckArray[playerNumber-1].add( new Card( getHandValue(hand[index])));

for( int i = 1; i < hand.length+1; i++){
    if ( index == hand.length-1 ){
        hand[index] = null;
    }else{
        hand[index] = hand[index+i];
        index = index + i; 
    }
}

因此,在 for 循环开始时,index 的值不能不同于 0。

如果 hand.length 是 5,那么循环将从 1 到 5 - 当“i 比数组长度多不到一”时运行会很困惑,但这就是你的意思我得到了。这样做的一个潜在问题是 java 数组从 0 开始,因此如果数组长度为 5,那么它有卡片 0-4,而不是 1-5。如果您将数组声明为长度为 6,这可能没问题。我还没有深入研究您的所有代码来确定您是如何声明它的。

因此循环从 1 运行到 5;如果索引为 4,则将该元素设置为 null。因此索引 1、2、3 和 5 处的值将尝试执行 if 语句的其他部分。如果是 5,那么您最好有一个可容纳索引 6(长度为 7)的数组,因为数组中有一个索引 + i。显然你没有,因为你的错误消息说 6 是数组索引越界。

Java 错误消息和堆栈跟踪是其两个最有用的功能。他们最常告诉您问题是什么以及在代码中的哪个位置发现问题——这在编程世界中并不通用。如果您要使用 Java 编程,请学会信任错误消息,并学会阅读它们并从中获取信息,作为解决问题的起点。

此外,我要说的是,“index”的使用令人困惑——在循环中,它似乎在“i”后面保留了一个计数,除了我认为是长度 + 1 和长度 - 1 的拼写错误之外.如果你使用 i 来遍历数组元素,那么我不能用来与某些东西进行比较来查看你在哪里,下一步要做什么等等,而不是使用另一个 int 吗?

最后,我要提醒您,将数组的最后一个元素设置为 null 不会缩短数组。如果您有一个包含 5 个对象的数组,并且将最后一个对象设置为 null,那么您将得到一个第 5 个元素为 null 的数组,而不是一个包含 4 个对象的数组。我不知道您是否期望数组的长度发生变化,但看来您确实在这里给出了代码。

关于java - 如何让线程按顺序打印java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20447589/

相关文章:

java - 使用不同 Base64 库时数据不匹配

java - Spring Mongodb - 无法为 java.time.Period 编写自定义转换器

java - Inc/dec mongotemplate,原子地

multithreading - 在这种情况下如何设计线程同步

c++ - 可以多次链接信号和插槽吗?

java - ConcurrentHashMap:将集合存储为值时需要同步

java - 在我的 tabhost 中强制关闭

java - Tomcat 返回 404 状态

c++ - 与 C++ unordered_map 的并行性

java - 为什么一个线程阻塞了我的 JavaFX UI 线程?