proper use of .java files (layout)

I

infinitum3d

I'm trying to figure out the best way to layout a java program. Should I put each object into its own .java file? If I'm making a card game, that would be 52 .java files. Is that crazy? Normal?

Or should I separate them by suit and just have 4 .java files? Or by value so there are 13 .java files?

Thanks!

I3D
 
R

Robert Klemme

I'm trying to figure out the best way to layout a java program.
Should I put each object into its own .java file? If I'm making a
card game, that would be 52 .java files. Is that crazy? Normal?
Crazy.

Or should I separate them by suit and just have 4 .java files? Or by
value so there are 13 .java files?

You better had just one class for Card which has different properties.
Which properties you need depends of course on the card at hand and on
the application. Sometimes it may make sense to make Card an interface
and have different implementing classes. But that all depends on the
application that is being written.

Kind regards

robert
 
A

Arne Vajhøj

I'm trying to figure out the best way to layout a java program.
Should I put each object into its own .java file? If I'm making a
card game, that would be 52 .java files. Is that crazy? Normal?

Or should I separate them by suit and just have 4 .java files? Or by
value so there are 13 .java files?

You need to distinguish between classes and objects.

You will have one class per Java file (actually you can
have more than one, but let us keep this simple to start with).

When the program runs then you can create one or more instances
of that class - those instances are objects.

A deck of card will usually be considered 52 instances/objects
of 1 class.

Arne
 
M

markspace

I'm trying to figure out the best way to layout a java program.
Should I put each object into its own .java file? If I'm making a
card game, that would be 52 .java files. Is that crazy? Normal?

What Arne and Robert said. In this case you want a single class with
two fields, one for suit and one for face value. (You could encode both
the suit and the value in to a single field. However this sort of space
saving is usually counter-productive, unless you're absolutely sure it's
needed.)

public class PlayingCard {
private final int value; // Ace = 1
private final Suit suit;

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

... ect....

}


You will of course have to make 52 instances of that class. Do that at
runtime, don't try to make 52 files.
 
I

infinitum3d

Brilliant! That makes perfect sense.

Thank you all for the advice. This will really make things easier for me.

-I3D
 
J

John B. Matthews

Arne Vajhøj said:
You need to distinguish between classes and objects.

You will have one class per Java file (actually you can have more
than one, but let us keep this simple to start with).

When the program runs then you can create one or more instances of
that class - those instances are objects.

A deck of card will usually be considered 52 instances/objects of 1
class.

infinitum3d: There's a nice example that illustrates this using typesafe
enums, introduced in Java 1.5:

<http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html>
 
L

Lew

markspace said:
public class PlayingCard {

private final int value; // Ace = 1

I would make this an enum.

"Ace = 1" is not a valid association in the problem domain, and its use
as a representation creates risk of an artificial equivalency.
private final Suit suit;

That's more like it.
public static enum Suit { HEARTS, CLUBS, SPADES, DIAMONDS }
... ect.... [sic]
}

You will of course have to make 52 instances of that class. Do that at

No "of course" about it.
http://www.hoylegaming.com/rules/showrule.aspx?RuleID=209
runtime, don't try to make 52 files.

How many cards in a blackjack shoe?
http://en.wikipedia.org/wiki/Blackjack

If you hard-code certain assumptions, e.g., that there are 52 cards in the deck,
your program will be unable to model many games.
 
M

markspace

I would make this an enum.

"Ace = 1" is not a valid association in the problem domain, and its use
as a representation creates risk of an artificial equivalency.


I was actually thinking about that. I don't like the idea of trying to
encode most of the values of a face card as enums. Something like this
might be a reasonable compromise.

public static enum Cards {ACE, DEUCE, KING, QUEEN, JACK }

public void set( Cards card, Suit suit ) {
switch( card ) {
case ACE: value = 1; break;
case DEUCE: value = 2; break;
case KING: value = 13; break;
case QUEEN: value = 12; break;
case JACK: value = 11; break;
}
this.suit = suit;
}

public void set( int card, Suit suit ) {
value = card;
this.suit = suit;
}

I also think it might be valuable to have one implementation of
PlayingCard with one internal encoding, then assigning different
semantics (e.g., ace high or low) in a separate game object. Trying to
overload PlayingCard too much with too much business logic seems to
violate encapsulation. A simple wrapper class could easily switch the
value of an ace; so could a custom comparator. Without more
requirements from the OP, it's really hard to guess what of the many
possible solutions is best.

So I went with a simple implementation of "ace" (ace = 1) and I'm
leaving to other logic to decide how to treat that. You could have
other more complicated implementations of PlayingCard, but too much gets
too baroque quickly, imo, especially if you don't need all that
functionality for most use cases.

Another example: in many standard decks, the names of the suits are not
Spades, Hearts, etc. but vary by country. Again I'm leaving that for
some other part of the program. Localization of card names can be done
by wrapping this PlayingCard with a GermanPlayingCard, for example.
 
L

Lew

I was actually thinking about that. I don't like the idea of trying to
encode most of the values of a face card as enums. Something like this
might be a reasonable compromise.

I wouldn't code *any* of the values of the face cards or the pip cards as anything
in the PlayingCard type.
public static enum Cards {ACE, DEUCE, KING, QUEEN, JACK

, TEN, NINE, EIGHT, SEVEN, SIX, FIVE, FOUR, TREY, JOKER,

And I'd put them in order {JOKER, ACE, DEUCE, ..., }
public void set( Cards card, Suit suit ) {

'Card', not 'Cards'.
switch( card ) {

case ACE: value = 1; break;

That's clumsy. But how will this work for Blackjack?
case DEUCE: value = 2; break;
case KING: value = 13; break;
case QUEEN: value = 12; break;
case JACK: value = 11; break;
}
this.suit = suit;
}

public void set( int card, Suit suit ) {
value = card;

Should not be an 'int', I reiterate.

There is nothing "integery" about the card name.
this.suit = suit;
}

I also think it might be valuable to have one implementation of
PlayingCard with one internal encoding, then assigning different

Yes, the "internal encoding" is the enum constant.
semantics (e.g., ace high or low) in a separate game object. Trying to
That.

overload PlayingCard too much with too much business logic seems to
Agreed.

violate encapsulation. A simple wrapper class could easily switch the

Not "switch", assign, and not a "simple wrapper class" but a games rule engine.
value of an ace; so could a custom comparator. Without more
requirements from the OP, it's really hard to guess what of the many
possible solutions is best.

I was going for modeling a playing card so it would work in any card game.
So I went with a simple

but feckless
implementation of "ace" (ace = 1) and I'm
leaving to other logic to decide how to treat that. You could have
other more complicated implementations of PlayingCard, but too much gets

You've already included too much by having an 'int' value.
too baroque quickly ^H^H^H^H^H^H^Halready
, imo, especially if you don't need all that
functionality for most use cases.

You don't need the 'int' value for any use cases.
Another example: in many standard decks, the names of the suits are not
Spades, Hearts, etc. but vary by country. Again I'm leaving that for

Silliness. We know from the OP's problem statement that they intend the French suits.
some other part of the program. Localization of card names can be done
by wrapping this PlayingCard with a GermanPlayingCard, for example.

Wrap, wrap, wrap. You sure are addicted to wrapping. I wouldn't recommend that.

How would a 'GermanPlayingCard' delegate to the standard French model?

I'd use a different type that implements a suitable interface, or just use a different enum.

But I can't really see the refactoring clearly from here. I'd need a candidate implementation
to refactor.
 
A

Arne Vajhøj

I was actually thinking about that. I don't like the idea of trying to
encode most of the values of a face card as enums.

Why not?

13 distinct values with an order but no numeric values
seems a perfect fit for enum to me.
Another example: in many standard decks, the names of the suits are not
Spades, Hearts, etc. but vary by country. Again I'm leaving that for
some other part of the program. Localization of card names can be done
by wrapping this PlayingCard with a GermanPlayingCard, for example.

Or by using standard I18N techniques in the UI layer!

Arne
 
A

Arne Vajhøj

Here is a possible outline for a simple card game component
It has NOT been compiled.

And it will not.

.... is not valid Java (in the context where it is used).
Comments welcome

Card.java

public class Card{
//enumeration types for rank and suit perhaps
...
}

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

Deck.java

public class Deck{

private Card[] deck = null; //implementation hidden from clients

public Deck(Integer cardCount){
deck = new Card[cardCount]; //not all games use all the cards
}
...
}

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

Dealer.java

public class Dealer{

private Deck deck = null;

public Dealer(Deck deck){
this.deck = deck;
}

public void shuffle(){
... //delegate to deck ?
}
...

public List<Card[]> deal(Integer hands, Integer cardsPerHand){
...
}
}

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

Snap.java

public class Snap {

private Deck deck = null;
private Dealer dealer = null;

public Snap(){
this.deck = new Deck(54); // don't forget the jokers
this.dealer = new Dealer(deck);
}

public void play(Integer numPlayers){
dealer.shuffle();
dealer.deal(numPlayers, 0); // 0 indicates deal all to players
...
}
...
}

Java is well suited to an 'Object Oriented' approach to software design
The above outline is just one of many possible OO solutions.


A Deck constructor with just the number of jokers would make
more sense to me.

The Deck(cardCount) does not specify what cards are there. And
it is not really a deck but a deck with something added or
removed.

Arne
 
G

Gene Wirchenko

[snip]
13 distinct values with an order but no numeric values
seems a perfect fit for enum to me.

An enum does not guarantee an order.

Do you play poker? Aces are usually high, but can be low in the
case of straights.

[snip]

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

On 12/17/2012 1:28 PM, Lew wrote:
[snip]
If you hard-code certain assumptions, e.g., that there are 52 cards in the deck,
your program will be unable to model many games.

I would argue that a deck is always 52 cards, but that some
games use more than one deck.

Some games do not use all of the deck; some include one or more
jokers. See the section "Modified Deck" in
http://boardgamegeek.com/wiki/page/Standard_Deck_Playing_Card_Games
for several examples.

Sincerely,

Gene Wirchenko
 
A

Arne Vajhøj

How come a brand-new pack of cards always has fifty-four?

It does not always.

It comes with 2, 3 or maybe even 4 jokers.

So number of jokers should be a constructor argument, if
it has to be realistic.

Arne
 
E

Eric Sosman

It does not always.

It comes with 2, 3 or maybe even 4 jokers.

So number of jokers should be a constructor argument, if
it has to be realistic.

Can we say, then, that "a deck is always 52 cards, for
suitable values of 52?"
 
A

Arne Vajhøj

Can we say, then, that "a deck is always 52 cards, for
suitable values of 52?"

Very funny.

A deck is 52 + number of jokers cards.

A game may be multiple decks or maybe even a subset of a deck.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top