Open Side Menu Go to the Top
Register
Looking for info on C++ Looking for info on C++

02-23-2012 , 01:44 PM
Ah you decrement cards_in_deck before using it.
Looking for info on C++ Quote
02-23-2012 , 04:21 PM
Quote:
Originally Posted by Ryanb9
Think I'm going in the right direction?


Spoiler:
Code:
#include "stdafx.h"
#include <iostream> 
#include <string> 
#include <vector>
#include <stdlib.h>
#include <time.h>
#include <sstream>

using namespace std ; 

	string array_card_string[2][52] = 
	{{"Ah", "2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "10h", "Jh", "Qh", "Kh",
	"Ad", "2d", "3d", "4d", "5d", "6d", "7d", "8d", "9d", "10d", "Jd", "Qd", "Kd",
	"As", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s", "Js", "Qs", "Ks",
	"Ac", "2c", "3c", "4c", "5c", "6c", "7c", "8c", "9c", "10c", "Jc", "Qc", "Kc"},
	{"11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10", 
	"11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10",
	"11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10",
	"11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10",}};
	vector<int> card_vector;
	int string_to_int_converter(string abc);
	int RNG(int cards_in_deck);
	void refresh_deck();
	int deal_a_card(int cards_in_deck);
	
int main () 
{
	srand(unsigned (time(0)));
	int cards_in_deck = 53; 
	refresh_deck();
int test = 0; 
do{
	int card1 = deal_a_card(cards_in_deck--);
	int card2 = deal_a_card(cards_in_deck--);
	cout << endl << "Your hand is " << array_card_string[0][card1] << " " << array_card_string[0][card2] << endl ;
	cout << "Your hand value is " << ((string_to_int_converter(string (array_card_string[1][card1]))) + (string_to_int_converter(string (array_card_string[1][card2])))) << endl ; 
	cin >> test; 
} while (test != 0) ; 
	return 0 ; 
}
int RNG(int cards_in_deck) 
{
	int random_number = rand() % cards_in_deck ; 
	return random_number; 
}

void refresh_deck()
{
	for (int y = 0 ; y != 52 ; y++) {
	card_vector.push_back (y); 
	};
}

int deal_a_card(int cards_in_deck)
{
	cards_in_deck--;	
	int ticker = 0 ; 
	do {
		swap (card_vector[0], card_vector[RNG(cards_in_deck)]) ; // shuffles the deck
		ticker++ ; 
	} while (ticker != cards_in_deck) ; 
	int xyz ;  
	xyz = card_vector.at(0); 
	card_vector.erase (card_vector.begin());
	return xyz; 
}

int string_to_int_converter(string abc)
{
std::string be_converted = abc;
int value = atoi(be_converted.c_str());
return value;
}


I'm trying to do it in as few lines as possible but its starting to hurt my brain. I think I can get rid of the card1 but not sure how yet.
One suggestion. Try to separate data from code in your program design. You don't want to hard code stuff like the card deck. Because that forces you to modify code whenever you want to change inputs/data into the program. Save the card deck in a text file, and write a class that reads that file and creates the relevant objects.
Looking for info on C++ Quote
02-23-2012 , 04:27 PM
Each card has 2 properties:
a string name
a numeric value

You are putting the numeric values in strings because that's the type of array you have for the deck. That is bad: it's a number, save it as a number. It's also bad because you have to "know" how to navigate the array to find the value. "knowing stuff" is your enemy. That's dependencies. As the dependencies grow in a program, so does the complexity. It becomes an entropy battle that kills the program in the end.

Keep related things together:

Code:
struct Card {
string name;
int value;
};
You can still initialize:
Code:
Card cards[] =
{ {"Ah", 11},
{"2h", 2},
...
};
Looking for info on C++ Quote
02-23-2012 , 04:42 PM
Quote:
Originally Posted by attempto!
-dump the value lookup think for the cards. u can use a multidimensional array to store the value along with the card string.
Was trying to do this >.< seemed like a good idea but took me forever to figure out how to get from string to int.
Looking for info on C++ Quote
02-23-2012 , 05:30 PM
Quote:
Originally Posted by muttiah
One suggestion. Try to separate data from code in your program design. You don't want to hard code stuff like the card deck. Because that forces you to modify code whenever you want to change inputs/data into the program. Save the card deck in a text file, and write a class that reads that file and creates the relevant objects.
The definition of a deck of cards isn't changing. Having it external means it could be edited to be *anything*. The program then has to deal with a much bigger set of inputs -- a harder problem.

Over generalizing is its own set of problems.
Looking for info on C++ Quote
02-23-2012 , 06:40 PM
You don't need to re-shuffle the deck every time you deal a card. You can just do it once. You also don't need a vector because you have a fixed number of cards (52), so you can just use a plain array. Try something like this:

Code:
struct Deck
{
    int cards[52];
    int top; // array index of the top card in the deck
};

Deck deck;

void refresh_deck()
{
    for(int i = 0; i < 52; i++)
        deck.cards[i] = i;
    deck.top = 51;
}

void shuffle()
{
    refresh_deck();
    for (int i = deck.top; i >= 0; i--)
    {
        int r = RNG(i + 1);
        swap(deck.cards[i], deck.cards[r]);
    }
}

int deal_a_card()
{
    if(deck.top < 0) // this is an error condition
        exit(1); // exit the program
    int card = deck.cards[deck.top]; // get the top card in the deck
    deck.top--;
    return card;
}
Then you can just call shuffle() from main(). (note: untested code)
Looking for info on C++ Quote
02-23-2012 , 09:00 PM
Agree with Chips Ahoy about using structs to represent the cards as being simpler and more intuitive.

Also, since you're probably focused on learning the functional part of C++ at this point and maybe haven't gotten into objects and classes, using structs is a nice entry point to thinking about objects. In C++, a struct is the same thing as a class (with one difference, which you can ignore for now), and a particular instance of that struct (a concrete variable, such as cards[23]) is also an object of data type Card. And each Card object (struct) has a string object data member and an int data member as we specified in our struct declaration.

If you're not clear on how to use them, say you want the value of either Card data member, you access it with the dot operator like
Code:
cards[23].name
or
Code:
cards[23].value
.

This might be getting to far ahead for you, but the traditional way to handle this problem would be to use a deck object that contains a collection of card objects, along with basic functions like shuffle and deal. Here's a simple example where we create a Deck struct (really a class, but this might be a little easier to understand) that has a function known as a constructor, along with the functions deal and shuffle, and an array of Card objects. When we create a Deck, the constructor automatically runs and populates the hands array and shuffles the cards. When we call the deal function, the deck first deals from the first element of the array as indicated by the Deck member variable cardIndex, and after each deal that index is incremented. Once we've dealt all the cards in the deck, the deal function reshuffles the deck without our having to worry about it.

It should be a bit easier to work with Deck and Card objects. Some of the syntax might be a bit confusing, let me know.

Code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <ctime>
#include <vector>

using namespace std;

const string Suits[] = {"Spades", "Hearts", "Diamonds", "Clubs"};
const string Ranks[] = {"Ace", "2", "3", "4", "5", "6", "7",
			 "8", "9", "Ten", "Jack", "Queen", "King"};

struct Card {
	int suit;
	int rank;
};

struct Deck {
	// Constructor function, runs first automatically each time
	// a Deck object is created.  We can use this to populate cards.
	Deck() {
		for( int suit = 0; suit < 4; suit++ ) {
			for( int rank = 0; rank < 13; rank++ ) {
				int curCard = suit*13 + rank;
				cards[curCard].suit = suit;
				cards[curCard].rank = rank;
			}
		}
		
		shuffle();
	}
		
	// member functions
	void shuffle() {
		cardIndex = 0;
		
		for( int pass = 1; pass <= 1000; pass++ ) {
			int startIndex = rand() % 52;
			int newIndex = rand() % 52;
	
			Card originalCard = cards[startIndex];
			cards[startIndex] = cards[newIndex];
			cards[newIndex] = originalCard;
			// You could also use the swap() function from <algorithm>
			// swap(cards[startIndex], cards[newIndex]);

		}
	}
	
	Card deal() {
		// If we're at the end of the deck we reshuffle the deck
		// and start over at the first card
		if( cardIndex > 51 ) {
			cout << "Shuffling...\n";
			shuffle();
		}
		return cards[cardIndex++];
	}
	
	// data members
	Card cards[52];
	int cardIndex;	// this keeps track of how many cards we've dealt from the deck
};

int main() {
	srand((unsigned)time(0));
	Deck deck;
	for( int i = 1; i <= 55; i++ ) {
		Card card = deck.deal();
		cout << "You drew the " << Ranks[card.rank] << " of "
			 << Suits[card.suit] << "\n";
	}
	
	return 0;
}

Last edited by weevil; 02-23-2012 at 09:30 PM.
Looking for info on C++ Quote
02-23-2012 , 09:39 PM
I'm just going to toss this out here: Once you're reasonably comfortable with the language, spending some time with Stroustrup's big book can be very informative. Don't care how long you've been using C++, you can learn stuff from it.

When I read it I was shocked at times at little features I didn't know.
Looking for info on C++ Quote
02-23-2012 , 11:36 PM
I will look at those codes, thanks. The main problem I was having was trying to figure out how to keep track of dealer and players hand value so I know if/when someone busts etc. Idk why I was using a vector but they are fun. And now I see why people are bothered to make classes, i couldn't figure it out before but holy **** thats amazing.
Looking for info on C++ Quote
02-25-2012 , 02:08 AM
Great thread, 5*
Looking for info on C++ Quote
02-25-2012 , 02:20 PM
Okay I gave OOP a shot and I have to say I like it a lot. But I wanted to check up with you guys before I got into the grunt work of actually making the pieces come together.

Spoiler:
Code:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <sstream>

using namespace std; 

class BlackJack{ 
public:
	// Public Functions:
	void SetDeck () ;
	void ShuffleDeck () ;
	void GiveCardPlayer () ;
	void GiveCardDealer () ;
	void DisplayPlayerHand () ;
	void DisplayDealerHand () ;
	int GetPlayerHandValue () ;
	int GetDealerHandValue () ;
	void DisplayPlayerHandValue () ;
	void DisplayDealerHandValue () ;
	void PurgeVectors() ; 

	void tester() ; 

private:

	//private variables 
	vector<string> CardFace ;       //  Will get poker value of each card pushed into it
	vector<int> CardValue ;         // Will get poker value of each card pushed into it
	vector<int> CardNumber ;        //  Will contain #'s 0-51
	vector<string> PlayerHand ;    //  Gets Ah, 7d, 9s, etc pushed into it
	vector<string> DealerHand ;     // Gets Ah, 7d, 9s, etc pushed into it
	vector<int> PlayerHandValue ;   //  Gets 11, 7, 9, pushed into it
	vector<int> DealerHandValue ;   //  Gets 11, 7, 9, pushed into it

	//private functions
	int RNG () ; 
	int GetZeroCard ()  ; 
	int BotCardReadAndDestory () ; 
}; 



int main ()
{
	srand(unsigned (time(0))) ; //used for RNG idk where to put it

	BlackJack Game; 
	Game.SetDeck();
	Game.ShuffleDeck(); 
	Game.GiveCardPlayer();
	Game.GiveCardPlayer();
	Game.GiveCardDealer();
	Game.GiveCardDealer();

	cout << "Your Hand is " ; 
	Game.DisplayPlayerHand(); 
	cout << " value is " ; 
	Game.DisplayPlayerHandValue() ; 
	cout << "\nDealer hand is " ; 
	Game.DisplayDealerHand () ; 
	cout << " value is " ; 
	Game.DisplayDealerHandValue() ; 
	cout << "\nDealing you another card...\n" ; 
	Game.GiveCardPlayer();
	cout << "Your Hand is " ; 
	Game.DisplayPlayerHand(); 
	cout << " value is " ; 
	Game.DisplayPlayerHandValue() ; 



	Game.PurgeVectors() ;
	char f ; 
	cin >> f; 
	return 0 ; 
}

	//Function definitions

	// this function will....
	void BlackJack::SetDeck () 
	{
		// make a vector with 52 different playing card "faces"
		string CardFaceArray[52] =  
		{"Ah", "2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "10h", "Jh", "Qh", "Kh",
		"Ad", "2d", "3d", "4d", "5d", "6d", "7d", "8d", "9d", "10d", "Jd", "Qd", "Kd",
		"As", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s", "Js", "Qs", "Ks",
		"Ac", "2c", "3c", "4c", "5c", "6c", "7c", "8c", "9c", "10c", "Jc", "Qc", "Kc"};	

		// make a vector with 52 (10 unique) poker hand values
		int CardValueArray[52] = 
		{11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 
		11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 
		11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 
		11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10}; 

		// and make 1 last vector which is n 0-51 that i use as my meta-index
		for(size_t i = 0; i != 52 ; i++)
		{
			CardNumber.push_back(i) ; 
			CardFace.push_back ( CardFaceArray[i] ) ;
			CardValue.push_back ( CardValueArray[i] ) ;
		}
	}

	// returns a random number between 0 and 51
	int BlackJack::RNG () 
	{
		int x = rand() % 52 ;
		return x ; 
	}

	// uses random number to shuffle deck around
	void BlackJack::ShuffleDeck ()  
	{
		for (int i = 0; i != 52 ; i++)
		{
			int x = RNG() ; 
			swap(CardNumber[i], CardNumber[x]) ;
		}
	}

	// this is seperate just in case 
	int BlackJack::GetZeroCard ()  
	{
		int x = CardNumber.at(0) ; 
		return x ; 
	}

	//gets value of index card at bottom of deck, saves it, the removes that
	// index card from the deck 
	int BlackJack::BotCardReadAndDestory () 
	{
		int x = GetZeroCard () ; 
		int z = CardNumber[x] ; 
		CardNumber.erase (CardNumber.begin() ) ;
		return z ; 
	}

	//deal card to player, push that cards face into one vector
	// and value into another
	void BlackJack::GiveCardPlayer ()
	{		
		int y = BotCardReadAndDestory () ; 
		PlayerHand.push_back ( CardFace[y] ) ;
		PlayerHandValue.push_back ( CardValue[y] ) ;
	}

	//same thing except push into dealers 2 vectors
	void BlackJack::GiveCardDealer ()
	{		
		int y = BotCardReadAndDestory () ; 
		DealerHand.push_back ( CardFace[y] ) ;
		DealerHandValue.push_back ( CardValue[y] ) ;
	}

	// cout each card in players hand
	void BlackJack::DisplayPlayerHand () 
	{
		for(size_t i = 0; i < PlayerHand.size(); i++)
		cout << PlayerHand[i] << " " ;  
	}

	// same for dealer
	void BlackJack::DisplayDealerHand ()                                 
	{
		for(size_t i = 0; i < DealerHand.size(); i++)
		cout << DealerHand[i] << " " ;  
	}

	// get aggregate value of cards in players hand.....
	int BlackJack::GetPlayerHandValue () 
	{
		int x = 0 ; 
		for(size_t i = 0; i < PlayerHandValue.size(); i++)
			x += PlayerHandValue[i] ;
		return x ; 
	}
	
	// etc
	int BlackJack::GetDealerHandValue () 
	{
		int x = 0 ; 
		for(size_t i = 0; i < DealerHandValue.size(); i++)
			x += DealerHandValue[i] ;
		return x ; 
	}

	void BlackJack::DisplayPlayerHandValue () 
	{
		int x = 0 ; 
		for(size_t i = 0; i < PlayerHandValue.size(); i++)
			x += PlayerHandValue[i] ;
		cout << x ;  
	}
	
	void BlackJack::DisplayDealerHandValue () 
	{
		int x = 0 ; 
		for(size_t i = 0; i < DealerHandValue.size(); i++)
			x += DealerHandValue[i] ;
		cout << x ; 
	}
	

	void BlackJack::tester ()
	{
		for (size_t y = 0 ; y != 52 ; y++) 
			cout << CardNumber[y] << "  " << CardFace[y] << "   " << CardValue[y] << endl ; 
	}
	
	void BlackJack::PurgeVectors()
	{
		CardFace.clear();
		CardValue.clear();
		CardNumber.clear();
		PlayerHand.clear();
		DealerHand.clear();
		PlayerHandValue.clear();
		DealerHandValue.clear();
	}


it runs but one time it told me i got a value that was out of range or something.
Looking for info on C++ Quote
02-25-2012 , 02:59 PM
Took a quick look and there are some things you can do. I would declare your CardFaceArray, and CardValue array as static variables in the black jack class and initialise them in your implementation file (or after the class if you are using a single file).

I'd also create hand and deck classes. It's best to keep your class abstraction consistent. If you find a class with functions that don't really belong together, refactor it into smaller classes.

Don't store the hand strings for the hands. Rather, store just the integers and use the integers to generate the hand string when you want to print it.

You have errors in your BotCardReadAndDestory:
- GetZeroCard returns the value of the card at the first index
- Then you save the value of the card at the index of the returned card value
- then you destroy the first card in the array

Also, at() and [] both do the same thing for std::vectors. You might want to consider having a fixed array and keeping an integer that stores the index of the next card and simply incrementing it when you deal a card and resetting when you shuffle.

Make a deal function to contain:

Code:
Game.ShuffleDeck(); 
	Game.GiveCardPlayer();
	Game.GiveCardPlayer();
	Game.GiveCardDealer();
	Game.GiveCardDealer();

You don't need to purge your vectors. STL vectors automatically manage their own memory. When main() is out of scope, your BlackJack class object is destructed. When it is destructed all the member objects' destructors are also called (if you have a pointer to an item that you created with new or malloc you will have to destruct the object manually). I'd suggest reading up on Constructors and destructors.

Also, you can do this:

Code:
int BlackJack::RNG () 
	{
		return rand() % 52 ;
	}
instead of this

Code:
int BlackJack::RNG () 
	{
		int x = rand() % 52 ;
		return x ; 
	}
Looking for info on C++ Quote
02-25-2012 , 03:06 PM
Quote:
Originally Posted by skier_5
Also, you can do this:

Code:
int BlackJack::RNG () 
	{
		return rand() % 52 ;
	}
instead of this

Code:
int BlackJack::RNG () 
	{
		int x = rand() % 52 ;
		return x ; 
	}
I never do expressions in the return. When I'm debugging I want to be able to look at the result of the expression without jumping out of the function. So I can "set next statement", etc.
Looking for info on C++ Quote
02-25-2012 , 03:27 PM
I think you are moving in the right direction, but having it all in one class I think make it more complex than it needs to be. It makes sense as mentioned above, to have for example a Card class, a Cardstack class (that can be either the deck or a hand) and a Player class. And maybe some other things too
Looking for info on C++ Quote
02-25-2012 , 04:14 PM
Quote:
Originally Posted by Ryanb9
Okay I gave OOP a shot and I have to say I like it a lot. But I wanted to check up with you guys before I got into the grunt work of actually making the pieces come together.

...
You're on the right track. Right now, you're using the huge BlackJack class to contain all the functionality and data of your program, which doesn't really take advantage of an OOP design. Classes are meant to represent distinct things, like a Player or Dealer, or a Card or Deck. The idea of Blackjack contains all of those things, but we can use what is known as composition to have a Blackjack class that contains other class objects.

Imagine we defined the Deck and Card structs I gave earlier. Each Card object is responsible for one thing, representing a suit and a value (rank). Each Deck object is reponsible for one thing, representing an actual deck and all the functionality that you can correspond with an actual deck of cards, like dealing a card and shuffling the deck. And the way we've chosen to represent the deck, we can keep a single Deck object around for as many games as we like, with as many players as we like, because it always has 52 cards, and reshuffles itself whenever all 52 cards have been dealt.

We then have the idea of a Player, who represents someone sitting at a Blackjack table, who is dealt 2 cards, and can perform actions like betting, hitting/standing/splitting/doubling etc. We can create a very simple Player class to emulate your actions like this:

Code:
const std::string Suits[] = {"s", "h", "d", "c"};
const std::string Ranks[] = {"A", "2", "3", "4", "5", "6", "7",
				 "8", "9", "T", "J", "Q", "K"};

struct Card { ... };
struct Deck { ... };

class Player
{
public:
	Player( Deck &d ) // we have to use pass by reference to share the same Deck
		: deck(d) // reference member variables have to be initialized here
	{
		points = 0;
		hit();
		hit();
	}
	
	string display() {
		string handStr;
		for( int i = 0; i < cards.size(); i++ )
			handStr += Ranks[cards[i].rank] + Suits[cards[i].suit] + " ";
		return handStr;
	}
	
	void hit() { // note we're not treating the variable value of an ace here properly
		Card card = deck.deal();
		points += card.rank < 9 ? card.rank + 1 : 10; // ternary ?: operator
		cards.push_back(card);
	}
	
	int pointCount() {
		return points;
	}
	
private:
	Deck &deck;
	vector<Card> cards;
	int points;
};
Everything your BlackJack class does can be done in main(), like so:

Code:
int main() {
	srand((unsigned)time(0));
	Deck deck;	// one deck to share
	Player playerOne(deck); // we pass each Player object the same deck
	Player dealer(deck);
	
	cout << "Your hand is " << playerOne.display() << "value is "
		 << playerOne.pointCount() << "\n";
	cout << "Dealer hand is " << dealer.display() << "value is "
		 << dealer.pointCount() << "\n";
	cout << "Dealing you another card...\n";
	playerOne.hit();
	cout << "Your hand is " << playerOne.display() << "value is "
		 << playerOne.pointCount() << "\n";
	
	return 0;
}
So we made a class to represent a player at the table, whose only parameter is a reference to a deck object. From there, the player is automatically dealt two cards and his point count determined. We can request another card with hit(), which automatically updates his point count, and we can ask for a string representing the current cards in his hand with display(). Hopefully you can see how we can add other functionality, like adding functions for betting, doubling, and splitting (here we could add another vector of cards data member called vector<Card> splitCards).

The main idea is that the Player class should be as isolated from actual game mechanics as possible, only performing those actions that any abstract player can perform in a game of Blackjack. We can leave that to a new Blackjack class that can do things like instantiate a deck object (that can be used for all subsequent games), run a game with an artibtrary number of players, etc.

Last edited by weevil; 02-25-2012 at 04:27 PM.
Looking for info on C++ Quote
02-25-2012 , 09:41 PM
Quote:
Originally Posted by skier_5
Took a quick look and there are some things you can do. I would declare your CardFaceArray, and CardValue array as static variables in the black jack class and initialise them in your implementation file (or after the class if you are using a single file).
I would too but apparently you cant or at least I cant or at least its hard as ****. I spent 2 hours yesterday trying to do that.

Quote:
Originally Posted by skier_5
You have errors in your BotCardReadAndDestory:
- GetZeroCard returns the value of the card at the first index
- Then you save the value of the card at the index of the returned card value
- then you destroy the first card in the array
It is supposed to be like that its probably just confusing. I am not using a real deck im using a fake deck of n 0 - 51. i know that 0 is Ah which has a value of 11, and 51 = Kc which has a value of 10, etc because my other 2 vectors are in matching order.
Looking for info on C++ Quote
02-26-2012 , 04:32 AM
Quote:
Originally Posted by Ryanb9
It is supposed to be like that its probably just confusing. I am not using a real deck im using a fake deck of n 0 - 51. i know that 0 is Ah which has a value of 11, and 51 = Kc which has a value of 10, etc because my other 2 vectors are in matching order.
Nevermind, the above quoted is wrong, the guy quoted in the above quoted is right, and his suggestion sounds like a good one xD After enough "random" errors I came back and re-read what you said and now I see what you mean.
Looking for info on C++ Quote
02-27-2012 , 04:07 AM
Quote:
Originally Posted by Chips Ahoy
I never do expressions in the return. When I'm debugging I want to be able to look at the result of the expression without jumping out of the function. So I can "set next statement", etc.
That's a good point, and now that you mention it, I have modified some one line functions just for that reason.

Quote:
Originally Posted by Ryanb9
I would too but apparently you cant or at least I cant or at least its hard as ****. I spent 2 hours yesterday trying to do that.
.

It's a bit counterintuitive, but you have to do it like this:

Code:
class foo {
static const int card[52];
};
And then in your implementation (.cpp) file (you can put it right below your class declaration, but in multi file projects you will get linker errors):

Code:
const int foo::card[52] = { 0, 1, 2.....51};
Looking for info on C++ Quote
02-29-2012 , 04:19 PM
I have a couple more questions xD I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that? Is Java objectively "better" in that particular aspect?

Second, is heap vs stack a big deal? When / why would you choose stack over heap?
Looking for info on C++ Quote
02-29-2012 , 04:43 PM
Quote:
Originally Posted by Ryanb9
I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that?
It's not strictly true. In Java, there are primitive types (e.g. int, char, float, etc.), which are always passed by value. Then there are object types, which you could say are passed by reference (it would be more correct to say that references to objects are passed by value). This results in a system that is easy to use and usually works the way you would expect it to work.

By contrast, C++ gives you lots of ways to pass parameters. You can pass both primitives and objects by value, reference, pointer, or in C++11, by rvalue reference. This gives you a lot more fine-grained control over the system, at the expense of being more complex. Although passing by reference isn't much harder than passing by value. ("void myFunction(int& x)" vs "void myFunction(int x)").

Quote:
Is Java objectively "better" in that particular aspect?
No. It is less complex and therefore easier, but also gives you less control. It's a tradeoff.

Quote:
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
The heap is for large memory allocations, or for when you need to pass objects between different scopes. Stack-allocated objects are destroyed when they go out of scope (e.g. in a function, if you allocate a local variable on the stack, it will be destroyed once the function returns.) By contrast, if you create an object on the heap, it will still be there when the function returns.
Looking for info on C++ Quote
02-29-2012 , 05:54 PM
In addition, if you do put them on the heap you have to do your own garbage collection
Looking for info on C++ Quote
02-29-2012 , 07:03 PM
Quote:
Originally Posted by Ryanb9
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
Another reason to use heap (aka dynamic) allocation is to enable polymorphism. When a function in a base class is declared virtual, you can use a pointer of the base class type to an object of a derived class and any calls to that virtual function will call the derived class function.

The usual example is something like a base class Shape, with derived classes Circle, Square, Triangle etc. You declare the function Shape.draw() to be virtual, and have a bunch of pointers of type Shape pointing to various derived objects, like so:

Shape s; // base object
Shape *shapePtr = &s; // base pointer to base object
shapePtr->draw(); // calls Shape::draw()

Triangle t; // derived object
shapePtr = &t; // base pointer to derived object
shapePtr->draw(); // calls Triangle::draw()

Circle c; // another derived object
shapePtr = &c; // base pointer to another derived object
shapePtr->draw() // calls Circle::draw()

We can have a collection of Shape pointers to circles, squares and triangles and C++ can call the right function at run-time.

EDIT: rofl, ignore that. These are still stack objects we're pointing to. Pointers don't have to point to dynamic memory! But usually with polymorphism you'll be dealing with objects passed between scopes, in which case they'd need to be heap objects. So maybe I'm not entirely off-point...

Last edited by weevil; 02-29-2012 at 07:10 PM.
Looking for info on C++ Quote
03-01-2012 , 04:52 AM
Quote:
Originally Posted by sards
(it would be more correct to say that references to objects are passed by value).
How can this statement be falsified?
Looking for info on C++ Quote
03-01-2012 , 09:20 AM
Quote:
Originally Posted by Ryanb9
I have a couple more questions xD I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that? Is Java objectively "better" in that particular aspect?

Second, is heap vs stack a big deal? When / why would you choose stack over heap?
In Java when you create an object:

Object o;
o = new Object();

Line 1 creates a reference variable of type Object. A reference variable is like a pointer in C++. It typically requires 4 bytes (or 8 bytes on 64-bit systems) since it just holds an address. o is also stored on the stack.

Line 2 creates the actual object and saves its memory location in the variable o. The object is created on the heap.

When o goes out of scope the variable (created on the stack) is destroyed. However the actual Object is not destroyed until the Java garbage collector cleans it up (it realizes that no reference variables point to the object, so it is deleted).

In C++ you achieve the same thing with the notation

Object* o;
o = new Object(); // created on heap in c++

The main difference is that when o goes out of scope the created object is not automatically deleted. You must explicitly call the delete operator

delete o; // now object is deleted from heap

In C++ you can also create objects on the stack (this is not possible in Java). You simply use the notation:

Object o; // actually calls the default constructor for Object in C++, object created on stack

Java eliminated these alternative options for simplicity and other design considerations. C++ was designed for performance and flexibility.

Accessing heap objects is generally slower than accessing stack objects. However the stack is much smaller so you don't want to create giant arrays of objects on the stack (in C++).
Looking for info on C++ Quote
03-01-2012 , 04:32 PM
Quote:
Originally Posted by Ryanb9
How can this statement be falsified?
In C++, the default is to pass by value:
Code:
void swap(int a, int b)
{
  int temp = a;
  a = b;
  b = temp;
}

int main()
{
  int x = 5;
  int y = 9;
  swap(x, y); 
  cout << x << endl; // prints "5"
  cout << y << endl; // prints "9"
}
In the above example, the values of x and y don't get changed because they were passed by value, so swap() was operating on copies of their values. If you want swap() to work, you have to pass by reference:
Code:
void swap(int& a, int& b)
{
  int temp = a;
  a = b;
  b = temp;
}

int main()
{
  int x = 5;
  int y = 9;
  swap(x, y); 
  cout << x << endl; // prints "9:
  cout << y << endl; // prints "5"
}
In that example, copies of x and y aren't made; a and b are just references to x and y. Now, pointers are also passed by value:
Code:
void swap(int* a, int* b)
{
  int* temp = a;
  a = b;
  b = temp;
}

int main()
{
  int m = 5;
  int n = 9;
  int* x = &m; // x is a pointer holding the memory address of m
  int* y = &n; // y holds the address of n
  cout << *x << endl; // prints "5"
  cout << *y << endl; // prints "9"
  swap(x, y); 
  cout << *x << endl; // still prints "5"
  cout << *y << endl; // still prints "9"
}
As you can see, the pointers x and y didn't get swapped. They were passed by value. Copies of the pointers x and y were made and passed to swap(). Note: no copies of m and n, the data that the pointers point to, are made. In order to get swap() to work, you have to do this:
Code:
void swap(int*& a, int*& b) // note the difference here
{
  int* temp = a;
  a = b;
  b = temp;
}

int main()
{
  int m = 5;
  int n = 9;
  int* x = &m; // x is a pointer holding the memory address of m
  int* y = &n; // y holds the address of n
  cout << *x << endl; // prints "5"
  cout << *y << endl; // prints "9"
  swap(x, y); 
  cout << *x << endl; // now prints "9"
  cout << *y << endl; // now prints "5"
}
So in Java, object references are equivalent to C++ pointers. And they are always passed by value, as the pointers are in my third C++ example. So hopefully now you understand what I mean when I say that in Java, references are passed by value.
Looking for info on C++ Quote

      
m