Lab #4 and #5
Coding from a Design Document and Collections

What We're Gonna Do:

In this lab we'll use VisualWorks to build a simple card game using collections and random numbers. This time around though, you'll have to code most of it yourself using the design document specified below and your previous experience with VisualWorks. In the process, you'll hopefully learn about collections, which are Smalltalk's mechanism for representing groups of objects. If you get stuck along the way on how collections work, you can take a look at a Fall 1995 lab dealing specifically with collections. You have two lab periods to finish this lab (and the time in between), so take that time to figure out anything that you don't quite understand. Use your text book, and talk to some of the other students in your section to see if they understand something you don't. If you're really stuck, get in touch with your TA during their office hours.

Problem Description

Donald Trump, disappointed with the sales of his biography, has decided to turn to simpler things. He wants to have a game where one card is dealt to each player until one or more players have between 18 and 21 points. The company (Ace Consultants) he retained for the project came up with the following OOA and OOD, but when he discovered what a steal Tech students are, he reneg-ed on the contract and decided to hand it over to you for coding.

Your job is to take the OOA and OOD that makes up the design document, and implement the system. The interface to the various classes should be as specified, but how you implement the functionality (what the classes and objects do) is up to you. To make life a bit less uncertain, The Donald provided a likely scenario for you to try out your code with.

Object-Oriented Analysis

Below is the OOA diagram that Ace Consultants came up with.

The system deals with three types of objects: Card, CardDeck, and Player. Using the first-person language, the objects would describe themselves this way:

Card
I'm a card. I have a suit (one of Heart, Club, Spade, Diamond) and a rank from 1 to 13.
CardDeck
I'm a deck of cards. I have 52 cards that are in some order.
Player
I'm a player of this card game. I have a hand of cards.

Object-Oriented Design

Using the same diagram as above (since the objects don't send messages to one another in this game), the objects describe their behavior for the OOD:
Card
I'm a card. When my class receives a suit: rank: message it creates a new one of me, and sets my suit and rank attributes to the supplied values. I also know my suit and rank, and can tell them when asked.
CardDeck
I'm a deck of cards. My class knows how to initialize itself, and when it receives an initialize message it creates a new batch of cards and remembers them in the InitialCardDeck class variable. My class also knows how to create a new one of me, and does so when it receives a new message. I deal the card on top when I get the next message. When I'm told to return: a card, I place it at the bottom of my pile. I know how to shuffle myself, which randomizes the order of my cards. I also can tell how many cards I hold, and will say whether I'm empty when I get the isEmpty message.
Player
I'm a player of this card game. My class can create a new one of me. I know how to take: a card and add it to my hand. I also know how to returnAll: of my cards to a deck of cards. When asked for my points I sum the ranks of all the cards I currently hold and answer the total.
In addition to the methods mentioned above, you might want to create a number of private methods that the objects can use to help them do their thing more elegantly. A bit more on that in the Helpful Hints section.

Some Tools

To help you along the way, here are some code for taking something at random from a Collection. There are two classes provided: SampleSpaceWithReplacement and SampleSpaceWithoutReplacement give the ability to repeatedly select something at random from a Collection, with and without replacement, respectively. Of course, you can only select from a Collection without replacement as many times as there are elements in the collection. File in the code you found in the above link, and try out the following to get a feel for how the classes work:
| die |
die := SampleSpaceWithReplacement data: (1 to: 6).
1 to: 10 do:
   [ :i | Transcript show: (die next printStringRadix: 10); show: '  ' ].
Transcript cr.

| urn |
urn := SampleSpaceWithoutReplacement data: #(red red red blue blue).
1 to: (urn size) do: [ :i | 
  Transcript show: 'Size = '; show: (urn size printStringRadix: 10).
  Transcript show: '  Selected = '; show: (urn next); cr ].
Transcript cr.
What happens when you try to select from an empty urn?

Helpful Hints

Here are some thing to consider:
Card class
Create a private method for the Card class which lets you set the suit and rank of the card. This isn't something you want to give to other classes, but is needed within the class.
CardDeck class
Create a private method for assigning to the cards instance variable. The class also needs to be initialized before being used for the first time. Check out the example in the next section. Notice that InitialCardDeck is capitalized. That implies that it is a class variable. A class variable is a variable associated with an entire class rather than an instance of that class. (Sort of like the shared segment of an executable). The class variable is used to store an initial card deck, which can be copied to new instances of the CardDeck class rather than creating it from scratch each time. Objects can understand the copy message, which returns a copy of an object. Use this to copy the InitialCardDeck to new instances of the class. Read up on class variables if you're still a bit confused.
Player class
Create a private method for setting the cards instance variable to an empty OrderedCollection. This is useful when creating a new player, and when the player returns all their cards to the deck.
In addition, adding the following methods to you your classes will help you test and incrementally debug your code. To the Card class, add the following method for printing out the card value on the system Transcript:
printOn: aTextCollector
  "Write my value on the TextCollector argument."

  aTextCollector show: 'Suit = ', suit.
  aTextCollector show: '  Rank = ', (rank printStringRadix: 10).
  aTextCollector cr.
  aTextCollector flush.
To the Player class, add the following method for showing the player's hand:
showHand

   Transcript show: '      Read em and weep...'.
   Transcript show: (self points printStringRadix: 10), ' points!'; cr.
   cards do: [ :eachCard | eachCard printOn: Transcript ].

Testing It

Use the following code to incrementally test your implementation as you write and debug your code.

Card class

| cardDeck cards |
cardDeck := OrderedCollection new: 52.
#(heart club spade diamond) do:
  [ :eachSuit | 
	1 to: 13 do: [ :n | cardDeck add: (Card suit: eachSuit rank: n) ]].
cards := SampleSpaceWithoutReplacement data: cardDeck.
1 to: 5 do: [ :i | (cards next) printOn: Transcript ].

CardDeck class

| cardDeck |
CardDeck initialize.
cardDeck := CardDeck new.
13 timesRepeat: [ (cardDeck next) printOn: Transcript ].
cardDeck shuffle.
13 timesRepeat: [ (cardDeck next) printOn: Transcript ].

When everything is in place...

| players gameCards winners |
players := Set new.
4 timesRepeat: [ players add: Player new ].
gameCards := CardDeck new.
gameCards shuffle.
[ winners := players select: [ :each | each points between: 18 and: 21 ].
  winners isEmpty and: [ gameCards isEmpty not ]]
     whileTrue:
       [ players do:
	[ :each | each points < 21 ifTrue: [ each take: gameCards next ]]].
winners do: [ :player | player showHand ].

Turning in the Code

Go to the system Browser and select the category holding the Card Game classes. Choose the middle-button menu item File Out and type a file name (or the default category name) when prompted. Also, save to a file the output generated on the system transcript when you ran the test code provided above. If you didn't get all the way to the end just save what you have. Mail both the output and the code to your appropriate TA.

(1:30-3)
cat output.txt Game.st | mail -s "lab 4 - YOUR NAME" joita@cc.gatech.edu
OR (3-4:30)
cat output.txt Game.st | mail -s "lab 2 - YOUR NAME" jyan@cc.gatech.edu
OR (4:30-6)
cat output.txt Game.st | mail -s "lab 2 - YOUR NAME" smk@cc.gatech.edu

That's all for this lab. Please quit from VisualWorks before you logout.