Dice Roll
Volume Number: 8
Issue Number: 2
Column Tag: Getting Started
A Role of the Dice
Traditional C programming vs. Macintosh C programming
By Dave Mark, MacTutor Regular Contributing Author
About the author
Dave Mark is an accomplished Macintosh author and an Apple Partner. He is the
author of The Macintosh Programming Primer Series which includes: Macintosh C
Programming Primer, Volumes 1 and 2; Macintosh Pascal Programming Primer,
Volume 1, and his latest book, Learn C on the Macintosh. These books are available
through the MacTutor Mail Order Store located in the back of the magazine. Dave is also
the “professor” on the Learn Programming Forum on CompuServe. To get there, type
GO MACDEV, then check out section 11.
Last month, we discussed Macintosh development economics in an article
entitled, “Getting the best rate on an adjustable, MPW/Inside Macintosh, jumbo
mortgage”. This month, we’re going to build two programs, each of which tackles the
same task. The first uses the traditional, character-based approach typical of a PC or
Unix-based environment. The second program solves the same problem using an
approach that is pure Macintosh. Get your Mac fired up, and let’s get started.
The Environment
Since we’re going to be coding together, I thought I’d pass along some specifics
about my development environment. All the code presented in this column was developed
and tested in this environment. I’m using a Mac IIci with 8 MB of RAM and a Daystar
Digital FastCache card. I’m running THINK C 5.0, and ResEdit 2.1.1. The whole shooting
match runs under System 7, with 32-bit mode turned on.
GenericDice: Proof That Math Really Works!
Our first application, GenericDice, rolls a pair of simulated dice 1000 times,
displaying the results in THINK C’s console window (Figure 1). The results are listed
in 11 rows, one for each possible roll of the dice. The first row shows the number of
rolls that total 2, the second row shows the number of rolls that total 3, etc. The x’s to
the right of each roll count show the roll count graphically. Each x represents 10 rolls.
Figure 1: GenericDice in action.
For example, of the 1000 rolls in Figure 1, 31 had a total of 2, 48 had a total of
3, 88 had a total of 4, etc. Notice the bell-shaped curve formed by the x’s. You
math-hounds out there should recognize a normal distribution from your probability
and statistics days.
Creating the GenericDice Project
Launch THINK C, creating a new project called GenericDice.π (The π character
is created by typing option-p). THINK C will create a project window with the title
GenericDice.π. The project window (and the project file it represents) acts as a
miniature database, tying together all the source code and library files that make up
your project.
Select New from the File menu to create a new source code window. Type the
following source code into the window:
/* 1 */
#include
#include
#include
short RollOne( void );
void PrintRolls( short rolls[] );
void PrintX( short howMany );
main()
{
short rolls[ 11 ], twoDice, i;
srand( clock() );
for ( i=0; i<11; i++ )
rolls[ i ] = 0;
for ( i=1; i <= 1000; i++ )
{
twoDice = RollOne() + RollOne();
++ rolls[ twoDice - 2 ];
}
PrintRolls( rolls );
}
/****************** RollOne ************/
short RollOne( void )
{
long rawResult;
short roll;
rawResult = rand();
roll = (rawResult * 6) / 32768;
return( roll + 1 );
}
/****************** PrintRolls ************/
void PrintRolls( short rolls[] )
{
short i;
for ( i=0; i<11; i++ )
{
printf( "%3d ", rolls[ i ] );
PrintX( rolls[ i ] / 10 );
printf( "\n" );
}
}
/****************** PrintX ************/
void PrintX( short howMany )
{
short i;
for ( i=0; i
printf( "x" );
}
Select Save from the File menu and save the source code under the name
GenericDice.c. Next, select Add (not Add...) from the Source menu to add GenericDice.c to
the project. Finally, select Add... from the Source menu to add the ANSI library to the
project. You’ll find ANSI inside your Development folder, inside the THINK C Folder,
inside the C Libraries folder. ANSI contains the standard C routines defined by the ANSI
C standard. ANSI contains such routines as printf(), getchar(), and strcpy().
Figure 2: The GenericDice project window, before compilation.
Once ANSI has been added to your project, your project window should look like
the one shown in Figure 2. The number to the right of each of the two files indicates the
size of the object code associated with each file. Since GenericDice.c hasn’t been
compiled yet and ANSI hasn’t been loaded, both files have an object size of 0.
Running GenericDice.π
Select Run from the Project menu, asking THINK C to compile and run your
project. If you run into any compile or link errors, check the code over carefully. Once
your project runs, you should see something similar to Figure 1. Since GenericDice
uses a random number generator to roll its dice, the numbers will change each time you
run the program.
Walking Through the Source Code
GenericDice consists of four routines, main(), RollOne(), PrintRolls(), and
PrintX(). GenericDice.c starts off by including , , and . These
three files contain the prototypes and constants needed to access the ANSI library
functions printf(), srand(), and clock().
/* 2 */
#include
#include
#include
The ANSI library is one of the reasons for C’s tremendous success. As evidenced
by this program, as long as a program is restricted to the functions that make up the
program itself, as well as functions in the standard libraries, the program will
recompile and run under any ANSI-compliant C environment.
Next come the function prototypes:
/* 3 */
short RollOne( void );
void PrintRolls( short rolls[] );
void PrintX( short howMany );
main() starts by initializing the standard ANSI random number generator. The
random number generator’s seed is based on the time returned by clock().
/* 4 */
main()
{
short rolls[ 11 ], twoDice, i;
srand( clock() );
Next, the array rolls is iniatialized to 0. rolls consists of 11 shorts, one for each
possible two-dice total. rolls[ 0 ] holds the number of 2’s rolled. rolls[ 1 ] holds the
number of 3’s rolled. You get the idea.
/* 5 */
for ( i=0; i<11; i++ )