Search code examples
javaenumsinstanceencapsulation

Not displaying cards


I am creating an instance deck of cards that should display all 52 cards when built, then it should shuffle the cards and deal 5. After this the menu should prompt for either another 5 to be dealt, or the deck to be reshuffled, which adds all the drawn cards back in, or to exit the application. However, when I run the app, it just displays null for all 52 cards, and each card that is dealt. The application worked and almost met all the specification before I talked with my instructor, and what I have now is where I got during/ after our talk. I'm not sure what I'm doing wrong and could really use the help. Just for clarification I will post the requirements, then the code. I appreciate the help.

At startup, it constructs a Deck of Cards
52 distinct cards running from Ace - King, of suit Heart, Club, Diamond, or Spade
Shuffle the cards!!
For proof, print out all 52 cards to the console in a useful, readable way.
Then, deal the top five cards to the console (meaning print them to the console)
After all of this, allow the user choose between dealing the next five cards, reshuffling the deck, or quitting the application. 
If the user chooses to deal the next 5 cards, do so based on which cards have not yet been dealt. DO NOT RESHUFFLE.
If the user chooses to reshuffle, simply repeat the process of shuffling, printing the deck, and dealing the top five cards.
If the user chooses to quit the application, simply end the app.

The code I'm practicing encapsulation so I will post each class broken up as is in eclipse.

Driver

public class Driver {

    public static void main(String[] args) throws IOException {

        DeckRun.run();

        }

    }

DeckRun

    public class DeckRun {

    static Card[] d1 = new Card[52];

    public static void run() throws IOException {

        printDeck();
        System.out.println("");
        Deal.dealCards(d1);
        System.out.println("");
        menu();

    }

    public static void printDeck() {

    for (Card c : d1) {
        System.out.println(c);
    }

    }

    public static void menu() throws IOException{

        BufferedReader readRacer = new BufferedReader(new InputStreamReader(System.in));

        int menu = 0;

        do {

        System.out.println("Press 1 to be dealt 5 random cards.");
        System.out.println("Press 2 to shuffle all the cards back into the deck.");
        System.out.println("Press 3 to quit the application.");

        String input = readRacer.readLine();
        menu = Integer.parseInt(input);

        switch (menu) {

        case 1: Deal.dealCards(d1);
            break;
        case 2: System.out.println("The deck has been shuffled.");
                Deck[] d1 = new Deck[52];
            break;
        case 3: System.out.println("I'm not bad, I'm just drawn that way.");
            break;
        }
        } while (menu != 3);
    }

}

Card

public class Card {

    private Rank rank; // Variable to assign a card its rank.
    private Suit suit; // Variable to assign a card its suit.

    public Card (Rank rank, Suit suit) { // Constructor to build a card.
        this.rank = rank;
        this.suit = suit;
    }

    public Rank getRank() { // Retrieves the card's rank from the enum Rank.
        return rank;
    }

    public Suit getSuit() { // Retrieves the card's suit from the enum Suit.
        return suit;
    }

    @Override
    public String toString() { //
        return rank + " OF " + suit;
    }

}

Deck

public class Deck {

    private Card[] cards;

    public Deck() {

        int numberOfRanks = 13;
        int numberOfSuits = 4;
        int numberOfCards = numberOfRanks * numberOfSuits;

        Rank[] rank = Rank.values();
        Suit[] suit = Suit.values();

        cards = new Card[numberOfCards];

        for (int i = 0; i < numberOfRanks; i++) {
            for (int j = 0; j < numberOfSuits; j++) {

                cards[j * numberOfRanks + i] = new Card(rank[i], suit[j]);
            }
        }
    }

    public void shuffleCards() {

        Random rand = new Random();

        for (int c = rand.nextInt(6) + 5; c > 0; c--) {
            for (int i = cards.length - 1; i > 0; i--) {

                int index = rand.nextInt(i + 1);
                Card card = cards[index];
                cards[index] = cards[i];
                cards[i] = card;
            }
        }
    }
}

Deal

public class Deal {

    private static int counter = 0;

    public static void dealCards(Card[] d1) {

        for (int i = 0; i < 5; i++) {
            counter++;
            System.out.println(d1[counter]);
            if (counter == 50) {
                System.out.println("Almost all cards have been used, please reshuffle.");
            }
        }
    }
}

Rank (Enum)

public enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING, }

Suit (Enum)

public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES, }

Not really sure where the issue is, but what I've changed today is after realizing I need an instance of the deck, my professor helped me understand that instead of a method for the deck of cards in class Deck, i needed a constructor. I believe I'm going down the right path but I am just utterly stumped. Any help is appreciated and if you can explain my errors so I may learn and progress even more thanks.


Solution

  • Okay guys. The answer was simple. I deleted the deal class, and moved the method to the deck class. I initialized the counter as a private, class-level int, which fixed the repetition issue. I will post the finished code below, so you can see.

    DeckRun Class

    public class DeckRun {
    
        static Deck d1 = new Deck();
    
        public static void run() throws IOException {
    
            printDeck();
            System.out.println("");
            d1.dealCards();
            System.out.println("");
            menu();
    
        }
    
        public static void printDeck() {
    
            System.out.println(d1.toString());
        }
    
    
        public static void menu() throws IOException{
    
            BufferedReader readRacer = new BufferedReader(new InputStreamReader(System.in));
    
            int menu = 0;
    
            do {
    
            System.out.println("Press 1 to be dealt 5 random cards.");
            System.out.println("Press 2 to shuffle all the cards back into the deck.");
            System.out.println("Press 3 to quit the application.");
    
            String input = readRacer.readLine();
            menu = Integer.parseInt(input);
    
            switch (menu) {
    
            case 1: d1.dealCards();
            System.out.println("");
                break;
            case 2: System.out.println("The deck has been shuffled.");
                        d1.shuffleCards();
                        System.out.println("");
                break;
            case 3: System.out.println("I'm not bad, I'm just drawn that way.");
                break;
            }
            } while (menu != 3);
        }
    
    }
    

    Deck Class

    public class Deck {
    
        private Card[] cards;
    
        public Deck() {
    
            int numberOfRanks = 13;
            int numberOfSuits = 4;
            int numberOfCards = numberOfRanks * numberOfSuits;
    
            Rank[] rank = Rank.values();
            Suit[] suit = Suit.values();
    
            cards = new Card[numberOfCards];
    
            for (int i = 0; i < numberOfRanks; i++) {
                for (int j = 0; j < numberOfSuits; j++) {
    
                    cards[i * numberOfSuits + j] = new Card(rank[i], suit[j]);
                }
            }
        }
    
        public void shuffleCards() {
    
            Random rand = new Random();
            counter = 0;
    
            for (int c = rand.nextInt(6) + 5; c > 0; c--) {
                for (int i = cards.length - 1; i > 0; i--) {
    
                    int index = rand.nextInt(i + 1);
                    Card card = cards[index];
                    cards[index] = cards[i];
                    cards[i] = card;
                }
            }
        }
    
        private int counter = 0;
    
        public void dealCards() {
    
            try{
            for (int i = 0; i < 5; i++) {
                counter++;
                System.out.println(cards[counter]);
                if (counter == 50) {
                    System.out.println("Almost all cards have been used, please reshuffle.");
                    // Either return 1 card or an array of 5 cards.
                }
            } 
            } catch (ArrayIndexOutOfBoundsException aioobe){
                System.out.println("Caught an ArrayIndexOutOfBoundsException. Reshuffling deck.");
                shuffleCards();
            }
        }
    
        @Override
        public String toString() {
    
            String deckOfCards = "";
    
            for (Card c : cards) {
    
                deckOfCards += c.toString() + "\n";
    
            }
    
            return deckOfCards;
    
        }
    }
    

    That is all I had to fix, but I appreciate the help. Thanks everyone.