Sign in to follow this  
Chrono1081

I made my first C++ game! :D

Recommended Posts

Ok you can all laugh when you see this but I was excited :D I made it for my programming class. Only thing is I cant figure out how to make the whole thing loop when you reach the bust function or the win function. Is there a way to make a function skip to the end of a loop? Here is my code.
#include <iostream>
#include <time.h>
#include <string>

using namespace std;

void wait(int);
void blackJack(void);
void bust(string);
void titleScreen(void);
void cardGenerate(int &);
void compare(int, int);
void win(string);

int  initialDeal (int &, int&);
int  playerTurn(int &);
int  houseTurn(int &, int);


void main()
{
	srand(time(0)); //Seed random number for the cards

	int pTotal=0;   //Sum of players cards
	int hTotal=0;   //Sum of house cards
	int card=0;     //Card value out of the cardGenerate()
    
	titleScreen();

	initialDeal(pTotal, hTotal);
	playerTurn(pTotal);
	houseTurn(hTotal, pTotal);
	compare(pTotal, hTotal);
}










//////////////////////////////////////////////////////////////////////////////////////////////////////////

void titleScreen()
{
	char userChoice;


	cout<<endl;
	cout<<"\t    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n";
	cout<<"\t    $$                                                   $$\n";
	cout<<"\t    $$ ***  *      *    **** *  *  ****   *    **** *  * $$\n";
	cout<<"\t    $$ *  * *     * *  *     * *      *  * *  *     * *  $$\n";
	cout<<"\t    $$ ***  *    *   * *     **       * *   * *     **   $$\n";
	cout<<"\t    $$ *  * *    ***** *     * *  *   * ***** *     * *  $$\n";
	cout<<"\t    $$ ***  **** *   *  **** *  *  ***  *   *  **** *  * $$\n";
	cout<<"\t    $$                                                   $$\n";
	cout<<"\t    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n";	
	cout<<endl<<endl<<endl<<endl<<endl<<endl;
	cout<<"\t    Press 'S' to Start";
	cout<<endl<<endl;
	cout<<"\t    Press 'X' to Exit \n";
	cout<<endl<<endl;
	cout<<"\t    Selection: ";

	do
	{
		cin>>userChoice;
	    userChoice=toupper(userChoice);

		if(userChoice == 'S')
		{
		}

		else if(userChoice == 'X')
		{
			cout<<"\t    Thank you for playing!\n";
			exit(0);
		}

		else
		{
			cout<<endl;
			cout<<"\t    That is not a valid selection. Please enter S or X";
			cout<<endl<<endl;
			cout<<"\t    Selection: ";
		}
	}while(userChoice != 'S');
}

/////////////////////////////////////////////////////////////////////////////

void cardGenerate(int &x)
{
	x = rand() % 12+2; //Generates random value on the card
    int y = rand() % 4+3;  //Generates a random card

	if(x>9)
	{
		switch(x)
		{
		case 10:
			cout<<" --- "<<endl;
			cout<<"|"<<(char)y<<"  |"<<endl;
			cout<<"| "<<"J"<<" |"<<endl;
			cout<<"|  "<<(char)y<<"|"<<endl;
			cout<<" --- "<<endl;
			break;

		case 11:
			cout<<" --- "<<endl;
			cout<<"|"<<(char)y<<"  |"<<endl;
			cout<<"| "<<"Q"<<" |"<<endl;
			cout<<"|  "<<(char)y<<"|"<<endl;
			cout<<" --- "<<endl;
			x=10;
			break;

		case 12:
			cout<<" --- "<<endl;
			cout<<"|"<<(char)y<<"  |"<<endl;
			cout<<"| "<<"K"<<" |"<<endl;
			cout<<"|  "<<(char)y<<"|"<<endl;
			cout<<" --- "<<endl;
			x=10;
			break;

		case 13:
			cout<<" --- "<<endl;
			cout<<"|"<<(char)y<<"  |"<<endl;
			cout<<"| "<<"A"<<" |"<<endl;
			cout<<"|  "<<(char)y<<"|"<<endl;
			cout<<" --- "<<endl;
			x=11;
			break;

		default:
			break;
		}
	}

	else
		{		
		cout<<" --- "<<endl;
		cout<<"|"<<(char)y<<"  |"<<endl;
		cout<<"| "<<x<<" |"<<endl;
		cout<<"|  "<<(char)y<<"|"<<endl;
		cout<<" --- "<<endl;
		}
}

/////////////////////////////////////////////////////////////////////////////////////////

int initialDeal(int &pTotal, int &hTotal)
{
	
	int card;
	
	cout<<endl<<endl;
	cout<<"The house deals the cards...";

	wait(2);

	cout<<endl<<endl;
	cout<<"Your Cards:";
	
	wait(1);

	cout<<endl;
	cardGenerate(card);
	pTotal+=card;

	wait(1);
	
	cout<<endl;
	cardGenerate(card);
	pTotal+=card;

	if(card==11 && pTotal>21) //Tests for a second ace. If second ace is there then it will reduce ace value to 1.
	{
		pTotal=pTotal-10;
	}
	else
	{
	}

	wait(1);

	cout<<endl;

	cout<<"Total: "<<pTotal; //Tests for BlackJack

		if(pTotal == 21)
		{
			blackJack();
		}
		else
		{
		}
    ///Players deal ends, House deal begins

	wait(2);

	cout<<endl<<endl;
	cout<<"House Cards:";

	wait(1);
	
	cout<<endl;
	cardGenerate(card);
	hTotal+=card;

	wait(1);

	cout<<endl;
	cardGenerate(card);
	hTotal+=card;
	
	if(card==11 && hTotal>21) //Tests for the ace. If the ace throws the player over then ace value is 1 instead of 11.
	{
		hTotal=hTotal-10;
	}
	else
	{
	}

	wait(1);

	cout<<endl;
	cout<<"Total: "<<hTotal;
	cout<<endl<<endl;

	wait(1);

	if(hTotal == 21) //Tests for BlackJack
		{
			blackJack();
		}
		else
		{
		}

	return pTotal, hTotal; 

	
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void wait (int seconds)
{
  clock_t endwait;
  endwait = clock () + seconds * CLOCKS_PER_SEC ;
  while (clock() < endwait) {}
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void blackJack()
{
	cout<<endl;
	cout<<"\t    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n";
	cout<<"\t    $$                                                   $$\n";
	cout<<"\t    $$ ***  *      *    **** *  *  ****   *    **** *  * $$\n";
	cout<<"\t    $$ *  * *     * *  *     * *      *  * *  *     * *  $$\n";
	cout<<"\t    $$ ***  *    *   * *     **       * *   * *     **   $$\n";
	cout<<"\t    $$ *  * *    ***** *     * *  *   * ***** *     * *  $$\n";
	cout<<"\t    $$ ***  **** *   *  **** *  *  ***  *   *  **** *  * $$\n";
	cout<<"\t    $$                                                   $$\n";
	cout<<"\t    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n";
	cout<<endl<<endl<<endl<<endl<<endl<<endl;
	cout<<"\t                             WIN!!!\n";
	exit(0);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void bust(string text)
{
	
	cout<<endl<<endl;
	cout<<"***  *   *  ***  *****\n";
	cout<<"*  * *   * *   *   *  \n";
	cout<<"***  *   *  ***    *  \n";
	cout<<"*  * *   * *   *   *  \n";
	cout<<"***   ***   ***    *  \n";
	cout<<endl<<endl<<endl;
	cout<<text<<" lost!!!";
	cout<<endl<<endl;
	exit(0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int playerTurn(int &pTotal)
{
	int  card;

	char userChoice;
	char player[20]="You";

	do
	{
		cout<<endl<<endl;
		cout<<"Would you like another card? Y or N";
		cin >> userChoice;
		userChoice=toupper(userChoice);

		if(userChoice == 'Y')
		{
			cardGenerate(card);
			pTotal=pTotal+card;
			
			if(card==11 && pTotal>21) //Tests for ace throwing player over 21
			{
				pTotal=pTotal-10;
			}
			else
			{
			}
			cout<<endl;
			cout<<"Total: "<<pTotal;

			if(pTotal>21)
			{
				cout<<endl;
				bust(player);
			}

			else
			{
			}
		}
	}while(userChoice != 'N');

	cout<<endl;
	cout<<"You chose to stay...";
	cout<<endl;

	return pTotal;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

int houseTurn(int &hTotal, int pTotal)
{
	int rndNum=rand()%4+14;
	int loop=1;
	int card;

	char house[20]="The House";

	do
	{
		if(hTotal>=rndNum && hTotal>pTotal)
		{
			cout<<endl;
			cout<<"The house chooses to stay...";
			cout<<endl;
			loop=0;
		}

		else
		{
			cout<<endl;
			cout<<"The house draws a card...";

			wait(1);
			
			cout<<endl;
			cardGenerate(card);
			cout<<endl<<endl;
			
			hTotal=hTotal+card;

			if(card==11 && hTotal>21)
			{
				hTotal=hTotal-10;
			}
			else
			{
			}
			cout<<endl;
			cout<<"Total: "<<hTotal;

			if(hTotal>21)
			{
				bust(house);
			}
			else
			{
			}
		}
	}while(loop != 0);

	return hTotal;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void compare(int pTotal, int hTotal)
{
	char player[20]="You";
	char house[20] ="The House";

	if(pTotal>hTotal)
	{
		cout<<endl;
		win(player);
	}
	
	else if(pTotal<hTotal)
	{
		cout<<endl;
		win(house);
	}

	else
	{
		cout<<endl;
		cout<<"Theres a tie!!!";
		cout<<endl;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void win(string text)
{
	cout<<endl;
	cout<<text<<" Wins!"<<endl;;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////


Share this post


Link to post
Share on other sites
Congrats! [smile]

Quote:
Original post by Chrono1081
Is there a way to make a function skip to the end of a loop?

Use the break key word, as in:
if (pTotal > 21)
{
cout << endl;
bust(player);
break; // I think we're done here!
}

Along the same lines, you can use continue to skip the rest of the code in the loop and to proceed directly with the next itteration, as in:
while (true)
{
if (something)
{
cout << "I can't be bothered with the rest of the code.";
continue;
}

cout << "If 'something' was true, we shouldn't see this line.";
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Chrono1081
I may have to use goto :/ Its the only way I can think of to skip to the end of the loop :/ The suggestions from other posters dont seem to work inside a function :'(


Are you trying to just skip some code inside of a loop and not break out of it? I'm trying to figure out why break or continue won't give you what you need.

Share this post


Link to post
Share on other sites
Whoah don't use break, continue or goto. Properly structure your code with conditionals.
There is *never* a situation where you have to use break/continue/goto. They make the code unreadable and difficult to follow.

Share this post


Link to post
Share on other sites
Quote:
Original post by othello
Whoah don't use break, continue or goto. Properly structure your code with conditionals.
There is *never* a situation where you have to use break/continue/goto. They make the code unreadable and difficult to follow.

You never *have* to use break/continue... But there are also situations where choosing not to use them can make the code *less* readable... (I'm not going to stick up for goto - stay away from that one!)

Share this post


Link to post
Share on other sites
Quote:
Original post by othello
Whoah don't use break, continue or goto. Properly structure your code with conditionals.
There is *never* a situation where you have to use break/continue/goto. They make the code unreadable and difficult to follow.


O_O

What? Please, let's not be that dogmatic. Many ungodly sins have been committed in the name of "avoiding break or continue".

Those are ok. Really.

As for goto, I don't see any in the original code, and noone suggested using it, so I don't understand why it's even being discussed here. Someone out of the blue said "don't use goto", and all of this popped up as a result. Sigh.

Anyway, to the OP, there are definitely a lot of things that can be cleaned up here. :)

One thing in particular I'd like to draw your attention to:


return pTotal, hTotal;


This does not do what you seem to think it does. It is, in effect, equivalent to "return hTotal;" It looks like you figured that out somehow, and got around it by passing pTotal and hTotal by reference, and then ignoring the return value. But let's finish the job: if the return value is meaningless, cut it out. Declare a return type of 'void', and don't return anything explicitly.

But for a first assignment, let's do a little cleanup in cardGenerate().




First, the comments. The term you want for "value on the card" is rank, and the corresponding term (the symbol) is suit. Describe the solution using the vocabularly of the problem.

While we're at it, though: it costs you nothing to make the variable name into something more descriptive. Let the code speak for itself; call the variables "rank" and "suit". If it's called "suit", you don't have to explain that it's a suit, etc. You don't need to say, either, that calling the rand() function generates a random number; you're supposed to know that.

If you can't tell, at even a basic level, what something does from what its name is, the name is wrong. Don't write a comment to explain what it does. Fix the name.

The function name is wrong, too: it isn't grammatical, in the English sense. Write your code to read naturally, as much as possible. (It's a lot more possible than most programmers seem to think.)

Next, all the code that draws the suit of a card, and the box around it, is the same no matter what the rank of the card is. So don't repeat yourself. If you write something three times, that's (a) three chances to get it wrong, and (b) three places you have to change it if you ever decide you want something different.

So what we do is determine the symbol that corresponds to the card, and then run the code (which is only written once) to draw a card, supplying it with the symbol. In fact, we can wrap that up in a function, too. This will become useful later; trust me.

Incidentally, the "symbol" logically is a char. Even though we calculate it with rand(), we only ever use it as a character. So that's what the variable type should be. (The assignment from int to char should not require a cast, but I have been pedantic with casts in the final code so you can see what is going on.)

The code for the rank generation is wrong. We will never create any cards with a "10" symbol on them (that's two letters, which throws off our formatting; the usual solution is to represent these cards with 'T'). When you write 'rand() % 12', that means 12 different possible values can be generated (0 through 11 inclusive). This is obviously wrong.

What we'll do, to avoid confusion, is have separate values for the rank of the card (the symbol we print) and the value (the numbers that we add up to evaluate the hand). The value gets returned. BTW, when we calculate the value from the rank, checking for x > 9 is redundant; use the default case of a switch statement to pick up all the "other" possibilities that we don't explicitly handle.

Finally, there's no reason to "return by reference" for this function. This is abusive: it makes the interface to the function more complicated (you have to declare a variable first, even if you're not actually going to use the returned result later), and unnatural (you expect to return information with, well, the return value).


int generateCard() {
int rank = rand() % 13 + 1;
char suit = static_cast<char>(rand() % 4 + 3);
int value;
char symbol;
switch (rank) {
case 1: // ace
symbol = 'A';
value = 11;
break;

case 10: // ten
symbol = 'T';
value = 10;
break;

case 11: // jack
symbol = 'J';
value = 10;
break;

case 12: // queen
symbol = 'Q';
value = 10;
break;

case 13: // king
symbol = 'K';
value = 10;
break;

default: // two through nine
symbol = static_cast<char>(static_cast<int>('0') + rank);
value = rank;
break;
}

// Now, the output code. Notice that (a) it's perfectly ok to output newlines
// explicitly, and (b) it's perfectly ok to create multiple lines of output
// with one statement. In fact, it's generally preferred style to flush (with
// std::flush or std::endl) at most once per "block" of output text.

cout << " --- \n"
<< "|" << suit << " |\n"
<< "| " << symbol << " |\n"
<< "| " << suit << "|\n"
<< " --- " << endl;

return value;
}






Yes, this is really only a first step. :) I hope it gives you some things to think about, though.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Yes, this is really only a first step. :) I hope it gives you some things to think about, though.

I was about to post some code suggestions, but then I thought: nah, the Amazing Zahlman will stop by this thread sooner or later anyway.

And so it happened. :)

Share this post


Link to post
Share on other sites
Wow thank you all so much for your input! I was hoping for something like that. This evening (morning for you most likely) ill work on re-writing this code to make it easier to read (and to loop at the end so you dont have to restart it each time you want to play.

Ill also be renaming all of my variables because after a second look through I realized that they are confusing. One again thank you everyone for your input and thank you Zahlman for taking your time to write me some code to learn from :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this