Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#define NUM_DICE 1
#define NUM_SIDES 2
#define NUM_TARGET 3
#define NUM_TOP 4
#define MAXDICE 100
struct s_die {
int sides;
int value;
};
static int dice_compare(const void *d1, const void *d2);
void usage(void);
void createAndRollDie(struct s_die *d, int sides);
main(int argc, char **argv)
{
int i, j, target = 0, work, numDice = 0, nextParm = 0, topNumToTotal = 0;
int hits = 0, total = 0, topTotal = 0, lastSides = 0;
time_t t;
struct s_die *dice, *p, **sortarray, **s;
int numCurrSides = 6, numCurrDice = 2;
/* Allocate space for up to 100 dice (for simplicity's sake) */
if ((dice = (struct s_die *)malloc(sizeof(struct s_die) * MAXDICE)) == NULL)
{
fprintf(stderr, "Unable to allocate space for dice structures\n");
exit(1);
}
p = dice;
/* Seed random number generator */
time(&t);
srand(t);
/* Parse arguments */
for (i = 1; i < argc; i++)
{
if (*argv[i] == '-')
{
switch(*(argv[i] + 1))
{
case 'n': /* Number of dice */
nextParm = NUM_DICE;
break;
case 's': /* Number of sides */
nextParm = NUM_SIDES;
break;
case 't': /* Target number */
nextParm = NUM_TARGET;
break;
case 'p': /* Total top p dice */
nextParm = NUM_TOP;
break;
default:
fprintf(stderr, "Invalid parameter: %s\n", argv[i]);
usage();
}
}
else
{
switch(nextParm)
{
case NUM_DICE:
numCurrDice = atoi(argv[i]);
numDice += numCurrDice;
if (numDice > MAXDICE)
{
fprintf(stderr, "Maximum of %d dice allowed\n", MAXDICE);
exit(1);
}
for (j = 0; j < numCurrDice; j++)
createAndRollDie(p++, numCurrSides);
break;
case NUM_SIDES:
numCurrSides = atoi(argv[i]); break;
case NUM_TARGET:
target = atoi(argv[i]); break;
case NUM_TOP:
topNumToTotal = atoi(argv[i]); break;
default:
usage();
}
}
}
if (numDice < 1) usage();
/* Allocate array of pointers to sort dice */
if ((sortarray = (struct s_die **)malloc(sizeof(struct s_die *) * numDice)) == NULL)
{
fprintf(stderr, "Unable to allocate space for sort array structures\n");
exit(1);
}
/* Print value of dice and build array for sorting, and calculate target hits */
for (i = 0, p = dice, s = sortarray; i < numDice; i++, p++, s++)
{
*s = p;
if (target > 0 && p->value >= target) hits++;
if (p->sides == lastSides)
printf(", ");
else
{
printf("\nRoll %d-sided dice: ", p->sides);
lastSides = p->sides;
}
printf("%d", p->value);
total += p->value;
}
/* Sort array */
qsort(sortarray, numDice, sizeof(struct s_die *), dice_compare);
/* Get total of top N dice */
if (topNumToTotal > numDice) topNumToTotal = numDice;
for (i = 0, s = sortarray; i < topNumToTotal; i++, s++)
topTotal += (*s)->value;
/* Print totals */
printf("\nTotal of all dice = %d\n", total);
if (topNumToTotal) printf("Total of top %d dice = %d\n", topNumToTotal, topTotal);
if (target) printf("Total dice > %d = %d\n", target, hits);
/* Clean up */
free(sortarray);
free(dice);
return 0;
}
/* Compare function for qsort. Returns are reversed so that sort is in descending order */
static int dice_compare(const void *d1, const void *d2)
{
int v1 = (*(const struct s_die **)d1)->value;
int v2 = (*(const struct s_die **)d2)->value;
if (v1 < v2)
return 1;
else if (v1 > v2)
return -1;
else
return 0;
}
/* Initializes a die structure, and "rolls" the dice using rand() */
void createAndRollDie(struct s_die *d, int sides)
{
d->sides = sides;
d->value = rand() % sides + 1;
}
/* A little help blurb */
void usage()
{
fprintf(stderr, "Usage: dice [-t target] [-p toptotal] [ [-s sides] [-n numdice] ] ...\n\n \
Rolls numdice dice of s sides. Returns number of dice with value at least\n\
target, and total for toptotal dice.\n\
-s and -n can be repeated to roll multiple dice of different sizes.\n\
When -s and -n are used together, put -s first.\n");
exit(1);
}
Bookmarks