Keith
Keith

Reputation: 133

java accessing an objects data from within another object

Ive recently started learning java and for the most part its going well. To help understand what I am learning Ive decided to write a card game engine. Ive build the card and deck class using what i believe is proper abstraction and encapsulation methods. However while building the dealer class I've run into an issue, I don't know how to access the card classes data from within the dealer class. From the deck class I have all the access I need to the card class but once I get to the dealer class I'm just not sure how to access the data that is encapsulated 2 classes deep.

Here is what I have so far , while code to solve the problem is appreciated , if someone could point me in the direction of a document or book to help better understand what I am experiencing would be greatly appreciated.

Just to be clear. I'd like to be able to access the data pertaining to the individual cards in the deck array such as the instance variable values from the dealer class. I know that if I reference the a card from a println statement it invokes the cards to string method. But what im looking for is the cards actual data.

The last class is just something I was using to test the methods I wrote.

   import java.util.*;
   public class Card {

        public Card() {
            suit = 0;
            value = 0;
            setName(value);                             
        }

        public Card(int cSuit, int cValue) {
            suit = cSuit;
            value = cValue;
            setName(cValue);
        }

        public String getNewCard() {
                suit = rgen.nextInt(4)+1;
            value = rgen.nextInt(13)+1;
            setName(value);

            return name +" of " +getSuitAsString();             
        }

        public int getValue() {
            return value;
        }

        public int getSuit() {
            return suit;
        }

        public String getName() {
            setName(value);
            return name;
        }

        public String getName(int val) {
            setName(val);
            return name;
        }

        public String getSuitAsString() {

            switch(suit) {
            case 1: return "Diamonds";
            case 2: return "Hearts";
            case 3: return "Spades";
                        case 4: return "Clubs";
                      default: return null;
            }
        }

        public String getSuitAsString(int cSuit) {
            switch (cSuit) {
                case 1: return "Diamonds";
            case 2: return "Hearts";
            case 3: return "Spades";
                    case 4: return "Clubs";
                default:return null;
            }
        }

        public String toString() {
            return name +" of "+ getSuitAsString();
        }

        private void setName(int value) {
            switch (value) {
            case 0 : name = "null";
            break;
            case 1 : name =  "Ace";
            break;
            case 2 : name =  "Two";
            break;
            case 3 : name =  "Three";
            break;
            case 4 : name =  "Four";
            break;
            case 5 : name =  "Five";
            break;
            case 6 : name =  "Six";
            break;
            case 7 : name =  "Seven";
            break;
            case 8 : name =  "Eight";
            break;
            case 9 : name =  "Nine";
            break;
            case 10 : name = "Ten";
            break;
            case 11: name =  "Jack";
            break;
            case 12 : name = "Queen";
            break;
            case 13 : name = "King";
            break;
            }


        }

    private int suit;
    private String name;
    private int value;


    private Random rgen = new Random();
    }
    import java.util.Random;


    public class Deck {

    //Constructor assembles an initial deck of 52 cards in order by suit.
    //Array element [0] is never used.
        public Deck(){
            int cards = 1;
            int cardsPerSuit = 13;
            int suits = 4;
            while(cards < DECK_ARRAY_SIZE){
                for(int i = 1; i <= suits ; i++){
                    for(int j = 1; j <= cardsPerSuit; j++){
                    deck[cards++] = new Card(i , j);


                }
            }
        }   
    }

    //  Constructor creates and empty deck of 53 indexes set to null.
    //  Array element [0] is never used.
        public Deck(int deckArraySize){
            for(int i = 1; i < deckArraySize ; i++){
                deck[i] = new Card();
                }
        }

        public Deck(int suitCount , int cardsPerSuit , int deckArraySize){
    //  Constructor for special deck configuration.     
    }



        public void shuffle(){
            int SHUFFLE_COUNT = 100000;
            int arrayPos1 = 0;
            int arrayPos2 = 0;
            int count = 0;

            while(count < SHUFFLE_COUNT){
                Card card1 = deck[rgen.nextInt(DECK_ARRAY_SIZE)];
                if(card1 == deck[0]) card1 = deck[1];//This prevents the NullPointerException error.broke the always use braces rule.
                Card card2 = deck[rgen.nextInt(DECK_ARRAY_SIZE)];
                if(card2 == deck[0]) card2 = deck[52];//This prevents the NullPointerException error.broke the always use braces rule.



                for(int i = 1; i < DECK_ARRAY_SIZE; i++){
                    for (int j = 1; j < DECK_ARRAY_SIZE; j++){
                        if (deck[i].equals(card1)){
                            arrayPos1 = i;
                            if (deck[j].equals(card2)){
                            arrayPos2 = j;

                            }
                        }
                    }   
                    Card temp = deck[arrayPos1];
                    deck[arrayPos1] = deck[arrayPos2];
                    deck[arrayPos2] = temp;
                    count++;    

                }       

        }           

    }


    //  Gets the top card of the deck.
        public Card getTopCard(){
            Card topCard = deck[1];
            return topCard;

        }
    //  Gets a card at specified index. 
        public Card getCardAt(int cardAtPos){
            Card cardAt = deck[cardAtPos];  
            return  cardAt; 

        }


    //This method makes an implicit call to the Card classes toString method when string manipulation is performed .    
    //This is done by the compiler automatically.
        public void getDeckInfo(){
            for(int i = 1; i < DECK_ARRAY_SIZE ; i++){
            System.out.print(i +" ");
            System.out.println(deck[i]);
            }
        }


        public String toString(){
    //      getDeckInfo();
            return "Nothing to see here, move along.";

        }

    private Random rgen = new Random();
    public static final int DECK_ARRAY_SIZE = 53;
    private Card[] deck = new Card[DECK_ARRAY_SIZE];

    }
    public class Dealer {

    public Dealer(){
        playDeck = new Deck();
        discardStack = new Deck(Deck.DECK_ARRAY_SIZE);
    }

    public int getDeckCardCount(){
// this count should go down anytime a card is dealt to a player 
        return deckCardCount;
    }

    public int getDiscardCount(){
// this count should go up anytime a card is removed from the deck or from play.        
        return discardCount;
    }

    public void dealCards(){

// should be self explanatory.      
    }

    public void shuffle(){
// need to make sure that shuffle compensates for cards removed 
// from deck and move cards to the front of the array before the shuffle.
// make sure that the empty indexes at the end of the array are not included in the shuffle.
// also need a shuffle method for shuffles at the end of the game. or just 
// throw out he deck and get a new deck.... 
// maybe pass the remaining cards in the deck to the shuffle method .

    }

    public String toString(){

        return "Nothing to see here , move along.";
}
public Deck playDeck;   
public Deck discardStack;
private int deckCardCount;
private int discardCount;
    }

public class CardTest  {

public static void main(String[] args){


    Card singleCard = new Card();
    Deck deck = new Deck();
    Deck playDeck = new Deck();
    Deck discardStack = new Deck(53); 
    Dealer dealer = new Dealer();

System.out.println("value: "+singleCard.getValue());
System.out.println("Name: "+singleCard.getName());
System.out.println("Suit: "+singleCard.getSuitAsString());
System.out.println("Card to string: "+singleCard.toString());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("Pass a 4 to the getSuitAsString() method:    "+singleCard.getSuitAsString(4));
System.out.println("Pass a 12 to the getName() method: "+singleCard.getName(12));
deck.getDeckInfo();
System.out.println("Top card is: "+deck.getTopCard());

System.out.println("Shuffling...");
int count =0;
while(count < 500){
dealer.playDeck.shuffle();
discardStack.shuffle();
count++;
}

deck.getDeckInfo();
System.out.println("Top card is: "+deck.getTopCard());
System.out.println("Card at position ??: "+deck.getCardAt(5));
playDeck.getDeckInfo();
discardStack.getDeckInfo();
playDeck.shuffle();
playDeck.getDeckInfo();
discardStack.shuffle();
discardStack.getDeckInfo();
dealer.playDeck.getDeckInfo();
dealer.playDeck.shuffle();
System.out.println("Shuffling...");
dealer.playDeck.getDeckInfo();
System.out.println(dealer.playDeck.getCardAt(5));
System.out.println(dealer.discardStack.getCardAt(5));   


}

}

Upvotes: 1

Views: 5014

Answers (3)

fgysin
fgysin

Reputation: 11923

Some general remarks:

  • At some point you'll have to start learning about/dealing with arrays that start at index 0. Might as well do it sooner than later, as what you are doing ("//Array element [0] is never used." will likely just lead to off-by-one errors later on...

  • Only define constructors that you really need. An empty constructor is only useful if there is a proper use case for it. Generally after construction your object instance should be in a valid state - which is not the case if you call the default newu Card()

  • There are many possible ways of dealing with string constants. The way you're doing it is the easiest one, but also the most error-prone. For example if you do a typo in the "Diamonds" string somewhere, that can take age to find. For now, I'd suggest using constants, i.e. some public static final DIAMOND = "Diamond" definition. Like that, whenever you need your diamond string you just use the variable DIAMOND - which you'll know contains the right thing and can not be modified. (Later on, you can also start reading about Enum types.)

To your question:

I think there is some misunderstanding going on...

"I know that if I reference the a card from a println statement it invokes the cards to string method. But what im looking for is the cards actual data."

This is not true. What happen is: if you're card variable is in a place where Java expects only a string - e.g. when concatenating two strings using the + operator - then it accesses the toString() method.

Card card = // some card variable

// This will use card.toString()
system.out.println("Printing a card string " + dealer.playDeck.getCardAt(5));

// However, you can just print something like this:
system.out.println("Printing a card suit " + dealer.playDeck.getCardAt(5).getSuitAsString());

Addendum:
Concerning your question in comments on other answer.

for(int i = 0; i < deck.getCards().length; i++){
    deck.getCards()[i] // this is the i-th card, do something with it
}

Upvotes: 0

Daniel Kaplan
Daniel Kaplan

Reputation: 67360

I have a feeling I'm not understanding something, but isn't it as simple as putting this method inside your Deck class:

public Card[] getCards() {
    return deck;
}

Now your Dealer can call aDeck.getCards() and do whatever it wants with it.

For example, I put this code in the Dealer class and it compiles fine:

public Dealer() {
    Deck deck = new Deck();
    for (Card card : deck.getCards()) {
        int suit = card.getSuit();
        int value = card.getValue();
    }
}

Upvotes: 0

ilan berci
ilan berci

Reputation: 3881

The model isn't bad, the problem lies with your 2nd and 3rd constructor for Deck.. the first constructor ensures a legal deck while the other 2 create a deck that you scratch your head at in your sample code below.

Ask yourself why you would ever need a 'special construction' and if you do.. why can't you start with a proper 52 card deck created by your first Deck constructor and work from there.. ie.. remove the cards you don't need.

Lastly, OO philosophy dictates that your instance should never be in an invalid state after it's construction. Having a constructor Card() is simply not good enough as you need to know what card you want to end up with.. 6 of hearts Card.new(6, "hearts") is a valid ctor

Upvotes: 1

Related Questions