Why do I get an “ArrayIndexOutOfBounds” error in this program?

I wrote this program to initialize and create a deck of cards, to shuffle it, and then to deal out N hands of cards. In spite of the fact that compilation proceeds without a hitch each time, when I run the program it throws me a different ArrayIndexOutOfBounds (:52 or :54). I've checked for bugs by using System.out.println(1), changed and swapped indices, changed the length of arrays and so on. But I'm stumped... Maybe you can help me?

public class Deal 
{

public static void main(String[] args) 
{ 

    int N = Integer.parseInt(args[0]);
    int hand = 5;

    String[] rank = 
    {
        "2", "3", "4", "5", "6", "7", "8", "9", "10", 
        "Jack", "Queen", "King", "Ace"
    };

    String[] suit = {"Spades", "Hearts", "Clubs", "Diamonds"};

    // Create Deck
    String[] deck = new String[rank.length * suit.length];

    // Fill the deck with cards
    for (int i = 0; i < suit.length; i++)
    {
        for (int j = 0; j < rank.length; j++)
        {
            //System.out.println(1);
            deck[rank.length*i + j] = rank[j] + " of " + suit[i];
            System.out.println(deck[rank.length*i +j]);
        }
    }

    // Shuffle deck
    for (int i = 0; i < deck.length; i++)
    {
        int r = i + (int)(Math.random() * (N-1));
        String t = deck[i];
        deck[i] = deck[r];
        deck[r] = t;
    }

    // Count number of cards dealt
    int counter = 0;

    while (N != 0 && counter <= deck.length)
    {
        for (int i = counter; i < hand + counter; i++)
        {
            System.out.println(deck[i]);
            counter++;
        }

        N--;
        System.out.println();
    }
}
}
Jon Skeet
people
quotationmark

The problem is in your shuffling code:

for (int i = 0; i < deck.length; i++)
{
    int r = i + (int)(Math.random() * (N-1));
    String t = deck[i];
    deck[i] = deck[r];
    deck[r] = t;
}

There's no guarantee that r will be in range - as soon as i gets within N of the end, it can fail depending on the random number generated.

Better: use Collections.shuffle:

Collections.shuffle(Arrays.asList(deck));

When you've fixed that, you'll then have an issue here:

while (N != 0 && counter <= deck.length)
{
    for (int i = counter; i < hand + counter; i++)
    {
        System.out.println(deck[i]);

What do you expect to happen when counter == deck.length?

Basically, the answer to all questions like this involves the following steps:

  • Work out where the code is failing
  • Work out how/why you're getting an invalid index
  • Work out what you actually wanted to do, in order to stay within the bounds of the array
  • Implement that change

people

See more on this question at Stackoverflow