Lessons in modularity, based on a previous work by major_small .
Code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
#include <fstream>
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
using std::string;
using std::cout;
using std::endl;
using std::cin;
using std::fstream;
void showTrack ( void ) {
string tracks[] = {
"Welcome to Aintree, happy betting!",
"Welcome to Royal Ascot! May luck be on your side!",
"Welcome to Newmarket, the odds are on your side!",
"Welcome to Epsom...it's a fine day for some serious betting!",
"Welcome to Chepstow...there are some big races today!"
};
int track = rand() % ASIZE(tracks);
cout << tracks[track] << endl;
}
void createOdds( int odds[], int numOdds ) {
const int min = 2;
const int max = 12;
for ( int i = 0 ; i < numOdds ; i++ ) {
odds[i] = (rand() % (max - min + 1) + min);
}
}
void showBalance ( int balance ) {
cout << "Your balance is "
<< static_cast<char>(156) //this kind of cast is safer
<< balance
<< endl;
}
bool promptForLoan ( int& balance ) {
bool result = false;
string loanloan;
cout<<"Would you like to take a loan? (Y/N): ";
getline (cin, loanloan);
if ( loanloan == "Y" || loanloan == "y" )
{
int loan;
cout<<"Enter the amount of the loan: ";
cin>>loan;
cin.ignore(100,'\n'); //!! problems mixing cin and getline
balance += loan;
showBalance ( balance ); //!! re-use of a function
result = true;
}
return result;
}
void displayRunners ( string horses[], int odds[], int numRunners ) {
cout <<"\nOdds....\n\n";
for ( int i = 0 ; i < numRunners ; i++ ) {
cout << horses[i] << " " << odds[i] << ":1" << endl;
}
}
int chooseHorse ( string horsenames[], int numRunners ) {
int horse;
do {
cout<<"Please choose your horse:" << endl;
for ( int i = 0 ; i < numRunners ; i++ ) {
cout << i+1 << ". " << horsenames[i] << endl;
}
cin>>horse;
cin.ignore(1);
if ( horse < 1 || horse > numRunners )
{
cout<<"That is not a correct horsename!\n"<<endl;
system("cls");
}
} while(horse<0 || horse > 3);
return horse - 1;
}
int chooseBet ( int balance, string horsename ) {
int bet;
do
{
cout << "Please enter the amount you would like to bet on "
<< horsename
<< ": "
<< char (156);
cin>>bet;
cin.ignore();
if(bet>balance)
{
cout<<"You don't have enough money to bet that amount!\n"<<endl;
}
else if(bet==0)
{
cout<<"You have to bet something!\n"<<endl;
}
} while ( bet > balance || bet == 0 );
return bet;
}
bool checkLoan ( int &loan, int balance ) {
bool loanOutstanding = true;
loan += 10;
if ( balance >= loan )
{
balance -= loan;
loan = 0;
cout << "You have sucessfully paid off your loan" << endl;
showBalance ( balance );
loanOutstanding = false;
}
return loanOutstanding;
}
int main()
{
bool loantrue = false;
int loan = 0;
int balance = 0;
int bet = 0;
int win = 0;
int winnings = 0;
string stopch;
int horse;
string horsenames[] = {
"Black Beauty",
"Red Rum",
"Green Goddess",
"Silver Speedy"
};
const int numRunners = ASIZE(horsenames);
int odds[numRunners];
// do this once at program start, not in every loop
srand(time(0));
std::fstream infile("test.dat",std::ios::in);
infile>>balance>>loantrue>>loan;
infile.close(); //don't forget to close your files
do
{
showTrack();
createOdds( odds, ASIZE(odds) );
showBalance ( balance );
if (balance == 0)
{
loantrue = promptForLoan ( balance );
}
displayRunners ( horsenames, odds, numRunners );
horse = chooseHorse ( horsenames, numRunners );
bet = chooseBet ( balance, horsenames[horse] );
cout<<"Please wait while the race takes place...\n"
<<"Press [ENTER] to continue"<<std::endl;
std::cin.get();
win = (rand() % numRunners);
winnings = odds[win] * bet;
if ( horse == win )
{
cout << "Congratulations, " << horsenames[horse]
<< " won the race!\n\n"
<< "You have won " << char(156) << winnings;
balance += winnings;
showBalance ( balance );
if ( loantrue )
{
loantrue = checkLoan ( loan, balance );
}
}
else
{
cout << "Sorry, " <<horsenames[horse]<< " lost.\n\n";
balance -= bet;
showBalance ( balance );
if (loantrue)
{
loan += 10;
// you can never pay off the loan on a loss, so there's
// no point in checking.
// This bit of the code can be deleted
//if(balance > loan + 10)
//{
// balance -= loan;
// cout<<"You have sucessfully paid off your loan have payed off your loan.\n\n"
// <<"Your balance is now "<<char(156)<<balance<<endl;
//}
}
}
cout<<"Would you like to play again?(Y/N): ";
getline(cin, stopch);
bet = 0;
system ("CLS");
} while (stopch=="Y"||stopch=="y");
// moved outside the loop
fstream outfile("test.dat",std::ios::out|std::ios::trunc);
outfile<<balance<<'\n'<<loantrue<<'\n'<<loan;
outfile.close();
return 0;
}
How does this help?
Well for one thing, main is <100 lines long now rather than 250+ (and growing).
Also, it's a lot easier to add new code, knowing that stuff which is there already is working.
For example, you might have started out with
Code:
void showBalance ( int balance ) {
cout << "Your balance is "
<< static_cast<char>(156) //this kind of cast is safer
<< balance
<< endl;
}
int main ( ) {
int balance = 123;
showBalance( balance );
return 0;
}
A pretty trivial example, but a function allows you to test it in isolation. Once you know it works, you can simply cut/paste it to your main program.
If it doesn't work, then you have a nice simple program to post to the forum, which would be far more appreciated than say dumping 100's of lines of main() code on the forum and asking for "hunt the bug"