Baccarat Final Programming Project
CS 149, Spring 2021

Baccarat


 

 

 

 

  

1. Due Dates and Submission Details

See below for all due dates and submission details. Note there are multiple submission parts.

2. Honor Code

This assignment should be completed individually to maximize learning. It is important that you adhere to the Course Policies described in the syllabus. Also relevant is the JMU Honor Code.

3. Learning Objectives

This programming assignment is designed to help you learn about (and assess whether you have learned about):

 

      • Creating classes of immutable objects.
      • Creating classes of mutable objects.
      • Creating and using objects (and classes).
      • The difference between (and appropriate use of) static and non-static methods and attributes.

 

It is also intended to reinforce what you have already learned about loops (including nested loops) and arrays.

4. Background

Baccarat is a card game that is similar, at least in spirit, to blackjack. There are actually several versions of baccarat, our concern here is with the punto banco version in which there are two participants, the player and the banker, and the participants do not make any choices. The outcome of each game (or coup) is either "Player", "Banker", or "Tie". In other words, the participant with the higher point value (calculated as described below) is the winner, but ties are possible. The game is controlled by a person known as the croupier. Cards are dealt from a shoethat contains multiple decks of cards. The cards are shuffled (i.e., placed in random order) before they are inserted in the shoe.

4.1 Point Values

Each card in baccarat has a point value. Specifically, the 2 through 9 have the corresponding point value (i.e., 2 through 9), the Ace (A) has a point value of 1, and the 10, Jack (J), Queen (Q), and King (K) all have a point value of 0.

Each hand in baccarat also has a point value. Specifically, the value of a hand is the right-most digit of the sum of the values of the cards in that hand. So, a hand containing a 2 and a 3 has a value of 5, and a hand containing a 6 and an 8 has a value of 4 (the right-most digit of 14).

4.2 Game Play

At the start of each game, both participants (i.e., the player and the dealer) receive two cards (face up) from the croupier. The cards are dealt as follows - one to the player, one to the banker, one to the player, and one to the banker.

If either the player's hand or the banker's hand has a value of 8 or 9 (called a natural) then the game is over, the outcome is determined, the croupier announces the winner, and the game ends. Otherwise, play continues.

If the player's hand has a value of 0, 1, 2, 3, 4, or 5 then the player receives a third card from the croupier.

If the player did not receive a third card the rules are simple - if the banker's hand has a value of 0, 1, 2, 3, 4, or 5 then the banker receives a third card from the croupier. If the player did receive a third card then the rules are more complicated. Specifically:

Player's Third Card When Does Banker Receive a Third Card?
2 or 3 If the banker's hand has a value of 0, 1, 2, 3, or 4
4 or 5 If the banker's hand has a value of 0, 1, 2, 3, 4, or 5
6 or 7 If the banker's hand has a value of 0, 1, 2, 3, 4, 5 or 6
8 If the banker's hand has a value of 0, 1, or 2
A, 9, 10, J, Q, or K If the banker's hand has a value of 0, 1, 2, or 3

At this point, the player and the banker both have either two or three cards, the outcome is determined, the croupier announces the outcome, and the game ends.

4.3 Differences from Blackjack

If you are familiar with the blackjack, you may notice some similarities. However, there are some important differences that you must take into account. (If you are not familiar with blackjack, then you needn't concern yourself with this section.)

One of the things that differentiates baccarat from blackjack is the people involved. In baccarat there is a croupier and exactly two participants, the player and banker. In blackjack there is a dealer and one or more players.

A second thing that differentiates baccarat from blackjack is that neither participant makes any choices. In blackjack, the dealer does not make any choices, but a player can decide to take a card (i.e., "hit") or not take a card (i.e., "stand" or "stick").

A third thing that differentiates baccarat from blackjack is the point values of the cards. As mentioned above, in baccarat, the 2 through 9 have the corresponding point value, the Ace (A) has a point value of 1, and the 10, Jack (J), Queen (Q), and King (K) all have a point value of 0. In blackjack, the 2 through 9 have the corresponding point value, the 10, J, Q, and K all have a point value of 10, and the A has a point value of 11 for the dealer and either 1 or 11 for the player.

A fourth thing that differentiates baccarat from blackjack is the way in which the value of a hand is calculated. As mentioned above, the value of a hand is the right-most digit of the sum of the values of the cards in that hand. In blackjack, the value of a hand is just the sum of the values of the cards in that hand and it is possible to go "over" or "bust" (i.e., have a value that is higher than 21).

5. Design Overview

This section provides an overview of the design and operation of the application.

5.1 UML Class Diagram

The overall design of the application is illustrated in the following UML class diagram. In this diagram, the classes that are drawn in purple and gold have already been implemented, and the classes that are drawn in black must be implemented by you. You have been provided with the byte code for the classes drawn in purple and the source code for the classes drawn in gold. So, you can, if necessary, modify the classes drawn in gold but not those drawn in purple. You have also been provided with stubs for all of the classes drawn in black. This will make it easier for you to test your classes as you implement them.

The classes that have "Baccarat" in their name are specific to the game of bacarrat. The classes that do not have "Baccarat" in their name are applicable more generally (e.g., in other card games and other games of other kinds). You should keep this in mind when implementing these classes.

Baccarat Design

5.2 Operational Overview

From an operational perspective, the main() method in the Casino class must construct a BaccaratShoe object (used for dealing cards) and a BaccaratTable object (used to show the progress of the game). It must then construct a BaccaratCroupier object that will manage game play. Specifically, the BaccaratCroupier object must construct the banker's and player's Hand objects, deal Card objects to them (from the BaccaratShoe object) as appropriate, and display the progress of the game (using the BaccaratTable object).

6. Existing Classes

You are being provided with the source code for the Casino class (which is drawn in gold in the UML class diagram). You should download it (in most browsers, by right-clicking on the link) and put it in the directory/folder containing your source code. You may modify it, but it shouldn't be necessary.

 

 

You are also being provided the byte code for the BaccaratShoe and BaccaratTable classes (which are drawn in purple in the UML class diagram). If your section is using JGrasp or DrJava, you should download the following two .class files (in most browsers, by right-clicking on the links) and put them in the directory/folder containing your source code.

 

 

Here are some older Java 8 versions of these for use on home machines

 

If your section is using Eclipse, you should download the following .jar file into your project default folder[i.e. pa-final] (in most browsers, by right-clicking on the link) and add it to your project(Right click on your project name then Build Path -> Add External Archive and select the jar file)

 

 

This section contains information about these classes (over and above the information that is contained in the UML class diagram).

6.1 The BaccaratShoe Class

The BaccaratShoe class is used by the BaccaratCroupier object to deal cards to the player and the banker.

The explicit value constructor in the BaccaratShoe class is passed a single parameter, named numberOfDecks. This parameter represents the number of 52-card decks that will be shuffled and added to the BaccaratShoe object. If numberOfDecks is 0 then the BaccaratShoe will contain a known (i.e., not randomized) collection of Card objects that can be used for testing purposes. Specifically, it will contain the following (listed in the order in which they will be dealt): 3♣, 3♦, 2♣, 5♣, 4♣, 10♣, 5♦, 10♦, 9♦, 9♠, 2♦, 3♥, 8♥, 7♠, 8♦, 7♥, 5♥, J♣, J♦, A♦, K♠, 6♦, 7♥, 3♠, A♣, 3♣, 4♥, 4♠, 8♣, 4♦, 3♥, 9♣, 10♥, 10♠, 4♣, 10♠, 2♦, 5♥, K♥, 5♦, K♠, 8♦, 10♥, 9♥, J♠. Note that there are duplicates of some cards because a BaccaratShoe object can contain multiple decks.

The containsAtLeast() method returns true if the BaccaratShoe currently contains at least numberOfCards (references to) different Card objects and false otherwise. This method must be used by a BaccaratCroupier object to determine if there are enough Card objects in the BaccaratShoe object to play another game.

The deal() method returns the next Card object in the BaccaratShoe (or null if there are no more Card objects in the BaccaratShoe). It must be used by a BaccaratCroupier object to give Card objects to the player and banker (by calling their receiveCard() method).

6.2 The BaccaratTable Class

The BaccaratTable class is used by a BaccaratCroupier object to show the progress of the game. It has two operating modes, one that uses a graphical user interface (GUI) and one that is text-based and uses the console.

The default constructor instantiates an object that uses the console. The explicit value constructor instantiates an object that uses the GUI if it is passed true.

The clear() method must be called by a BaccaratCroupier object before the start of a game. It clears all of the cards from the table.

The open() method must be called before the BaccaratTable object is used (i.e., before any games are played). In GUI mode, this method will make the window visible.

The close() method must be called after the last game is played. In GUI mode, this method will dispose of the window.

The promptForContinue() method will ask the user (either using the console or the GUI, depending on the mode) to respond when she/he is ready to continue. This method may be used by a BaccaratCroupier object to "pause" the game so that the user can see what has changed.

The promptForYesNo() method will ask the user (either using the console or the GUI, depending on the mode) whether she/he wants to play another game. This method must be used by a Casino object to see if the program should terminate or not.

The showBanker() method shows the current state of the given Hand on the banker's portion of the table. Similarly, the showPlayer() method shows the current state of the given Hand on the player's portion of the table. It must be called by a BaccaratCroupier object at the appropriate times to display the progress of the game.

The showMessage() method displays the given String in the message area of the table. Similarly, the showOutcome() method displays the given String in the outcome area of the table. They must be called by a BaccaratCroupier object at the appropriate times to display the progress of the game.

6.3 The Casino Class

The Casino class is the main class for the program. Its main() method:

      1. Constructs a BaccaratTable that uses the GUI if the command-line arguments contain an element that equals "-gui" and constructs a BaccaratTable object that uses the console otherwise.
      2. Opens the BaccaratTable object.
      3. Constructs a BaccaratShoe object that uses 0 decks if the command-line arguments contain an element that equals "-test" and constructs a BaccaratShoe object that uses 8 decks otherwise.
      4. Iteratively, constructs a BaccaratCroupier object and calls its start() method as long as the BaccaratShoe object contains at least 6 Card objects and the user wants to continue (which it should determine by calling the BaccaratTable object's promptForYesNo()method).
      5. Closes the BaccaratTable object.

A sample expected output for the command line run of Casino via a java Casino -test is provided.

7. Description of Classes that Need to be Written

You must write and test several classes for the assignment. If a specification states that a class must have a particular method then that method must be public. Classes may contain methods and attributes that are not included in the specifications. All attributes must be private unless stated otherwise.

To help you test these classes as you implement them, you have been provided with stubs. You should download them (in most browsers, by right-clicking on the link), unzip them, add them to your working directory or project, and then modify them as required.

 

 

7.1 The Keys Class

The Keys class is a utility class (i.e., a class that contains only static methods) that contains methods for performing look-ups on String[] objects. The Keys class must satisfy the following specifications (in addition to those that are contained in the UML class diagram).

      1. The find() method must search through the unsorted String[] named haystack for theString named needle. It must return -1 when needle is not an element of haystack, when needle is null, and/or when haystack is null. Otherwise, it must return the index of the element in haystack that corresponds to needle. The find() method must properly account for the fact that elements of haystack may be null (i.e., it must "skip" such elements).
      2. The contains() method is a convenience method that returns true when haystackcontains needle and returns false otherwise. It must call the find() method. It must not use an if statement, switch statement, loop, or ternary operator.

7.2 The Card Class

The Card class is an encapsulation of a playing card. Though, at the moment, it will only be used to play baccarat, it must be flexible enough to be used in other card games, and this has influenced some of the design decisions that were made. The Card class must satisfy the following specifications (in addition to those that are contained in the UML class diagram).

      1. Card objects must be immutable.
      2. The RANKS and SUITS arrays must be final.
      3. The RANKS array must contain the elements null, "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", and "King" (in that order).
      4. The SUITS array must contain the elements "Clubs", "Diamonds", "Hearts", and "Spades" (in that order).
      5. The rank and suit attributes must be final.
      6. You should assume that the parameters passed to the two explicit value constructors are valid.
      7. The equals() method must return true if and only if the suit and rank of the two Cardobjects (i.e., the owning object and the parameter) are the same.
      8. The toString() method must return a String representation of the Card that contains the String representation of the rank followed by " of " followed by the Stringrepresentation of the suit (e.g., "10 of Spades" or "Ace of Hearts").

Note that the Card class for this assignment is similar to the one discussed in Chapter 12 of the textbook, but with a few important exceptions.

The Card class for this assignment must also have two static methods that can be used to determine the int rank and suit from their corresponding String representations. These methods are named parseRank() and parseSuit() respectively. They must make use of theKeys class and should assume that the parameters they are passed are valid.

The Card class for this assignment must also have an explicit value constructor that is passed a String representation of the rank and a String representation of the suit (in that order). This constructor must use the parseRank() and parseSuit() methods.

7.3 The Hand Class

The Hand class is an encapsulation of a collection of cards that belongs to a particular participant. Though, at the moment, it will only be used to play baccarat, it must be flexible enough to be used in other card games, and this has influenced some of the design decisions that were made. The Hand class must satisfy the following specifications (in addition to those that are contained in the UML class diagram).

      1. The explicit value constructor is passed the maximum number of Card objects that can be in the Hand. For baccarat this value will be 3 but for other games (e.g., 5 card stud) the number could be different. Initially, the Hand object must contain no Card objects.
      2. The clear() method must reset the Hand object to its initial state.
      3. The getCard() method must return the Card object with the given index. Indexes must be 0-based. If the index is invalid for any reason then this method must return null.
      4. The receive() method must add (a reference to) the given Card object to the Hand object if it is not at capacity. If the Hand object is at capacity, then this method must do nothing. This method must not make a copy of the given Card object.
      5. The size() method must return the number of Card objects currently in the Hand object (not the maximum number).
      6. When there are no Card objects in the Hand, the toString() method must return the String literal ".". Otherwise, the toString() method must return a comma-delimited list of String representations of the Card objects it contains. The String representation of each Card object must be the same as that returned by its toString() method. For example: "10 of Spades,10 of Diamonds,Ace of Hearts".

7.4 The BaccaratCroupier Class

The static methods in the BaccaratCroupier class essentially encapsulate rules of various kinds. They are static so that they can be used by other programs that do not require a BaccaratCroupier object (e.g., programs that teaches people how to play blackjack). These methods must satisfy the following specifications (in addition to those that are contained in the UML class diagram).

      1. The valueOf() methods must return the value of either the Card or Hand that they are passed (calculated using the rules of baccarat as discussed above).
      2. The isNatural() method must return true if and only if the given Hand has a value of 8 or 9.
      3. The mustHit(Hand) method must return true if the given Hand containing exactly two Card objects must receive another Card object. This method must use the rules discussed above (which always apply to the player and apply to the banker when the player did notreceive a third Card object).
      4. The mustHit(Card, Hand) method must return true if and only if the given banker'sHand containing exactly two Card objects must receive another Card object, given that the player received the given third Card. This method must use the rules discussed above (which apply to the banker when the player did receive a third card).
      5. The outcomeOf() method must return one of the following String objects: "Banker","Player", or "Tie". It must use the rules discussed above.

The BaccaratCroupier class is not a utility class (i.e., has non-static attributes and methods) so that a Casino object can create more than one BaccaratCroupier object (e.g., to control the play at more than one BaccaratTable object).

The constructor in the BaccaratCroupier class must "remember" the table and shoeattributes it is passed and construct the player and banker attributes.

The start() method in the BaccaratCroupier class controls the play of the game. It must:

      1. Call its table attribute's clear() method.
      2. Use its table to display the message "Initial Deal".
      3. Deal the first two Card objects (from its Shoe object) to both its player and its banker.
      4. Use its table to show its player and banker.
      5. If either its player or banker has a natural, call its outcomeOf() method to determine the outcome, and use its table attribute to display the message "Winner" and display the outcome. Otherwise, deal a Card object (from its Shoe object) to its player and/or bankeras appropriate, use its table attribute to display the message "After Draw", use its tableattribute to show its player and banker objects, call its outcomeOf() method to determine the outcome, and use its table attribute to display the message "Winner" and display the outcome.

It may also, at any time, call its table attribute's promptToContinue() method in order to "pause" the game (e.g., after the initial deal, after the draw, and/or after displaying the outcome).

8. Sample Screenshot

The following is a sample screenshot on an MS-Windows machine after the end of the first hand when the program is executed using the -gui -test command-line parameters.

GUI

9. A Recommended Process

This assignment is complicated enough that you are unlikely to complete it if you do not use a good process. What follows is one such process.

      1. Read and understand the stubs of of the classes.
      2. Implement the Keys class.
      3. Test the Keys class (locally using JUnit or main tests with stubbed other classes then submit to Autolab should get 15 points when fully working).
      4. Implement the Card class.
      5. Test the Card class (locally using JUnit or main tests with stubbed other classes then submit to Autolab should get 25 points when fully working).
      6. Implement the Hand class.
      7. Test the Hand class (locally using JUnit or main tests then may have enough after stubbing out BaccaratCroupier to submit a first test to Autolab should get 35 points when fully working).
      8. Implement the valueOf(Card) method in the BaccaratCroupier class.
      9. Test the valueOf(Card) method in the BaccaratCroupier class locally.
      10. Implement the valueOf(Hand) method in the BaccaratCroupier class.
      11. Test the valueOf(Hand) method in the BaccaratCroupier class locally.
      12. Implement the isNatural() method in the BaccaratCroupier class.
      13. Test the isNatural() method in the BaccaratCroupier class locally.
      14. Write the mustHit() methods in the BaccaratCroupier class.
      15. Test the mustHit() methods in the BaccaratCroupier class locally
      16. Write the outcomeOf() method in the BaccaratCroupier class.
      17. Test the outcomeOf() method in the BaccaratCroupier class locally.
      18. Test the static methods in the BaccaratCroupier class using Autolab.
      19. Write the constructor for the BaccaratCroupier class.
      20. Write the start() method in the BaccaratCroupier class.
      21. Test the complete application.

Note that, as long as you submit all of the stubs, you can use Autolab to test individual classes and methods. Hopefully, this will encourage you to use the above process and to learn the benefit of working on one small piece at a time. Of course, you should ignore the "hints" about classes/methods that you have not yet implemented.

Note also that, on the previous assignments, many of you have waited until you had everything working before you worried about style. For an assignment of this size, that's a very bad idea. Though it sounds counterintuitive, You will be much more productive if you run checkstyle on each class while you are working on it.

10. Submission

The submission for this assignment is divided into two parts that should be completed in order.

Part A: Understanding the Problem: due Mon, Apr 19 by 11:00pm

To complete Part A you should first carefully read the assignment specification. Once you feel confident that you have a good grasp of the assignment requirements, log into Canvas and complete Part A. YOU MUST ANSWER ALL QUESTIONS CORRECTLY (earn 100%) TO GET ANY CREDIT FOR PART A. You may take the quiz as many times as necessary but if you do not complete it on time, you will receive zero credit.

Part B: Java Implementation: due Monday, Apr 26 by 11:00pm

Submit your code to Autolab. You must upload a .zip file containing the source code for all of the classes necessary to compile and run Casino except the BaccaratShoe and BaccaratTableclasses. Your .zip file must not contain any source files you created for testing purposes and/or any .class files.

Note, since this is a difficult assignment, there is no limit on the number of submissions. However, that does not mean that you shouldn't test your code "locally" before you submit it since Autolab will not provide much feedback.

11. Grading

Your submissions will be graded according to the following criteria. Note that though there is no explicit category for Instructor grading based on style and code quality, individual points may be deducted in each category by the instructor for these types of issues. Note .java files that do not compile will result in a grade of zero for Part B.

Part A: 10%
Part B:
  Checkstyle 10%
  Correctness of the Keys class 5%
  Correctness of the Card class 10%
  Correctness of the Hand class 10%
  Correctness of the valueOf(), isNatural(), mustHit(), and outcomeOf() methods in the BaccaratCroupier class. 30%
  Correctness of the complete application. 25%

Note that, though you can earn partial credit, your code will not compile on Autolab if you don't submit all of the classes (with all of the required methods).

Back to Top