3 Replies - 1382 Views - Last Post: 30 September 2011 - 08:42 PM Rate Topic: -----

#1 BISHDP  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 30-September 11

C++ without fear Card Dealer question

Posted 30 September 2011 - 04:52 PM

I am just starting to learn C++ and I started with the book, C++ without fear. So far I am doing well and understanding what the writer is teaching but then I ran into the card dealer. Nothing to hard to understand until he adds in the array to ensure that no card was picked twice. I know that it works but I am unclear on HOW and WHY it works. As far as I can understand, the code simply passes a location in the array and that's all. I cannot figure out where the program is told what to do at the location, that is, check for 1's and skip them. Can someone please help me understand how this works. I do not want to continue on with the book without understanding this. Thank you.

Code:
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
using namespace std;

int rand_0toN1(int n);
void draw_a_card();
int select_next_available(int n);

char *suits[4] = {"Hearts", "Spades", "Clubs", "Diamonds"};
char *ranks[13] = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
	"Nine", "Ten", "Jack", "Queen", "King"};
int card_drawn[52];
int cards_remaining = 52;

int main() {
	int n, i;

	srand(time(NULL));

	while(1) {
		cout << "Enter number of cards to draw (0 to Exit)";
		cin >> n;
		if (n == 0)
			break;
		for (i =1; i <= n; i++)
			draw_a_card();
	}
	return 0;
}

void draw_a_card() {
	int r, s, n, card;

	if (cards_remaining == 0) {
		cout << "Reshuffling." << endl;
		cards_remaining = 52;
		for (int i = 0; i < 52; i++)
			card_drawn[i] = false;
	}

	n = rand_0toN1(cards_remaining--);
	card = select_next_available(n);

	r = card % 13;
	s = card / 13;
	cout << ranks[r] << " of " << suits[s] << endl;
}

int select_next_available(int n) {
	int i = -1;

	n++;

	while (card_drawn[i])
		i++;

	while (n-- > 0){
		i++;
		while (card_drawn[i])
			i++;
	}
	card_drawn[i] = true;
	return i;
}

int rand_0toN1(int n) {
	return rand() % n;
}



Is This A Good Question/Topic? 0
  • +

Replies To: C++ without fear Card Dealer question

#2 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5883
  • View blog
  • Posts: 12,765
  • Joined: 16-October 07

Re: C++ without fear Card Dealer question

Posted 30 September 2011 - 06:13 PM

Well, you're consistent.

http://answers.yahoo...28125233AAaV01C
http://cboard.cprogr...r-question.html

After getting this far:
// not needed
// #include "stdafx.h"
#include <iostream>
// wrong and not needed
// #include <math.h>
// fix
// #include <time.h>
#include <cstdlib>
#include <ctime>



I decided to give the author the benefit of the doubt. The program appears to be dealer3.cpp:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;
int rand_0toN1(int n);
void draw_a_card();
int select_next_available(int n);
bool card_drawn[52];
int cards_remaining = 52;
char *suits[4] =
{"hearts", "diamonds", "spades", "clubs"};
char *ranks[13] = {
	"ace", "two", "three", "four", "five",
	"six", "seven", "eight", "nine",
	"ten", "jack", "queen", "king"
};
int main() {
	int n, i;
	srand(time(NULL));
// Set seed for randomizing.
	while (1) {
		cout << "Enter no. of cards to draw ";
		cout << "(0 to exit): ";
		cin >> n;
		if (n == 0)
			break;
		for (i = 1; i <= n; i++)
			draw_a_card();
	}
	return 0;
}
// Draw-a-card function
// Perform a card draw by getting a random 0-4 and a
// random 0-12. Use these to index the strings
// arrays, ranks and suits.
//
void draw_a_card() {
	int r;
// Random index (0 thru 12) into
// ranks array
	int s;
// Random index (0 thru 3) into
// suits array
	int n, card;
	n = rand_0toN1(cards_remaining--);
	card = select_next_available(n);
	r = card % 13;
// r = random 0 to 12
	s = card / 13;
// s = random 0 to 3
	cout << ranks[r] << " of " << suits[s] << endl;
}
// Select-next-available-card function.
// Find the Nth element of card_drawn, skipping over
// those elements already set to true.
//
int select_next_available(int n) {
	int i = 0;
// At beginning of deck, skip cards already drawn.
	while (card_drawn[i])
		i++;
	while (n-- > 0) {
// Do the following n times:
		i++;
// Advance to next card
		while (card_drawn[i]) // Skip past cards
			i++;
// already drawn.
	}
	card_drawn[i] = true;
// Note card to be drawn
	return i;
// Return this number.
}
// Random 0-to-N1 Function.
// Generate a random integer from 0 to N-1.
//
int rand_0toN1(int n) {
	return rand() % n;
}



First, the book is horrid. It does explain it's examples, so you if you can't follow that much, I don't know what else to say. However, in spite of claiming to be up to date, the code inconsistent and often wrong.

As a card drawing program goes, it's honestly embarrassing that someone is using this as a teaching tool. The code is naive. Most of first year students on this site do a better job. It's not really C++ code...

Here's a quick random deal program I wrote just now. It's C++, offers you a couple of classes you can use in other projects.

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

struct Card {
	static const int SUIT_SIZE = 4;
	static const int FACE_SIZE = 13;

	int value;
	Card() : value(0) { }
	Card(int v) : value(v) { }
	int suit() const { return value / FACE_SIZE; }
	int face() const { return value % FACE_SIZE; }
	const char *suitName() const { 
		static const char *names[SUIT_SIZE] = {"hearts", "diamonds", "spades", "clubs"};
		return names[suit()];
	}
	const char *faceName() const { 
		static const char *names[FACE_SIZE] = { "ace", "two", "three", "four", 
	"five", "six", "seven", "eight", "nine", "ten", "jack", "queen", "king" };
		return names[face()];
	}
	
};

struct Deck {
	static const int DECK_SIZE = 52;
	Card cards[DECK_SIZE];
	int size;
	Deck() : size(DECK_SIZE) { for(int i=0; i<DECK_SIZE; i++) { cards[i] = i; } }
	Card deal() { return cards[--size]; }
	void shuffle() {
		for(int i=size-1; i>0; i--) { 
			int n = rand() % i;
			if (n!=i) {
				Card temp = cards[i];
				cards[i] = cards[n];
				cards[n] = temp;
			}
		}
	}
};

ostream &operator<<(ostream &out, const Card &card) {
	out << card.faceName() << " of " << card.suitName();
}

int main() {
	srand(time(NULL));
	Deck deck;
	deck.shuffle();
	while(deck.size>0) {
		cout << deck.deal() << endl;
	}
	return 0;
}



There are, of course, many ways to do this. You might find others more helpful. Doubtly, most will be better than your book's example.
Was This Post Helpful? 1
  • +
  • -

#3 BISHDP  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 30-September 11

Re: C++ without fear Card Dealer question

Posted 30 September 2011 - 07:42 PM

The first link isn't mine, though it does concern the same part of code. I understand where the n variable is coming from. My question is how does the select_next_available function work? This is my understanding of it, which I know is wrong cause it doesn't make sense. Lets assume that n is 35.

int select_next_available(int n) {
	    int i = 0;
	// At beginning of deck, skip cards already drawn.
	    while (card_drawn[i]) // this seems to be an recursive loop
	        i++;
	    while (35-- > 0) {
	// Do the following n times:
	        i++;
	// Advance to next card
	        while (card_drawn[i]) // Skip past cards, also seems recursive
	            i++;
	// already drawn.
	    }
	    card_drawn[i] = true;
	// Note card to be drawn
	    return i;
	// Return this number.
	}


There also seems to be no place where the actual number is stored as to what card was used. If 35 is generated again, how does it know that it has played that card already? What book would you suggest I look into instead of C++ without Fear?

This post has been edited by BISHDP: 30 September 2011 - 07:45 PM

Was This Post Helpful? 0
  • +
  • -

#4 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1371
  • View blog
  • Posts: 4,750
  • Joined: 19-February 09

Re: C++ without fear Card Dealer question

Posted 30 September 2011 - 08:42 PM

Each playing card has a position in the card_drawn array. The card can be drawn/played (true) or not drawn (false).

int card_drawn[52];



The cards are in a sequence.

card_drawn[0] is the Ace of Hearts
card_drawn[1] is the Two of Hearts
card_drawn[2] is the Three of Hearts
...



With select_next_available. Assuming n is 35.
Thirty-five is the 35th card that hasn't been drawn.
int select_next_available(int n)




If card_drawn is true the cards are skipped.
while (card_drawn[i]) 
  i++;



The index number i is incremented until it is the 35th undrawn card, because numbers are skipped i will be larger than 35 (except the first time when no cards have been drawn).
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1