2

I've been trying to make this method for the deck to deal, but once it deals 52 cards it goes onto an infinite loop.

I am aware this is because I have it to generate a random number until it gets a card that has not been set, but once all cards are set, the condition will never be true, therefore infinite loop.

Even though I know my problem, I don't know how to fix it. I've been trying for hours. I want to throw an exemption once it reaches 52 cards, but it never reaches that if statement once it goes into infinite loop.

public PlayingCard deal() {

    Random swift = new Random();
    int index = swift.nextInt(DECK_SIZE);
    cardsInDeck = DECK_SIZE;
    int i = 51;

    while (this.deck[index] == false||i==cardsInDeck) {index = swift.nextInt(DECK_SIZE);}
    if(i==cardsInDeck) { throw new RuntimeException("Empty Deck");}

    PlayingCard.CardRank[] Ranking = PlayingCard.CardRank.values();
    PlayingCard.CardSuit[] Suiting = PlayingCard.CardSuit.values();

    PlayingCard.CardRank Rank = Ranking[index % 13];
    PlayingCard.CardSuit Suit = Suiting[index % 4];

    PlayingCard selected = new PlayingCard(Suit, Rank);
    this.deck[index] = false;
    i++;
    cardsInDeck--;

    return selected;

}

=============================================================================

the whole code

import java.util.Random;

public class DeckOfCards {

public static final int DECK_SIZE = 52;
//Instance Variables
private boolean[] deck; //An implicit set of 52 Playing-Cards
private int cardsInDeck;//Number of cards currently in the deck
private Random dealer;  //Used to rendomly select a card to be dealt

//Constructor
public DeckOfCards() {
    this.deck = new boolean[DECK_SIZE];
    int index = 0;
    for (PlayingCard.CardSuit Suit : PlayingCard.CardSuit.values()) {
        for (PlayingCard.CardRank Rank : PlayingCard.CardRank.values()) {
            PlayingCard card = new PlayingCard(Suit, Rank);
            deck[index] = true;
            index++;
        }
    }
}

//Collect all 52 Playing-Cards into the deck
public void shuffle() {
    /*Random shuffle = new Random();
    for (int j = 0; j < this.deck.length; j++) {
    int k = shuffle.nextInt(this.deck.length);
    boolean temp = this.deck[j];
    this.deck[j] = this.deck[k];
    this.deck[k] = temp;*/
    int index = 0;
    for (PlayingCard.CardSuit Suit : PlayingCard.CardSuit.values()) {
        for (PlayingCard.CardRank Rank : PlayingCard.CardRank.values()) {
            PlayingCard card = new PlayingCard(Suit, Rank);
            deck[index] = true;
            index++;
        }

    }
}

//Simulate dealing a randomly selected card from the deck
//Dealing from an empty deck results in a RuntimeException
public PlayingCard deal() {

    Random swift = new Random();
    int index = swift.nextInt(DECK_SIZE);
    cardsInDeck = DECK_SIZE;
    int i = 0;

    while (this.deck[index] == false&&i>0) {index = swift.nextInt(DECK_SIZE);}
    if(i>cardsInDeck) { throw new RuntimeException("Empty Deck");}

    PlayingCard.CardRank[] Ranking = PlayingCard.CardRank.values();
    PlayingCard.CardSuit[] Suiting = PlayingCard.CardSuit.values();

    PlayingCard.CardRank Rank = Ranking[index % 13];
    PlayingCard.CardSuit Suit = Suiting[index % 4];

    PlayingCard selected = new PlayingCard(Suit, Rank);
    this.deck[index] = false;
    i++;
    cardsInDeck--;

    return selected;

}

==================================================================

public static void main(String[] args) {
    DeckOfCards myDeck = new DeckOfCards();
    myDeck.shuffle();

    for (int p = 1; p <= 4; p++) {
        for (int c = 1; c <= 13; c++) {
            System.out.print(myDeck.deal() + "  ");
        }
        System.out.println();
    }

    try {
        System.out.println(myDeck.deal());
    } catch (RuntimeException rte) {
        System.out.println(rte.getMessage());
    }
}

}

xlecoustillier
  • 16,183
  • 14
  • 60
  • 85
user1404664
  • 73
  • 1
  • 2
  • 8

3 Answers3

4

I've been trying to make this method for the deck to deal, but once it deals 52 cards it goes onto an infinite loop.

The easy way to deal a deck of cards is to:

  1. Place all cards in an ArrayList.
  2. Call Collections.shuffle() on that list;
  3. Deal out the cards in the order in which they appear in the shuffled list.

The code will be a lot simpler than what you have right now, and will be much easier to debug.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

have you tried something like this in the while

    while ((this.deck[index] == false||i==cardsInDeck)&&i<52)

?

JCarlos
  • 51
  • 1
  • 8
  • That still gives me infinite loop. Would you like me to post the rest of the code? maybe the problem lies somewhere else? – user1404664 May 19 '12 at 05:15
1

Once you start picking random indexes, it is too late. You need to test whether the deck has any cards first.

if (cardsInDeck <= 0) ...throw an exception?...
while (this.deck[index] == false) {index = swift.nextInt(DECK_SIZE);}

You need to initialize cardsInDeck correctly (set to DECK_SIZE not in deal but in shuffle and the constructor). You want the invariant that cardsInDeck is equal to the number of indexes for which deck[index]==true.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54