|
-
August 14th, 2002, 01:17 PM
#1
Simple question (involving rand() i think)
I'm making a black jack program as an excersize (mostly in structures and such) and i'm having a problem with the deal() method.
the problem seems to be that a) the random number seems to be 13 all the time ('k' is the output twice) and after i enter anything for the cin, it gives me a bus error and quits. any ideas?
(the player struct has a few ints (money, bet) and the name and hand (a 2-element array) for the player.)
this is the code for that method:
void deal(person player)
{
int i;
char askhit[3];
cout<<"You got: ";
for(i = 0; i < 3; i++) {
player.hand[i] = (rand()%13 + 1);
if (player.hand[i] == 11) player.hand[i] = 'j';
if (player.hand[i] == 12) player.hand[i] = 'q';
if (player.hand[i] == 13) player.hand[i] = 'k';
cout<<player.hand[i]<<" ";
}
cout<<endl;
do {
cout<<"Would you like to hit?"<<endl;
cin>>askhit>>endl;
if (askhit[0] == 'y' || askhit[0] == 'Y') hit(player);
} while (askhit[0] == 'y' || askhit[0] == 'Y');
}
-
August 14th, 2002, 01:30 PM
#2
What kind of data type is hand? You are assign hand with an integer and assign it a character.
Kuphryn
-
August 14th, 2002, 01:37 PM
#3
char hand[2];
can't chars hold ints and characters?
katy
-
August 14th, 2002, 04:37 PM
#4
No, a character cannot be an integer. An array of characters can be "13," but you will need a function like atoi() to convert it to an integer 13.
In your algorithm, use a temp integer to hold the random number.
Kuphryn
-
August 14th, 2002, 07:29 PM
#5
oh, ok... so what should i do to convert only the digits 11-13 to the chars 'j, q, k' respectively (or 'jack, queen, king' if it doesn't make much difference)?
-
August 14th, 2002, 07:49 PM
#6
I made some changes to your algorithm.
-----
void deal(person player)
{
int randNum = 0;
char askhit[3];
cout<<"You got: ";
for(int i = 0; i < 3; ++i)
{
// I assume you want random [1, 13]
randNum = static_cast<int>(((static_cast<double>(rand())) / (static_cast<double>(RAND_MAX + 1))) * 13 + 1);
if (randNum == 11)
player.hand[i] = 'j';
if (randNum == 12)
player.hand[i] = 'q';
if (randNum == 13)
player.hand[i] = 'k';
cout<<player.hand[i]<<" ";
}
-----
Kuphryn
-
August 15th, 2002, 04:33 AM
#7
A character can hold an integer: a signed char can hold a value in the range -128..+127 and an unsigned char can hold a value in the range 0..255. Where your code goes wrong is that you use 'j', 'q' and 'k' for the court cards, but you don't use '1', '2', etc for the others. In ASCII coding, the character '1' has the value 49, '2' has the value 50 and so on. So, for consistency your code should read:
Code:
player.hand[i] = (rand()%13 + 1);
if (player.hand[i] == 11)
player.hand[i] = 'j';
else if (player.hand[i] == 12)
player.hand[i] = 'q';
else if (player.hand[i] == 13)
player.hand[i] = 'k';
else if (player.hand[i] == 10)
player.hand[i] = '0'; // Needs a single char representation for "10"
else
player.hand[i] += '0'; // Get character representation of value.
Characters whose values lie between 0 and 31 (in ASCII) are generally not printable characters, so you won't see many of them in your printout (you might get the odd tab character coming out).
The more serious problem is that you say that "hand" is declared as char hand[2], yet you are accessing it in a loop that goes from 0 to 2 - i.e. you're going out of bounds in the array access.
A secondary problem is that you are not modelling a deck of cards: since each card you "deal" is simply a random number between 1 and thirteen, there is no account taken of the loss of a card once it has been "dealt" - e.g. if you deal the king of hearts, then you can't deal it again until the pack has been restored. A better approach may be to model a full deck, then randomise it and just keep picking cards off the top to deal them.
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
August 15th, 2002, 09:03 AM
#8
ok... that code makes sense. and yeah, the deck problem is something i planned to tackle maybe in my second edition of the program. but since you brought it up, how would you suggest i do it? i just started working in C++ so i don't know much about the possibilities for stacks or things like that that would model a real deck.
thanks kuphryn and Graham for your help!
katy
-
August 15th, 2002, 11:09 AM
#9
One way to do it, which conceptually maps well to the real world, is to use std::vector of Cards, which is basically what a deck is.
Code:
enum Suit
{
Hearts,
Diamonds,
Clubs,
Spades
};
struct Card
{
Suit suit;
unsigned int value;
}
typedef std::vector<Card> Deck;
....
Deck deck;
Initialize the deck by filling it with all the cards.
When dealing, pick a random number from the total remaining cards. When it's dealt, remove it from the deck.
Sounds like a fun problem to work on.
Jeff
-
August 15th, 2002, 11:11 AM
#10
Or, even better, initialize the deck and then "shuffle" it, which will randomly reorder it. Then deal off the top.
The closer a solution models the real world the better. Now, you just need free drinks and good buffets...
Jeff
-
August 15th, 2002, 01:43 PM
#11
To add to Jeff's suggestion, use the random_shuffle() algorithm function to shuffle the deck.
Code:
#include <algorithm>
#include <vector>
//...
typedef std::vector<Card> Deck;
using namespace std;
int main()
{
Deck deck(52);
//...Assume it is initialized
random_shuffle(deck.begin(), deck.end()); // Shuffle the cards
}
Regards,
Paul McKenzie
-
August 15th, 2002, 03:42 PM
#12
<B>It is an extremely bad idea to use Paul's random_shuffle() function to shuffle the deck as the OP requested.</B> Actually it is so bad that you are going to lose big money on the bets.
Why? The OP's intend was clearly trying to shuffle the deck in a [B]random and un-predictable</B> way that no one can guess the cards, for the purpose of gaming or gambling. When you use random_shuffle(), the result is quite predictable, causing your opponent to always been able to guess your card and win your money.
There was precedence, a couple of years ago an on-line gambling site so trusted the security of their deck shuffling algorithm that they published the code publicly, the result was it was cracked without a huzzle and every card was completely predictable. It was a true story. The problem was not with the algorithm itself, but with the random number generator.
The rand() function may be useful for statistics purpose. But it is totally useless when it comes to cryptographically secure applications. It's sequence is completely predictable, especially when it has not been seeded. random_shuffle() relies on rand() internally, and hence it is unsafe.
Designing a cryptographically secure application is very difficult. It all boils down to introducing un-predictable elemements into the system, which in physics is called entropy.
It is very hard to obtain entropy on a computer because all computers are deterministic, virtually all methods of collection entropy on a computer involves some sort of highly platform dependent component.
For example, on a PC, you can use the RDTSC to get the current clock count, you can scan the whole memory space to get a checksum, you can measure the accurate time interval between two key strikes, etc. and a good thing to do is hash your data a couple of thousand times before you seed your random number generator. And above all, never use rand() or any thing that relies on rand().
To sum up, I do not see how random_shuffle() in STL has any real usage, except for as some homework assignment for students.
-
August 15th, 2002, 03:48 PM
#13
I suggest people read Counterpane's CryptoGram and other security/cryptography related literatures. Very few people know any thing at all about concepts in the cryptography field, that is a big problem today when the IT is more and more vulnerable to information technology security flaws.
http://www.counterpane.com/crypto-gram.html
-
August 15th, 2002, 03:53 PM
#14
Most uses of random numbers don't need to be secure. Usually you just want a decent distribution of results
Case in point is the OP, which is a game. This is a perfectly good use for rand(). Unless this is going to be used for actually gambling for cash, it satisfies all the needs of a game.
But true, coming up with good random numbers is difficult, which can be seen by the large range of available pseudo-random number generators. Even with these, it is very important (and difficult) to pick a good starting value.
But in this case, rand() is completely suitable, as is random_shuffle<>.
Jeff
-
August 15th, 2002, 04:02 PM
#15
Furthermore, random_shuffle can take a predicate argument, so you don't need to use rand().
Jeff
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|