#ifndef RAND_H
#define RAND_H
//** Random number class and Random number pool class. This acts as a
//** replacement for the stdlib rand() function. Why would you want to
//** replace the rand() function? Because you often want a deteriminstic
//** random number generator that is exactly the same regardless of what
//** machine or compiler you build your code on. The stdlib rand() function
//** is not guaraenteed to produce the same results on different stdlib
//** implementations.
//**
//** You can also maintain any number of unique random number generators
//** as state machines by instancing this rand class over and over again.
//**
//** The random number pool is a data structure which you allocate if you
//** want to pull items from a data set, randomly, but without any
//** duplications. A simple example would be a deck of cards. You would
//** instantiate the random number pool as follows:
//**
//** RandPool deck(52);
//**
//** You would then pull cards from the deck as follows:
//**
//** bool shuffled;
//** int card = deck.Get(shuffled);
//**
//** This will return a number between 0-51 (representing a card in the deck)
//** without ever reporting the same card twice until the deck has been
//** exhausted. If the boolean 'shuffled' is true, then the deck was
//** re-shuffled on that call. This data structure has lots of uses in
//** computer games where you want to randomly select data from a fixed
//** pool size.
//**
//** This code submitted to FlipCode.com on July 23, 2000 by John W. Ratcliff
//** It is released into the public domain on the same date.
class Rand
{
public:
Rand(int seed=0)
{
mCurrent = seed;
};
// random number between 0 - 32767
int Get(void)
{
return(((mCurrent = mCurrent * 214013L + 2531011L) >> 16) & 0x7fff);
};
// random number between 0.0 and 1.0
float GetFloat(void)
{
return float(Get())*(1.0f/32767.0f);
};
void Set(int seed)
{
mCurrent = seed;
};
private:
int mCurrent;
};
class RandPool
{
public:
RandPool(int size,int seed) // size of random number pool.
{
mRand.Set(seed); // init random number generator.
mData = new int[size]; // allocate memory for random number pool.
mSize = size;
mTop = mSize;
for (int i=0; i<mSize; i++) mData[i] = i;
}
~RandPool(void)
{
delete mData;
};
// pull a number from the random number pool, will never return the
// same number twice until the 'deck' (pool) has been exhausted.
// Will set the shuffled flag to true if the deck/pool was exhausted
// on this call.
int Get(bool &shuffled)
{
if ( mTop == 0 ) // deck exhausted, shuffle deck.
{
shuffled = true;
mTop = mSize;
}
else
shuffled = false;
int entry = mRand.Get()%mTop;
mTop--;
int ret = mData[entry]; // swap top of pool with entry
mData[entry] = mData[mTop]; // returned
mData[mTop] = ret;
return ret;
};
private:
Rand mRand; // random number generator.
int *mData; // random number bool.
int mSize; // size of random number pool.
int mTop; // current top of the random number pool.
};
#endif
//** Test application demonstrating the usage of these two classes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "rand.h"
static char *suitnames[4] = { "hearts", "clubs", "diamonds", "spades" };
static char *cardnames[13] =
{
"ace",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"jack",
"queen",
"king"
};
void main(int argc,char **argv)
{
RandPool deck(52,0);
printf("Dealing deck of 52 cards.\n");
for (int i=0; i<52; i++)
{
bool shuffled;
int card = deck.Get(shuffled);
int suit = card/13;
card = card%13;
printf("%s of %s\n",cardnames[card],suitnames[suit]);
}
}
|