在while循环上防止IndexOutOfBoundsException [Java]

时间:2015-11-08 19:58:46

标签: java arrays loops arraylist

我正在制作一个纸牌游戏,它运行良好,除非我无法进入卡座的底部而不会在某些时候遇到IndexOutOfBoundsException错误。我有一个1到52之间的数字随机数组,我用它来选择从我所拥有的数组列表中调用的索引。由于套牌是一个ArrayList,我可以轻松地在每个循环后删除每张卡。但是我无法从随机数字数组中删除该数字,因此随着卡列表变小,调用索引的可能性就越大。无法找到解决方法。我已经尝试使用if语句将随机数的值更改为小于arrayList的最大长度但仍然得到错误。

public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println("Welcome to War! Press enter to begin."); //User prompt
    Scanner scanner = new Scanner(System.in); //Scanner init
    String[] suit = {" of Diamonds", " of Spades", " of Hearts", " of Clubs"};//Array for suits
    String[] faces = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};//Array for faces
    String[] deck = new String[52]; //Deck size setup
    boolean deckComplete = false;//Boolean for deck being finished
    int[] random = new int[52];//Array for all numbers between 0 and the number of cards in the deck multiplied by number of decks
    ArrayList<Integer> random1 = new ArrayList<Integer>();
    int playerOneTotal = 0;
    int playerTwoTotal = 0;



    for (int x = 0; x<random.length; x++) {
        random[x] = x;
    }//Content setup for random array

    Random rndNum = new Random();//Random init

    int i = 0;

        for (i = 0; i < deck.length; i++) {

            deck[i] = faces[i % 13] + suit[i % 4];
        }//Deck of cards setup



    ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(deck));//Changing Array with card contents into an ArrayList

    while (deckComplete == false) {         //While loop for dealing cards


        for (int j = deck.length; j >= 1; j--) {


           // System.out.println("Hit enter to be dealt a card!");    
            String readString = scanner.nextLine(); //Set variable "readString" to user input
            int randomNumber = rndNum.nextInt(j);
            int randomNumberTwo = rndNum.nextInt(j);


            if (readString.equals("")) {        //If user input equals "enter"...

                 if (randomNumber >= arrayList.size()) {
                    randomNumber = arrayList.size() - 1;
                }

                if (randomNumberTwo == arrayList.size()) {
                    randomNumberTwo = arrayList.size() - 1;
                }


                  int playerOne = random[randomNumber];
                  int playerTwo = random[randomNumberTwo];
                  int playerOneScore = 0;
                  int playerTwoScore = 0;


                  System.out.println("Player One Draws a: " + arrayList.get(random[randomNumber])); //Print out card
                  arrayList.remove(random[randomNumber]); //Remove card from deck
                  System.out.println("Player Two Draws a: " + arrayList.get(random[randomNumberTwo])); //Print out card
                  arrayList.remove(random[randomNumberTwo]); //Remove card from deck


                  playerOneTotal = playerOneTotal + playerOneScore;
                  playerTwoTotal = playerTwoTotal + playerTwoScore;

                  if (playerOneTotal > playerTwoTotal) {
                      System.out.println("Player One Wins this round! Current Score - Player One: " + playerOneTotal + " Player Two: " + playerTwoTotal);
                  }else if (playerOneTotal < playerTwoTotal) {
                      System.out.println("Player Two Wins this round! Current Score - Player One: " + playerOneTotal + " Player Two: " + playerTwoTotal);
                  }else if (playerOneTotal == playerTwoTotal) {

                  }


                   if (j == 1) {    //If program gets to last card...
                       deckComplete = true; //Set desk complete to true

                       System.out.println(arrayList.get(random[randomNumber])); //Print last card
                       arrayList.remove(random[randomNumber]); //Remove last card
                       System.out.println("You are out of cards!"); //Print "You are out of cards"
                       break; //Stop loop
                   }  
               }



       }

除了尝试(下面)之外还有什么方法可以让我得到正确的结果吗?

if (randomNumber >= arrayList.size()) {
                    randomNumber = arrayList.size() - 1;
                }

                if (randomNumberTwo == arrayList.size()) {
                    randomNumberTwo = arrayList.size() - 1;
                }

编辑:这是确切的错误消息。

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 33, Size: 23 at java.util.ArrayList.rangeCheck(ArrayList.java:635) at java.util.ArrayList.get(ArrayList.java:411) at Game.main(Game.java:72)

2 个答案:

答案 0 :(得分:1)

如果我读得正确,您每回合就会从ArrayList选择一张随机卡片。你可以通过在游戏开始时整个ArrayList来改变你的生活(类似于你在现实生活中如何改变牌组)。然后,您只需删除列表的第一个(或最后一个)元素,而不必担心IndexOutOfBoundsException

要对整个套牌进行随机播放,请使用Collections.shuffle

Collections.shuffle(fileList, new Random());

从牌组中取出顶牌:

arrayList.remove(0);

答案 1 :(得分:1)

你有deck这是52张牌的完整列表,按顺序排列。

您创建arrayList副本,就像您一样,除非您重命名stack(或cardStack),然后:

  • 使用Collections.shuffle()
  • 随机播放stack
  • 使用stack(或remove(stack.size()-1)remove(0)取卡,但速度较慢。

更好的是,使用ArrayDeque而不是ArrayList,因为它可以用作LIFO(后进先出)堆栈。在您的情况下,您可以使用stack.pop()来获取卡片。

<强>跟进

为了让游戏发挥作用,一张牌必须不仅仅是文字“Ace of Spade”。你需要知道它是一个Ace,它是一个Spade,所以你需要一个类,例如名为Card,包含两个字段:suitface。然后该类的toString()方法将返回“Ace of Spade”。

另请注意,除非您想作弊,否则永远不会使用索引访问cardStack。在堆栈被洗牌后允许的唯一操作是pop(),以将卡片放在堆栈的顶部。

你的整体循环看起来像这样:

// Build deck
...

// Create shuffled stack
Deque<Card> cardStack = new ArrayDeque<>(Arrays.asList(deck));
Collections.shuffle(cardStack, rndNum);

// Play game
while (! cardStack.isEmpty()) {
    Card player1card = cardStack.pop();
    Card player2card = cardStack.pop();

    // do you stuff here
}