Converting Pseudocode to Java Code

Now that you have had a chance to absorb Listing 1-4's Java-like pseudocode, you are ready to examine the process of converting that pseudocode to Java source code. This process consists of a couple of steps.

The first step in converting Listing 1-4's pseudocode to Java involves identifying important components of the game's structure and implementing these components as classes. I will formally introduce classes in Chapter 2.

Apart from the computer player (which is implemented via game logic), the important components are card, deck, and discard pile. I represent these components via Card, Deck, and DiscardPile classes. Listing 1-5 presents Card.

NOTE: Do not be concerned if you find this section's Java source code somewhat hard to follow. After you have read the next few chapters, you should find this code easier to understand.

Listing 1-5. Merging suits and ranks into cards

* Simulating a playing card.

public enum Card {

ACE_OF_CLUBS(Suit.CLUBS, Rank.ACE), TWO_OF_CLUBS(Suit.CLUBS, Rank.TWO),

THREE_OF_CLUBS(Suit.CLUBS, Rank.THREE), FOUR_OF_CLUBS(Suit.CLUBS, Rank.FOUR), FIVE_OF_CLUBS(Suit.CLUBS, Rank.FIVE), SIX_OF_CLUBS(Suit.CLUBS, Rank.SIX), SEVEN_OF_CLUBS(Suit.CLUBS, Rank.SEVEN), EIGHT_OF_CLUBS(Suit.CLUBS, Rank.EIGHT), NINE_OF_CLUBS(Suit.CLUBS, Rank.NINE), TEN_OF_CLUBS(Suit.CLUBS, Rank.TEN), JACK_OF_CLUBS(Suit.CLUBS, Rank.JACK), QUEEN_OF_CLUBS(Suit.CLUBS, Rank.QUEEN), KING_OF_CLUBS(Suit.CLUBS, Rank.KÎNG), ACE_OF_DIAMONDS(Suit.DIAMONDS, Rank.ACE), TWO_OF_DIAMONDS(Suit.DIAMONDS, Rank.TWO), THREE_OF_DIAMONDS(Suit.DIAMONDS, Rank.THREE), FOUR_OF_DIAMONDS(Suit.DIAMONDS, Rank.FOUR), FIVE_OF_DIAMONDS(Suit.DIAMONDS, Rank.FIVE), SIX_OF_DIAMONDS(Suit.DIAMONDS, Rank.SIX), SEVEN_OF_DIAMONDS(Suit.DIAMONDS, Rank.SEVEN), EIGHT_OF_DIAMONDS(Suit.DIAMONDS, Rank.EIGHT), NINE_OF_DIAMONDS(Suit.DIAMONDS, Rank.NINE), TEN_OF_DIAMONDS(Suit.DIAMONDS, Rank.TEN), JACK_OF_DIAMONDS(Suit.DIAMONDS, Rank.JACK), QUEEN_OF_DIAMONDS(Suit.DIAMONDS, Rank.QUEEN), KING_OF_DIAMONDS(Suit.DIAMONDS, Rank.KÎNG), ACE_OF_HEARTS(Suit.HEARTS, Rank.ACE), TWO_OF_HEARTS(Suit.HEARTS, Rank.TWO), THREE_OF_HEARTS(Suit.HEARTS, Rank.THREE), FOUR_OF_HEARTS(Suit.HEARTS, Rank.FOUR), FIVE_OF_HEARTS(Suit.HEARTS, Rank.FIVE), SIX_OF_HEARTS(Suit.HEARTS, Rank.SIX), SEVEN_OF_HEARTS(Suit.HEARTS, Rank.SEVEN), EIGHT_OF_HEARTS(Suit.HEARTS, Rank.EIGHT), NINE_OF_HEARTS(Suit.HEARTS, Rank.NINE), TEN_OF_HEARTS(Suit.HEARTS, Rank.TEN), JACK_OF_HEARTS(Suit.HEARTS, Rank.JACK), QUEEN_OF_HEARTS(Suit.HEARTS, Rank.QUEEN), KING_OF_HEARTS(Suit.HEARTS, Rank.KÎNG), ACE_OF_SPADES(Suit.SPADES, Rank.ACE), TWO_OF_SPADES(Suit.SPADES, Rank.TWO), THREE_OF_SPADES(Suit.SPADES, Rank.THREE), FOUR_OF_SPADES(Suit.SPADES, Rank.FOUR), FIVE_OF_SPADES(Suit.SPADES, Rank.FIVE), SIX_OF_SPADES(Suit.SPADES, Rank.SIX), SEVEN_OF_SPADES(Suit.SPADES, Rank.SEVEN), EIGHT_OF_SPADES(Suit.SPADES, Rank.EIGHT), NINE_OF_SPADES(Suit.SPADES, Rank.NINE), TEN_OF_SPADES(Suit.SPADES, Rank.TEN), JACK_OF_SPADES(Suit.SPADES, Rank.JACK), QUEEN_OF_SPADES(Suit.SPADES, Rank.QUEEN), KING_OF_SPADES(Suit.SPADES, Rank.KÎNG);

private Suit suit;

* @return <code>CLUBS</code>, <code>DIAMONDS</code>, <code>HEARTS</code>,

public Suit suit() { return suit; } private Rank rank;

* @return <code>ACE</code>, <code>TWO</code>, <code>THREE</code>,

* <code>FOUR</code>, <code>FIVE</code>, <code>SIX</code>,

* <code>SEVEN</code>, <code>EIGHT</code>, <code>NINE</code>,

* <code>TEN</code>, <code>JACK</code>, <code>QUEEN</code>,

Card(Suit suit, Rank rank) {

* A card's suit is its membership.

public enum Suit {

CLUBS, DIAMONDS, HEARTS, SPADES

* A card's rank is its integer value.

public enum Rank {

ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING

Listing 1-5 begins with a Javadoc comment that is used to briefly describe the Card class and identify this class's author. I will introduce you to Javadoc comments at the end of this section.

NOTE: One feature of Javadoc comments is the ability to embed HTML tags. These tags specify different kinds of formatting for sections of text within these comments. For example, <code> and </code> specify that their enclosed text is to be formatted as a code listing. Later in this chapter, you will learn how to convert these comments into HTML documentation.

Card is an example of an enum, which is a special kind of class that I discuss in Chapter 5. For now, think of Card as a place to create and store Card objects that identify all 52 cards that make up a standard deck.

Card declares a nested Suit enum. (I discuss nesting in Chapter 4.) A card's suit denotes its membership. The only legal Suit values are CLUBS, DIAMONDS, HEARTS, and SPADES.

Card also declares a nested Rank enum. A card's rank denotes its value: ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, and KING are the only legal Rank values.

A Card object is created when Suit and Rank objects are passed to its constructor. (I discuss constructors in Chapter 2.) For example, KING_OF_HEARTS(Suit.HEARTS, Rank.KING) combines Suit.HEARTS and Rank.KING into KING_OF_HEARTS.

Card provides a rank() method for returning a Card's Rank object. Similarly, Card provides a suit() method for returning a Card's Suit object. For example, KING_OF_HEARTS.rank() returns Rank.KING, and KING_OF_HEARTS.suit() returns Suit.HEARTS.

Listing 1-6 presents the Java source code to the Deck class, which implements a deck of 52 cards.

Listing 1-6. Pick a card, any card import java.util.ArrayList; import java.util.Collections;

import java.util.List;

* Simulate a deck of cards.

* @author Jeff Friesen

public class Deck {

Card.ACE_OF_CLUBS,

Card.TWO_OF_CLUBS,

Card.THREE_OF_CLUBS,

Card.FOUR_OF_CLUBS,

Card.FIVE_OF_CLUBS,

Card.SIX_OF_CLUBS,

Card.SEVEN_OF_CLUBS,

Card.EIGHT_OF_CLUBS,

Card.NINE_OF_CLUBS,

Card.TEN_OF_CLUBS,

Card.JACK_OF_CLUBS,

Card.QUEEN_OF_CLUBS,

Card.KING_OF_CLUBS,

Card.ACE_OF_DIAMONDS,

Card.TWO_OF_DIAMONDS,

Card.THREE_OF_DIAMONDS,

Card.FOUR_OF_DIAMONDS,

Card.FIVE_OF_DIAMONDS,

Card.SIX_OF_DIAMONDS,

Card.SEVEN_OF_DIAMONDS,

Card.EIGHT_OF_DIAMONDS,

Card.NINE_OF_DIAMONDS,

Card.TEN_OF_DIAMONDS,

Card.JACK_OF_DIAMONDS,

Card.OUEEN_OF_DIAMONDS,

Card.KlNG_OF_DIAMONDS,

Card.ACE_OF_HEARTS,

Card.TWO_OF_HEARTS,

Card.THREE_OF_HEARTS,

Card.FOUR_OF_HEARTS,

Card.FIVE_OF_HEARTS,

Card.SIX_OF_HEARTS,

Card.SEVEN_OF_HEARTS,

Card.EIGHT_OF_HEARTS,

Card.NINE_OF_HEARTS,

Card.TEN_OF_HEARTS,

Card.JACK_OF_HEARTS,

Card.OUEEN_OF_HEARTS,

Card.KING_OF_HEARTS,

Card.ACE_OF_SPADES,

Card.TWO_OF_SPADES,

Card.THREE_OF_SPADES,

Card.FOUR_OF_SPADES,

Card.FIVE_OF_SPADES,

Card.SIX_OF_SPADES,

Card.SEVEN_OF_SPADES,

Card.EIGHT_OF_SPADES,

Card.NINE_OF_SPADES,

Card.TEN_OF_SPADES,

Card.JACK_OF_SPADES,

Card.OUEEN_OF_SPADES,

Card.KING_OF_SPADES

private List<Card> deck;

* Create a <code>Deck</code> of 52 <code>Card</code> objects. Shuffle

* these objects.

Collections.shuffle(deck);

* Deal the <code>Deck</code>'s top <code>Card</code> object.

* @return the <code>Card</code> object at the top of the

public Card deal() {

return deck.remove(o);

Return an indicator of whether or not the <code>Deck</code> is empty.

* @return true if the <code>Deck</code> contains no <code>Card</code>

* objects; otherwise, false

public boolean isEmpty() {

return deck.isEmpty();

* Put back a <code>Card</code> at the bottom of the <code>Deck</code>.

* @param card <code>Card</code> object being put back

public void putBack(Card card) {

deck.add(card);

public void shuffle() {

Collections.shuffle(deck);

Deck initializes a private cards array to all 52 Card objects. Because it is easier to implement Deck via a list that stores these objects, Deck's constructor creates this list and adds each Card object to the list. (I discuss List and ArrayList in Chapter 8.)

Deck also provides deal(), isEmpty(), putBack(), and shuffle() methods to deal a single Card from the Deck (the Card is physically removed from the Deck), determine whether or not the Deck is empty, put a Card back into the Deck, and shuffle the Deck's Cards.

Listing 1-7 presents the source code to the DiscardPile class, which implements a discard pile on which players can throw away a maximum of 52 cards.

Listing 1-7. A garbage dump for cards

Simulate a pile of discarded cards.

* @author Jeff Friesen

public class DiscardPile {

private Card[] cards; private int top;

* Create a <code>DiscardPile</code> that can accommodate a maximum of 52

* <code>Card</code>s. The <code>DiscardPile</code> is initially empty.

public DiscardPile() {

cards = new Card[52]; // Room for entire deck on discard pile (should

* Return the <code>Card</code> at the top of the <code>DiscardPile</code>.

* @return <code>Card</code> object at top of <code>DiscardPile</code> or

* null if <code>DiscardPile</code> is empty

public Card getTopCard() {

if (top == -1) return null; Card card = cards[top]; cards[top--] = null; return card;

* Set the <code>DiscardPile</code>'s top card to the specified

* @param card <code>Card</code> object being thrown on top of the

* <code>DiscardPile</code>

public void setTopCard(Card card) {

* Identify the top <code>Card</code> on the <code>DiscardPile</code>

* without removing this <code>Card</code>.

* @return top <code>Card</code>, or null if <code>DiscardPile</code> is

* empty

public Card topCard() {

DiscardPile implements a discard pile on which to throw Card objects. It implements the discard pile via a stack metaphor: the last Card object thrown on the pile sits at the top of the pile and is the first Card object to be removed from the pile.

This class stores its stack of Card objects in a private cards array. I found it convenient to specify 52 as this array's storage limit because the maximum number of Cards is 52. (Game play will never result in all Cards being stored in the array.)

Along with its constructor, DiscardPile provides getTopCard(), setTopCard(), and topCard() methods to remove and return the stack's top Card, store a new Card object on the stack as its top Card, and return the top Card without removing it from the stack.

The constructor demonstrates a single-line comment, which starts with the // character sequence. This comment documents that the cards array has room to store the entire Deck of Cards. I will formally introduce single-line comments in Chapter 2.

The second step in converting Listing 1-4's pseudocode to Java involves introducing a FourOfAKind class whose main() method contains the Java code equivalent of this pseudocode. Listing 1-8 presents FourOfAKind.

Listing 1-8. FourOfAKind application source code

* <code>FourOfAKind</code> implements a card game that is played between two

* players: one human player and the computer. You play this game with a

* standard 52-card deck and attempt to beat the computer by being the first

* player to put down four cards that have the same rank (four aces, for

* The game begins by shuffling the deck and placing it face down. Each

* player takes a card from the top of the deck. The player with the highest

* ranked card (king is highest) deals four cards to each player starting

* with the other player. The dealer then starts its turn.

* The player examines its cards to determine which cards are optimal for

* achieving four of a kind. The player then throws away one card on a

* discard pile and picks up another card from the top of the deck. If the

* player has four of a kind, the player puts down these cards (face up) and

* @author Jeff Friesen

public class FourOfAKind {

final static int HUMAN = 0;

* Computer player

* Application entry point.

* @param args array of command-line arguments passed to this method

public static void main(String[] args) {

System.out.println("Welcome to Four of a Kind!"); Deck deck = new Deck(); // Deck automatically shuffled DiscardPile discardPile = new DiscardPile(); Card hCard; Card cCard;

hCard = deck.deal(); cCard = deck.deal(); if (hCard.rank() != cCard.rank()) break;

deck.putBack(hCard); deck.putBack(cCard);

deck.shuffle(); // prevent pathological case where every successive } // pair of cards have the same rank int curPlayer = HUMAN;

if (cCard.rank().ordinal() > hCard.rank().ordinal())

curPlayer = COMPUTER; deck.putBack(hCard); hCard = null; deck.putBack(cCard); cCard = null;

Card[] hCards = new Card[4]; Card[] cCards = new Card[4]; if (curPlayer == HUMAN)

showHeldCards(hCards); int choice = 0;

choice = prompt("Which card do you want to throw away (A, B, " + "C, D)? ");

switch (choice) {

case 'a': choice = 'A'; break; case 'b': choice = 'B'; break; case 'c': choice = 'C'; break; case 'd': choice = 'D';

discardPile.setTopCard(hCards[choice-'A']); hCards[choice-'A'] = deck.deal();

if (isFourOfAKind(hCards)) {

System.out.println();

System.out.println("Human wins!");

System.out.println();

putDown("Human's cards:", hCards);

System.out.println();

putDown("Computer's cards:", cCards);

return; // Exit application by returning from main()

curPlayer = COMPUTER;

int choice = leastDesirableCard(cCards); discardPile.setTopCard(cCards[choice]); cCards[choice] = deck.deal();

if (isFourOfAKind(cCards)) {

System.out.println();

System.out.println("Computer wins!");

System.out.println();

putDown("Computer's cards:", cCards);

return; // Exit application by returning from main()

curPlayer = HUMAN;

while (discardPile.topCard() != null)

deck.putBack(discardPile.getTopCard()); deck.shuffle();

Determine if the <code>Card</code> objects passed to this method all

* have the same rank.

* @param cards array of <code>Card</code> objects passed to this method

* @return true if all <code>Card</code> objects have the same rank;

* otherwise, false

static boolean isFourOfAKind(Card[] cards) {

for (int i = 1; i < cards.length; i++) if (cards[i].rank() != cards[0].rank()) return false; return true;

* Identify one of the <code>Card</code> objects that is passed to this

* method as the least desirable <code>Card</code> object to hold onto.

@param cards array of <code>Card</code> objects passed to this method @return 0-based rank (ace is 0, king is 13) of least desirable card static int leastDesirableCard(Card[] cards) {

rankCounts[cards[i].rank().ordinal()]++; int minCount = Integer.MAX_VALUE; int minIndex = -1;

if (rankCounts[i] < minCount && rankCounts[i] != 0) {

minCount = rankCounts[i]; minlndex = i;

if (cards[i].rank().ordinal() == minIndex) return i;

return 0; // Needed to satisfy compiler (should never be executed)

Prompt the human player to enter a character. * @param msg message to be displayed to human player

* @return integer value of character entered by user.

static int prompt(String msg) {

System.out.print(msg);

// Erase all subsequent characters including terminating \n newline // so that they do not affect a subsequent call to prompt(). while (System.in.read() != '\n'); return ch;

catch (java.io.IOException ioe) {

return 0;

Display a message followed by all cards held by player. This output simulates putting down held cards.

* @param msg message to be displayed to human player

* @param cards array of <code>Card</code> objects to be identified

static void putDown(String msg, Card[] cards) {

System.out.println(msg); for (int i = 0; i < cards.length; i++) System.out.println(cards[i]);

* Identify the cards being held via their <code>Card</code> objects on

* separate lines. Prefix each line with an uppercase letter starting with

* @param cards array of <code>Card</code> objects to be identified

static void showHeldCards(Card[] cards) {

System.out.println(); System.out.println("Held cards:"); for (int i = 0; i < cards.length; i++) if (cards[i] != null)

System.out.println((char) ('A'+i) + ". " + cards[i]);

System.out.println();

System.out.println((char) ('A'+i) + ". " + cards[i]);

System.out.println();

Listing 1-8 follows the steps outlined by and expands on Listing 1-4's pseudocode. Because of the various comments, I do not have much to say about this listing. However, there are a couple of items that deserve mention:

■ Card's nested Rank enum stores a sequence of 13 Rank objects beginning with ACE and ending with KING. These objects cannot be compared directly via > to determine which object has the greater rank. However, their integer-based ordinal (positional) values can be compared by calling the Rank object's ordinal() method. For example, Card.ACE_OF_SPADES.rank().ordinal() returns 0 because ACE is located at position 0 within Rank's list of Rank objects, and Card.KING_OF_CLUBS.rank().ordinal() returns 12 because KING is located at the last position in this list.

■ The leastDesirableCard() method counts the ranks of the Cards in the array of Card objects passed to this method, and stores these counts in a rankCounts array. For example, given two of clubs, ace of spades, three of clubs, and ace of diamonds, this array identifies one two, two aces, and one three. This method then searches rankCounts from smallest index (representing ace) to largest index (representing king) for the first smallest nonzero count (there might be a tie, as in one two and one three)—a zero count represents no Cards having that rank in the array of Card objects. Finally, the method searches the array of Card objects to identify the object whose rank ordinal matches the index of the smallest nonzero count, and returns the index of this Card object.

This behavior implies that the least desirable card is always the smallest ranked card. Furthermore, if there are multiple cards of the same rank, and if this rank is smaller than the rank of another card in the array, this method will choose the first (in a left-to-right manner) of the multiple cards having the same rank as the least desirable card. However, if the rank of the multiple cards is greater than the rank of another card, this other card will be chosen as least desirable.

I previously stated that Listing 1-5 begins with a Javadoc comment that describes the Card class and identifies this class's author. A Javadoc comment is a documentation item that documents a class, a method, or other program entity.

A Javadoc comment begins with /** and ends with */. Sandwiched between these delimiters (a pair of characters that mark the start and stop of some section) are text, HTML tags (such as <p> and <code>), and Javadoc tags, which are @-prefixed instructions. The following list identifies three common tags:

■ @author identifies the source code's author.

■ @param identifies one of a method's parameters (discussed in Chapter 2).

■ @return identifies the kind of value that a method returns.

The JDK provides a javadoc tool that extracts all Javadoc comments from one or more source files and generates a set of HTML files containing this documentation in an easy-to-read format. These files serve as the program's documentation.

For example, suppose that the current directory contains Card.java, Deck.java, DiscardPile.java, and FourOfAKind.java. To extract all of the Javadoc comments that appear in these files, specify the following command:

javadoc *.java

The javadoc tool responds by outputting the following messages:

Loading source file Card.java...

Loading source file Deck.java...

Loading source file DiscardPile.java...

Loading source file FourOfAKind.java...

Constructing Javadoc information...

Standard Doclet version 1.6.0_16

Building tree for all the packages and classes...

Generating Card.html...

Generating Card.Rank.html...

Generating Card.Suit.html...

Generating Deck.html...

Generating DiscardPile.html...

Generating FourOfAKind.html...

Generating package-frame.html...

Generating package-summary.html...

Generating package-tree.html...

Generating constant-values.html...

Building index for all the packages and classes...

Generating overview-tree.html...

Generating index-all.html...

Generating deprecated-list.html...

Building index for all classes...

Generating allclasses-frame.html...

Generating allclasses-noframe.html...

Generating index.html...

Generating help-doc.html...

Generating stylesheet.css...

Furthermore, it generates a series of files, including the index.html entry-point file. If you point your web browser to this file, you should see a page that is similar to the page shown in Figure 1-8.

Figure 1-8. The entry-point page into the generated Javadoc for FourOfAKind and supporting classes

javadoc defaults to generating HTML-based documentation for public classes and public/protected members of classes. You will learn about public classes and public/protected members of classes in Chapter 2.

For this reason, FourOfAKind's documentation reveals only the public main() method. It does not reveal isFourOfAKind() and the other package-private methods. If you want to include these methods in the documentation, you must specify -package with javadoc:

javadoc -package *.java

NOTE: The standard class library's documentation was also generated by javadoc and adheres to the same format.

Was this article helpful?

0 0

Post a comment