Notes on the Card Game Assignment
David Matuszek

Example of a game
Common misconceptions
Dumb things in the game
More code explanations

Example of a game

This is an example of the way this game is played. The purpose of the example is to clarify the rules of the game. The output below is based on actual output, but I have added quite a bit to help explain what is going on.

Dealer: Don
Players: Alice, Bob, and Carol

The deal:
     Don gives Alice a 5 (hidden) and a 4 (visible).
     Don gives Bob a 6 (hidden) and a 1 (visible).
     Don gives Carol an 8 (hidden) and a 9 (visible).
     (Visible totals are now: Alice, 4; Bob, 1; Carol, 9)

The play:
     Don tells Alice that it's her turn to play.
     Alice asks Don for a card.
     Don gives Alice a 4 (visible).
          (Alice's visible cards now total 8.)
     Don tells Bob that it's his turn to play.
     Bob asks Don for a card.
     Don gives Bob a 4 (visible).
          (Bob's visible cards now total 5.)
     Don tells Carol that it's her turn to play.
     Carol passes.
     Don tells Alice that it's her turn to play.
     Alice asks Don for a card.
     Don gives Alice a 10 (visible).
          (Alice's visible cards now total 18.)
     Don tells Bob that it's his turn to play.
     Bob asks Don for a card.
     Don gives Bob a 1 (visible).
          (Bob's visible cards now total 6.)
     Don tells Alice that it's her turn to play.
     Alice passes.
     Don tells Bob that it's his turn to play.
     Bob asks Don for a card.
     Don gives Bob a 1 (visible).
          (Bob's visible cards now total 7.)
     Don tells Bob that it's his turn to play.
     Bob asks Don for a card.
     Don gives Bob a 5 (visible).
          (Bob's visible cards now total 12.)
     Don tells Bob that it's his turn to play.
     Bob passes.
     Don notices that everyone has passed.

The scoring:
     Don asks Alice for her total, gets told 23.
     Don asks Bob for his total, gets told 18.
     Don asks Carol for her total, gets told 17.
     Don decides that Bob has won.
     
Common Misconceptions

A number of students seem to think that inheritance matters here. There is no inheritance. None of my classes is a subclass of any other of my classes. A Dealer is not a kind of Player, a Player is not a kind of Game, etc. (OK, all the classes inherit stuff from Object, at least in theory, but none of that stuff is used.) This program simply makes no use of inheritance. The dotted arrows in the BlueJ diagram indicate that objects in one class use objects in another class; turn the Uses and Inheritance checkboxes on and off to see what I mean.

The program does not ask for keyboard input. You start the program, it runs and produces output, it stops. You, the student, are not one of the Players. We haven't talked yet about how the program can read in anything from the keyboard. It's not easy. It's not wanted. Don't do it.

Dumb Things in the Game

No program is perfect. I got the program working, I did a number of things to simplify it and make it cleaner and more elegant. I missed some things. Any program can be improved, and this one is no exception.

Dumb thing #1. (Caution: you probably won't understand this unless you already thoroughly understand the concepts of object-oriented programming.) I was thinking of a game as an object referring to a Dealer and three Players. With this view, you have to tell the players what game object they are using. Then I made the variables dealer, player1, player2, player3 into static variables (associated with the Game class, not with any particular game instance). Doing this makes it impossible to have more than one game, but it simplifies the program. Once I made these variables static, there was no longer any reason to create a game object, or to require it as a parameter to the Player constructor. (If you understand this, feel free to change the program accordingly.)

This also means that when a player needs to send a nextCard() message to the dealer, he or she can do so by saying Game.dealer.nextCard(), rather than game.dealer.nextCard().

Dumb thing #2. When you have a complex problem to solve, you should break it down into simpler problems. Figuring out who won the game is a fairly complex problem. I created a "helper" method, playerWins(int, int, int). This is fine for my own code, but it is apparently hard to explain what this method is for. I should have left you to struggle with the original problem of determining who won the card game, rather than "help" you in this way. Sorry. Feel free to ignore this method.

More Code Explanations

In the extensive comments, I tried to tell you exactly what each method should do, and give you some good ideas on how to do it. This part is intended to supplement, not replace, those comments.

Game:

main(String)
Construct the game, three players, and the dealer, then tell the dealer to runGame().

Dealer:

runGame()
To deal the cards, call deal(). (This is an example of the Dealer talking to himself.)
To give each player a chance to play, call allowPlay(). (Ditto.)
To determine the winner, call scoreGame(). (Ditto.)
nextCard()
Returns a random number between 1 and 10, inclusive. I've already created a Random object, named random, for you. If you look at the Java API (as I suggested), you will find the Random class in java.util, and you will find that it responds to the message nextInt(int).
Note that a Player can ask a Dealer for a nextCard().
deal()
Hand out two cards to each player, one hidden, one not. You give a card to a player by telling the player to takeCard(...), along with extra information about which card to take (use nextCard() to get this), and whether the card is hidden or visible.
allowPlay()
This method is a little tricky to write. It should tell each player in turn to play(), unless that player has already passed (look at the player's passed variable) and it should frequently check whether all players have passed. When all players have passed, the method is finished.
playerWins(score1, score2, score3)
Determines whether score1 is the highest score not exceeding 21. This method is not necessary, but I found it convenient when writing scoreGame(). You can ignore this method if you want to.
scoreGame()
Asks each player in turn for their total score (by telling the getScore()), decides who has the highest score not exceeding 21, and announces the winner. (In the event of ties, no one wins).

Player:

takeCard()
This method is used by the dealer, at the beginning. The dealer gets a card (by using nextCard()), and tells a player to takeCard(cardhidden). The parameters are extra information given to the player: which card it is, and whether it should be hidden or visible. Since the dealer has to deal six cards, he sends the takeCard(...) message six times, twice to each player.
That's who uses the method. What the player does when she gets the message is to save the card in one of her instance variables, hiddenCard or sumOfVisibleCards, depending on what the hidden parameter tells her to do with it.
play()
The player uses this method to decide whether or not to take a card. The decision process can be as simple or as complicated as you want to make it. In the end, though, the player's choices are (1) to ask the dealer for another card, and add it to her sumOfVisibleCards, or (2) to assign her variable passed the value true.
(Note: The way I did things, the player doesn't know who the dealer is, so asking for another card is a bit complicated. I'll just tell you how to do it: int card = game.dealer.nextCard();)
getScore()
Just add hiddenCard and sumOfVisibleCards and return the result.