This discussion is archived
7 Replies Latest reply: Jul 12, 2010 6:03 AM by 800387 RSS

Need some OO design pointers for a Java card game I wrote for uni

843853 Newbie
Currently Being Moderated
Hi,

I hope a few of you Java sifus can help me understand I dilemma I keep finding myself in.
I created a card game for a university assignment which works great but its not very OO at the moment.
I only have 3 classes; a Card class, a Deck class and a Game class which contains all my GUI, AI, Game Controller, Player and Hand code.

The assignment is over but I feel like enhancing the game, adding animation, multiplayer, several AI agents etc.

The first thing I have attempted is animation and I've hit a brick wall. I am trying to create animation for my card game whereby I have an animation showing the cards being shuffled and then an animation which shows the cards being dealt to the players. The game then commences. The cards on the GUI then need to be clickable (MouseListeners?) to play the game. If you're running Windows 7, load up 'Hearts' and you'll know what I'm trying to achieve.

I don't understand how the GUI, and Card class need to be seperated so that its good OO.
If I give you a few snippets of code, it might explain the situation:
A snippet of my card class is as follows:
import javax.swing.*;

public class Card extends JLabel //Each card is a JLabel
{
     private int value;                    //variable for the value of the card
     private int suit;                         //variable for the suit of the card 
     private ImageIcon frontOfCard;     //Displays the image of the front of the cards
     private ImageIcon backOfCard;          //displays the image of the back of the cards
     
     public Card (int Value, int Suit, ImageIcon front, ImageIcon back)
     {
          value = Value;               
          suit = Suit;               
          frontOfCard = front;     
          backOfCard = back;
          setIcon(backOfCard);     //To make it non-visible when dealt
     }
As you can see, each card is a JPanel. I've been told by some I shouldn't extend JPanel but rather that I should have a BufferedImage/Image instance variable for each card as the image of the card. The thing is that I need each card displayed on the GUI which can then be clickable. When it is clicked, it is moved from the players hand, into the players move. - There needs to be an animation showing this.
I've got the animation code figured out in terms of how to move 'images' around a screen to make a pleasing animation. The problem is there are no clickable listeners for images, so the Images needs to be inside some container; a widget which can fire events - Hence the reason I have chosen to extend JPanel for my Cards.

and a Deck class, snippet is as follows:
public class Deck extends JLabel //The deck will be shown on the GUI as a JLabel
{
     private ArrayList<Card> standardDeck;
     
     public Deck()
     {
          standardDeck = new ArrayList<Card>();
          ImageIcon cardBack = new ImageIcon("CardBack.png");
          setPreferredSize(new Dimension(90, 135));
          setIcon(cardBack);
          int cardCount = 0;     //This variable counts the cards. Is used to assist in the name generation of the imageicon filename
          String str; //the imageIcon constructor accepts filenames as strings so this string holds the filename of the corresponding card image file.
          for (int a=0; a<4; a++) //putting the cards into the deck with the specifed parameters
          {
               for (int b=2; b<15; b++)
               {
                    cardCount+=1;     //incrementing the card count (the card files are named 1-52 as integers)
                    str = Integer.toString(cardCount); //Integer is converted to string type before being added to string str variable
                    str += ".png"; //To complete the image filename, ".png" has to be concatenated to the string.
                    standardDeck.add(new Card(b, a, new ImageIcon(str), cardBack)); //creating and then adding the cards
               }
          }
     }
This is how I envisage a new class diagram for my game:

Card class
Game Class <--- Holds a Deck instance, Players instances, and the GUI instance
Player Class <-- Will contains hand 'instances' , but I will not create a seperate 'Hand' Class, I will use an ArrayList.
AI Class extends Player Class
GUI Class
Deck Class <-- contains 52 cards

My question is, how do I show the Cards on the GUI if my Cards are in a Deck and the Deck is held in the Game class?
Please note that there are 52 cards, so potentially 52 images on the GUI, each of which needs to be clickable. When clicked, the cards are moved about, e.g. from the deck to a players hand, from a players hand back to the deck, from a players hand to a players current move hand.
etc

I've read that GUI, program control, and logic should be seperated. If thats the case, what do I have in my GUI class if the Cards (which are JPanels) are held in the Deck class which in turn is held in the Game class?

Any help on this would be greatly appreciated!

I know what I have written may not be fully clear. I find it hard sometimes to fully convey a problem at hand. Please let me know if you don't understand what I've written and I'll do my best to explain further.
  • 1. Re: Need some OO design pointers for a Java card game I wrote for uni
    800387 Newbie
    Currently Being Moderated
    Faz_86 wrote:
    Hi,

    I hope a few of you Java sifus can help me understand I dilemma I keep finding myself in.
    I created a card game for a university assignment which works great but its not very OO at the moment.
    I only have 3 classes; a Card class, a Deck class and a Game class which contains all my GUI, AI, Game Controller, Player and Hand code.

    The assignment is over but I feel like enhancing the game, adding animation, multiplayer, several AI agents etc.
    Admirable, and the best way to learn, doing something that interests you.
    The first thing I have attempted is animation and I've hit a brick wall. I am trying to create animation for my card game whereby I have an animation showing the cards being shuffled and then an animation which shows the cards being dealt to the players. The game then commences. The cards on the GUI then need to be clickable (MouseListeners?) to play the game. If you're running Windows 7, load up 'Hearts' and you'll know what I'm trying to achieve.

    I don't understand how the GUI, and Card class need to be seperated so that its good OO.
    If I give you a few snippets of code, it might explain the situation:
    A snippet of my card class is as follows:
    Do a quick Google on the model view controller pattern. Your listeners are your controllers. Your JPanel, JButton, etc. are your view. The AI, Player, Card and Deck (and presumably something like Score) are your model. Your model should be completely testable and not dependent on either the controller or the view. Imagine you could play the game from the command line. Get that working first. Then you can add all the bells and whistles for the UI.
    import javax.swing.*;
    
    public class Card extends JLabel //Each card is a JLabel
    (redacted)
    
    As you can see, each card is a JPanel. I've been told by some I shouldn't extend JPanel but rather that I should have a BufferedImage/Image instance variable for each card as the image of the card. The thing is that I need each card displayed on the GUI which can then be clickable. When it is clicked, it is moved from the players hand, into the players move. - There needs to be an animation showing this.
    Extending JPanel is fine. As you noted, you need something to add listeners to. However, I would separate things a bit. First, a card really only has a rank and suit (and perhaps an association to either the deck or a player holding the card). The notion of setIcon() is where you are tripping up. The card itself exists in memory. You should be able to test a card without using a UI. Create a separate class (CardPanel or something similar) that has a reference to a Card and the additional methods needed for your UI.
    I've got the animation code figured out in terms of how to move 'images' around a screen to make a pleasing animation. The problem is there are no clickable listeners for images, so the Images needs to be inside some container; a widget which can fire events - Hence the reason I have chosen to extend JPanel for my Cards.

    and a Deck class, snippet is as follows:
    public class Deck extends JLabel //The deck will be shown on the GUI as a JLabel
    {
         private ArrayList<Card> standardDeck;
         
         public Deck()
         {
              standardDeck = new ArrayList<Card>();
              ImageIcon cardBack = new ImageIcon("CardBack.png");
              setPreferredSize(new Dimension(90, 135));
              setIcon(cardBack);
              int cardCount = 0;     //This variable counts the cards. Is used to assist in the name generation of the imageicon filename
              String str; //the imageIcon constructor accepts filenames as strings so this string holds the filename of the corresponding card image file.
              for (int a=0; a<4; a++) //putting the cards into the deck with the specifed parameters
              {
                   for (int b=2; b<15; b++)
                   {
                        cardCount+=1;     //incrementing the card count (the card files are named 1-52 as integers)
                        str = Integer.toString(cardCount); //Integer is converted to string type before being added to string str variable
                        str += ".png"; //To complete the image filename, ".png" has to be concatenated to the string.
                        standardDeck.add(new Card(b, a, new ImageIcon(str), cardBack)); //creating and then adding the cards
                   }
              }
         }
    This is how I envisage a new class diagram for my game:
    I am not an animation buff, so I will assume the above works.
    Card class
    Remove the UI aspects to this class, and I think you are all set here.
    Game Class <--- Holds a Deck instance, Players instances, and the GUI instance
    Presumably this is where main() resides. It will certainly have a reference to model classes (player, game, deck, etc.) and likely the master JFrame (or a controller class you create yourself).
    Player Class <-- Will contains hand 'instances' , but I will not create a seperate 'Hand' Class, I will use an ArrayList.
    Does a player really have multiple hands? It seems to me more of a one-to-one relationship (or a player has a one-to-many relationship to Card).
    AI Class extends Player Class
    Why extend Player? Create a Player interface, then have a HumanPlayer and AIPlayer implementation. Common parts could be refactored out into either a helper class (delegation) or AbstractPlayer (inheritance).
    GUI Class
    My assumption is that this class has a reference to the master JFrame.
    Deck Class <-- contains 52 cards
    Yes. You may end up recycling this class such that a Deck can also function as a Hand for a given player. If there are differences between the two, create an interface and have a Hand and a Deck implementation. Coding to interfaces is a good thing.
    My question is, how do I show the Cards on the GUI if my Cards are in a Deck and the Deck is held in the Game class?
    You need to pass a reference to the appropriate view class. That is how MVC works. The controller receives a request from the view, dispatches to some model functionality you write (such as GameRulesEngine, Deck, etc.) and returns a result to the view (which could be the same view or a different one, imagine someone clicking 'high scores').
    Please note that there are 52 cards, so potentially 52 images on the GUI, each of which needs to be clickable. When clicked, the cards are moved about, e.g. from the deck to a players hand, from a players hand back to the deck, from a players hand to a players current move hand.
    etc
    That is up to you to write the animation code. In principle, you have a mouse listener, and then you take the appropriate rendering steps.
    I've read that GUI, program control, and logic should be seperated. If thats the case, what do I have in my GUI class if the Cards (which are JPanels) are held in the Deck class which in turn is held in the Game class?
    See above.
    Any help on this would be greatly appreciated!
    You are welcome.
    I know what I have written may not be fully clear. I find it hard sometimes to fully convey a problem at hand. Please let me know if you don't understand what I've written and I'll do my best to explain further.
    No, you have been doing fine.

    - Saish
  • 2. poker hands? Need some OO design pointers for a Java card game...
    782681 Newbie
    Currently Being Moderated
    Saish wrote:
    Faz_86 wrote:
    ...Player Class <-- Will contains hand 'instances' , but I will not create a seperate 'Hand' Class, I will use an ArrayList.
    Does a player really have multiple hands? It seems to me more of a one-to-one relationship (or a player has a one-to-many relationship to Card)...
    given the context, it looks related to ["poker hands"|http://www.thepokerforum.com/pokerhands.htm|explanation]
  • 3. Re: poker hands? Need some OO design pointers for a Java card game...
    800387 Newbie
    Currently Being Moderated
    gnat wrote:
    Saish wrote:
    Faz_86 wrote:
    ...Player Class <-- Will contains hand 'instances' , but I will not create a seperate 'Hand' Class, I will use an ArrayList.
    Does a player really have multiple hands? It seems to me more of a one-to-one relationship (or a player has a one-to-many relationship to Card)...
    given the context, it looks related to ["poker hands"|http://www.thepokerforum.com/pokerhands.htm|explanation]
    Poker? I don't even know her?

    (Sorry, could not resist, getting late on a Thursday).

    - Saish
  • 4. Re: Need some OO design pointers for a Java card game I wrote for uni
    843853 Newbie
    Currently Being Moderated
    Thanks a lot Saish. You're response is definitely above and beyond anything I was expecting.
    You've given me a lot of great feedback and have given me some great pointers on where to go next. I haven't really dived into the whole design patterns subject properly so I'll definitely do as much research as I can into the subject.

    Before I do though, I have a few questions/comments on your post:

    1) From what I've understood, View should be completely seperate from Model so my Card class should not extend JPanel and each object does not need to hold an image instance variable representing its image on the UI. It should only contain Card specific data; (Suit & Value). The UI should represent cards external of the Card class? - When these UI Cards are clicked, the UI should fire events (Controllers) to the Model, letting the Model know that something has changed in the View?
    I've had a little think about it and the way I would approach this then is to have 52 JPanels on the UI each one representing a specific card. I guess the main question then is how would I 'link' each of these JPanels to a Card instance?
    I suppose I can create my own Card widget class (extending JPanel) which contains a BufferedImage and a String instance variable. The String instance variable would hold the name of the card. The association between these JPanels and Card instances could be the String name instance variables in both the Card class and the JPanel representing that specific Card. I.e.
    if (Card.name == JPanel.name)
    {
         doSomething();
    }
    Would the above be acceptable? Would it not create too much overhead doing so many comparisons?

    2) You are correct in assuming that main() will sit in the Game class and it'll have references to model class objects.

    3) I just wanted to clarify why each Player has two 'Hands'. One 'Hand' will hold the players available cards (Holding Hand) and the other 'Hand' will hold the players 'move' ('Move Generated Hand'), which will consist of one or more of the cards taken from the 'Holding Hand'
    The best analogy is from Scrabble. 'Holding Hand' = the rack, 'Move Generated Hand' = the word created from available tiles on the rack.

    4) Great idea in having a Player interface. I didn't think of that.

    5) Currently the 'Deck' class has an ArrayList<Card> reference which holds the actual cards. It has methods a few of which are:
         
    public void shuffle() \\The only custom method which I've written.
    public int getDeckSize() \\calls ArrayList.size()
    public Card dealCard() \\calls ArrayList.get()
    public Card specifiedCardInfo(int location) \\calls ArrayList.get()
    public void addCard(Card usedCard) \\calls ArrayList.add()
    ...
    The 'Hand' behaves in exactly the same way as the Deck does in terms of holding, adding, removing cards. The only method it doesn't share is the shuffle() method. A bog standard ArrayList object is therefore perfect to function as a 'Hand'? I don't think an Interface is needed here?

    I would again like to say thanks for your response. As this post proves, its really got me thinking and brainstorming.
  • 5. Re: Need some OO design pointers for a Java card game I wrote for uni
    800387 Newbie
    Currently Being Moderated
    Faz_86 wrote:
    Thanks a lot Saish. You're response is definitely above and beyond anything I was expecting.
    You've given me a lot of great feedback and have given me some great pointers on where to go next. I haven't really dived into the whole design patterns subject properly so I'll definitely do as much research as I can into the subject.

    Before I do though, I have a few questions/comments on your post:

    1) From what I've understood, View should be completely seperate from Model so my Card class should not extend JPanel and each object does not need to hold an image instance variable representing its image on the UI. It should only contain Card specific data; (Suit & Value). The UI should represent cards external of the Card class? - When these UI Cards are clicked, the UI should fire events (Controllers) to the Model, letting the Model know that something has changed in the View?
    Sounds good.
    I've had a little think about it and the way I would approach this then is to have 52 JPanels on the UI each one representing a specific card. I guess the main question then is how would I 'link' each of these JPanels to a Card instance?
    Pass an instance of Card to each CardPanel's constructor (or alternatively, assign it in a mutator/setter method).
    I suppose I can create my own Card widget class (extending JPanel) which contains a BufferedImage and a String instance variable. The String instance variable would hold the name of the card. The association between these JPanels and Card instances could be the String name instance variables in both the Card class and the JPanel representing that specific Card. I.e.
    if (Card.name == JPanel.name)
    {
    doSomething();
    }
    Would the above be acceptable? Would it not create too much overhead doing so many comparisons?
    Since you are storing them in a List, override equals() and hashCode(). (You should do this for any item in a collection). Two cards are not equal if their "name" is equal, they are equal if their rank and suit are equal. Override toString() or provide a getName() method on the Card class itself. The name can be derived from rank and suit. There is no reason to store it in another variable. Your CardPanel would simply call Card#toString() or Card#getName() to retrieve a name to display.

    Once you pass the Card to a CardPanel via its constructor (or a setter), there should not be a need to iterate and associate a relationship between the UI and model objects. Note the pattern here. It is totally acceptable (indeed oftentimes unavoidable) for the UI to have a reference or dependency on the model. However, you do not want Card to be aware of any UI concepts. The model has no dependencies, except on other model objects.
    2) You are correct in assuming that main() will sit in the Game class and it'll have references to model class objects.

    3) I just wanted to clarify why each Player has two 'Hands'. One 'Hand' will hold the players available cards (Holding Hand) and the other 'Hand' will hold the players 'move' ('Move Generated Hand'), which will consist of one or more of the cards taken from the 'Holding Hand'
    The best analogy is from Scrabble. 'Holding Hand' = the rack, 'Move Generated Hand' = the word created from available tiles on the rack.
    So, something akin to a game where the player has both hidden card and then a pile of his or her own that is either face down or face up with cards placed on the table. Ok.
    4) Great idea in having a Player interface. I didn't think of that.

    5) Currently the 'Deck' class has an ArrayList<Card> reference which holds the actual cards. It has methods a few of which are:
         
    public void shuffle() \\The only custom method which I've written.
    public int getDeckSize() \\calls ArrayList.size()
    public Card dealCard() \\calls ArrayList.get()
    public Card specifiedCardInfo(int location) \\calls ArrayList.get()
    public void addCard(Card usedCard) \\calls ArrayList.add()
    ...
    The 'Hand' behaves in exactly the same way as the Deck does in terms of holding, adding, removing cards. The only method it doesn't share is the shuffle() method. A bog standard ArrayList object is therefore perfect to function as a 'Hand'? I don't think an Interface is needed here?
    The implementation may be an ArrayList, but I hope I would not see that used in your code. You should always code to an interface. So, I would expect to see List<Card> (or even Collection<Card> or Iterable<Card>) rather than ArrayList. This gives you the flexibility to change later to a Set<Card> (which makes sense since cards are unique) or LinkedList or any other number of permutations. Now, you just have to change the code in one spot, since you coded to an interface.

    This applies not just to standard Java library interfaces, but your own code as well. Interfaces allow you to change the implementation without normally adversely impacting other portions of code.

    One outstanding book you might want to pick up is Martin Fowler's Refactoring or Joshua Bloch's [Effective Java|http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/ref=sr_1_1?ie=UTF8&s=books&qid=1278077783&sr=8-1].
    I would again like to say thanks for your response. As this post proves, its really got me thinking and brainstorming.
    You are welcome. Keep experimenting. The best way to learn is by doing something interesting.

    - Saish
  • 6. Re: Need some OO design pointers for a Java card game I wrote for uni
    843853 Newbie
    Currently Being Moderated
    Thanks a lot for the info Saish - Definitely helpful
    The game is coming along nicely in a more OO way.

    Cheers

    Faz_86
  • 7. Re: Need some OO design pointers for a Java card game I wrote for uni
    800387 Newbie
    Currently Being Moderated
    Faz_86 wrote:
    Thanks a lot for the info Saish - Definitely helpful
    The game is coming along nicely in a more OO way.

    Cheers

    Faz_86
    Glad to hear it.

    - Saish