$30
Introduction
Slot Machines are one of the most popular gambling methods in modern day casinos. They typically account for approximately 70% of a US casino's income. Slot Machines include a currency detector which validates the money inserted to play. Once a bet is accepted, the machine pays off when a certain combination of symbols appear on its front once the wheels stop spinning. If you are unfamiliar with them, please spend a few moments playing one here: www.freeslots.com
Your Task
Based on a class-based template I will provide to you, your job will be to implement a random, three-wheel slot machine game. Players will need to deposit funds into the machine in order to bet and play. Once played, your slot machine will randomly display a letter in each of three wheels. Based on certain wheel patterns, your slot machine will pay off a multiple of what the player wagered on that round of play.
Your assignment is to complete this C++ program skeleton ( XCode VS2019 ) to produce a program that implements the described behavior. (We've indicated where you have work to do by comments containing the text TODO . Please remove those comments as you finish each thing you have to do.) The program skeleton you are to flesh out defines five classes that represent the five kinds of objects this program works with: SlotMachine, Bank, PayTable, Screen and RandomNumber. You will need to complete code for the SlotMachine, PayTable and Bank classes. Details of the interface to all of these classes are in the program skeleton, but here are the essential responsibilities of each class:
In order to simulate a real Slot Machine, a RandomNumber class has been provided to you. The following UML class diagram describes the RandomNumber class.
The RandomNumber class provides a random integer value within a certain desired range of values. When instantiated, you tell the RandomNumber constructor what the legal range of values you want. By default, the range will potentially include the lower and upper bound value. This behavior is configurable, so you can exclude the lower and upper bound, if you desire. Please review the following driver code:
RandomNumber die( 1, 6 ); // a six-sided die generating the random values 1-6
int toss = die.random( );
RandomNumber dayOfAugust( 0, 32, false, false ); // a day between 1-31
int day = dayOfAugust.random( );
The RandomNumber class is fully implemented and does not require any student changes.
In order to simulate spinning wheels, a Screen class has been provided to you. It provides the screen-related operations and is fully complete. It gets called by the SlotMachine to display information about the current round of play back to the user. The following UML class diagram describes the Screen class.
In order to simulate the currency validator of a slot machine, a Bank class has been provided to you. The Bank class will be used by the SlotMachine to hold player cash as it gets deposited, to verify that a bet can be wagered and to hold any winnings, as they occur. As you will note, the Bank assumes whole-dollar increments and does not support fractional dollar amounts (coins). The following UML class diagram describes the Bank class.
The bankAmount data member of the Bank class holds the total funds deposited by the player as well as winnings, if any. The wager data member of the Bank class holds the bet placed on the current turn of the SlotMachine. In the beginning of time, the bankAmount and wager need to be set to zero. The bankAmount value gets increased when a player deposits funds into the Bank via calls to the method deposit( int amount ). The bankAmount value is fully returned to the player when the Bank is cashed out via calls to the method cashOut( ). The Bank is used to determine whether there are sufficient funds available for a player to wager on a round of Slot Machine play. The method canWager( int amount ) should return true when there are sufficient funds (that is, the wager being equal to or less than the available bankAmount); false otherwise. When a round of the Slot Machine game ends, the Bank can be told the amount that was won or lost on a round of Slot Machine play by a call to either win( int amount ) or lose( int amount ). Please review the following driver code:
Bank b; // wager and bankAmount = 0
b.balance( ); // returns 0
b.canWager( 100 ); // returns false because there aren't sufficient funds in this Bank
b.deposit( 50 );
b.balance( ); // returns 50
b.canWager( 100 ); // returns false because there aren't sufficient funds in this Bank
b.deposit( 50 );
b.canWager( 100 ); // returns true because there are sufficient funds
b.setWager( 100 ); // $100 has now been bet
b.getWager( ); // returns 100
b.balance( ); // returns 100 because the bet wager has not yet been won or lost
b.win( 100 ); // the wager was won
b.cashOut( ); // returns 200
In the skeleton I have supplied, the Bank class is defined and implemented just enough to make the code compile. CS 31 students need to read the TODO comments in Bank.h and Bank.cpp to complete the implementation of this class. The Bank class must be finished first before moving on to the SlotMachine class.
The class PayTable is defined to implement machine payouts and to update a player's Bank. The following UML diagram describes the PayTable class:
The SlotMachine class will provide its three wheel values to the PayTable when a PayTable object is created. Based on those wheel values, a PayTable can determine the appropriate Multiplier for that round of play. A Multiplier is an enumerated value representing different possible slot machine payouts. The following UML diagram describes the enumeration Multiplier:
As its name suggested, calculateMultiplier( ) returns a Multiplier based on the current wheel values in this PayTable. By reviewing the value of the wheels, calculateMultiplier( ) should implement the following pays of winning plays:
Description
Winning Rate
createMultiplier( )returns
a single Ace as long as not a 5-to-1 straight
1-to-1
PayTable::Multiplier::ONETIME
two Aces
5-to-1
PayTable::Multiplier::FIVETIME
any pair other than Aces
3-to-1
PayTable::Multiplier::THREETIME
any pair other than Aces + Ace
4-to-1
PayTable::Multiplier::FOURTIME
three Aces
10-to-1
PayTable::Multiplier::TENTIME
three of a kind other than Aces
7-to-1
PayTable::Multiplier::SEVENTIME
AKQ or QKA in any order (which means AKQ, KAQ, QKA, KQA, QAK, AQK)
5-to-1
PayTable::Multiplier::FIVETIME
three of a kind other than Aces
7-to-1
PayTable::Multiplier::SEVENTIME
any other spins
Lost Wager
PayTable::Multiplier::ZERO
As its name suggests, manageWager( Bank & ) should update the Bank based on the Multiplier for the current wheel values in this PayTable by calling the Bank's .win( int ) or .lose( int ) method.
Finally. the SlotMachine class implements the gaming machine. The SlotMachine has three data members for the wheels of the machine (wheel1, wheel2 and wheel3) and has a data member of type string named sequence which provide the letters that should be displayed as the individual wheels of the machine spin during play and also has a boolean member named display which is tracking whether play display output is desired. One version of the .play( ... ) method randomly picks the wheel values. The other version of .play( ... ) accepts the wheel values so that your code can be properly tested. The SlotMachine constructor should be passed the sequence of letters to display for the spinning wheels feature. When played interactively with user output, call .showDisplay( ) to print the spinning wheels as play occurs. To test programmatically without output and pauses, call .noDisplay( ) prior to a round of play. The following UML class diagram describes the SlotMachine class.
Trivial accessor methods are provided for each of the wheel values. The internal operations spinWheels( ) and updateBankFromSpinAndDisplay( ) need to be called when the game is played.
The sample main( ) I have provided in the skeleton prompts the user for commands to run using the following format:
d# (as in, d100)
a command to deposit funds into the bank
c
a command to cash out all the funds from the bank
b# (as in, b50)
a command to bet an amount on the next round of play. To be accepted, the amount bet (called the wager) must not exceed the available funds in the SlotMachine's bank. A bet must be placed by the user before a round of play is allowed.
p
a command to spin the wheels of the machine. If a winning round happens, the SlotMachine needs to credit its bank accordingly. If a losing round happens, the SlotMachine needs to reduce its bank accordingly.
q
a command to quit the game which will end the program
The skeleton I have provided for you will compile and run but not many of these commands will not work correctly because the Bank, PayTable and certain SlotMachine operations have been left blank. Once you complete the Bank class, your next task will be to complete PayTable and then the SlotMachine class.
You are free to create additional public and private methods and data members as you see fit. However, the test cases will only be driving the public methods of the SlotMachine and Bank classes diagrammed here.
The source files (.h and .cpp) from all these classes will be what you turn in along with a main routine. You can have the main routine do whatever you want, because we will rename it to something harmless, never call it, and append our own main routine to your file. Our main routine will thoroughly test your functions. You'll probably want your main routine to do the same. If you wish, you may write functions in addition to those required here. We will not directly call any such additional functions. If you wish, your implementation of a function required here may call other functions required here.
The program you turn in must build successfully, and during execution, no method may read anything from cin. If you want to print things out for debugging purposes, write to cerr instead of cout. When we test your program, we will cause everything written to cerr to be discarded instead — we will never see that output, so you may leave those debugging output statements in your program if you wish.
Please read the posted FAQ for further assistance. There are also supplemental slides covering many of these ideas available for you to review.
Additionally, I have created a testing tool called CodeBoard to help you check your code. CodeBoard enables you to be sure you are naming things correctly by running a small number of tests against your code. Passing CodeBoard tests is not sufficient testing so please do additional testing yourself. To access CodeBoard for Project 6, please click the link you see in this week named CodeBoard for Project 6. The default student skeleton code has been loaded there. Inside the files named Bank.h, Bank.cpp, PayTable.h, PayTable.cpp, SlotMachine.h and SlotMachine.cpp, copy and paste the versions you have developed. CodeBoard uses its own main( ) to run tests against your code so you won't get any opportunity to provide a main( ) function. Click Compile and Run. However please be aware that no editing changes can be saved inside CodeBoard. In this anonymous user configuration, CodeBoard is read-only and does not allow for saving changes.
Programming Guidelines
Your program must not use any function templates from the algorithms portion of the Standard C++ library or use STL <list> or <vector>. Your implementations must not use any global variables (that is, variables declared outside the scope of main or a class...) whose values may get changed during execution.
Your program must build successfully under both Visual C++ and either clang++ or g++.
The correctness of your program must not depend on undefined program behavior.
What you will turn in for this assignment is a zip file named Project6 containing the following 12 files and nothing more:
The text files named Bank.h and Bank.cpp that implement the Bank class diagrammed above, the text files named SlotMachine.h and SlotMachine.cpp that implement the SlotMachine class diagrammed above, the text files named RandomNumber.h and RandomNumber.cpp that implement the RandomNumber class diagrammed above, the text files named Screen.h and Screen.cpp that implement the Screen class diagrammed above, the text files named PayTable.h and PayTable.cpp that implement the PayTable class diagrammed above, and the text file named main.cpp which will hold your main program. Your source code should have helpful comments that explain any non-obvious code.
A file named report.doc or report.docx (in Microsoft Word format), or report.txt (an ordinary text file) that contains:A brief description of notable obstacles you overcame.
A list of the test data that could be used to thoroughly test your functions, along with the reason for each test. You must note which test cases your program does not handle correctly. (This could happen if you didn't have time to write a complete solution, or if you ran out of time while still debugging a supposedly complete solution.) Notice that most of this portion of your report can be written just after you read the requirements in this specification, before you even start designing your program.
As with Project 3 and 4 and 5, a nice way to test your functions is to use the assert facility from the standard library. As an example, here's a very incomplete set of tests for Project 6. Again, please build your solution incrementally. So I wouldn't run all these tests from the start because many of them will fail until you have all your code working. But I hope this gives you some ideas....
#include <iostream>
#include <string>
#include <cassert>
#include "Bank.h"
#include "PayTable.h"
#include "SlotMachine.h"
using namespace std;
int main()
{
using namespace std;
using namespace cs31;
// test code
Bank b;
assert( b.balance() == 0 );
assert( b.getWager() == 0 );
assert( !b.canWager( 100 ) );
b.deposit( 50 );
assert( b.balance() == 50 );
assert( !b.canWager( 100 ) );
assert( b.canWager( 50 ) );
b.deposit( 50 );
PayTable p( 'A', 'A', 'A' );
PayTable::Multiplier m = p.calculateMultiplier( ); // 3 Aces is a 10-1 winner
assert( m == PayTable::Multiplier::TENTIME );
SlotMachine s( "AKQJ987" ); // cheating... b.setWager( 100 ); s.play( b, 'A', 'A', 'A' ); assert( b.balance( ) == 1100 ); // 3 Aces is 10-1 winner and a round of play adjusts the bank
cout << "all tests passed!" << endl; return 0;
}
Turn in the file by the due time above. Give yourself enough time to be sure you can turn something in, because we will not accept excuses like "My network connection at home was down, and I didn't have a way to copy my files and bring them to a SEASnet machine." There's a lot to be said for turning in a preliminary version of your program and report early (You can always overwrite it with a later submission). That way you have something submitted in case there's a problem later.
G31 Build Commands
g31 -c Bank.cpp
g31 -c PayTable.cpp
g31 -c RandomNumber.cpp
g31 -c Screen.cpp
g31 -c SlotMachine.cpp
g31 -c main.cpp
g31 -o runnable main.o Bank.o PayTable.o. RandomNumber.o Screen.o. SlotMachine.o
./runnable