Help me choose appropriate data structure

B

bigbang

#include<stdio.h>
#include<assert.h>

#define MAX_CARD 503
#define MAX_CARD_BITMAP 64

typedef unsigned char uint8;
typedef unsigned short int uint16;


typedef struct
{
unsigned char card_bitmap[MAX_CARD_BITMAP];
}LIST;

typedef struct _ABS_CARD_LIST
{
uint16 card;
struct _ABS_CARD_LIST *next;
}ABS_CARD_LIST;

typedef struct _CARD_RANGE
{
uint8 num_ranges;
uint16 *start;
uint16 *end;
}CARD_RANGE;

void init_cards(LIST *list)
{
int i;
for(i=0;i<MAX_CARD_BITMAP;i++)
{
list->card_bitmap = 0;
}
}

void add_card(LIST *list, uint16 card)
{
if(card > MAX_CARD) { assert(0); }
list->card_bitmap[card>>3] |= 1<<(card&7);
}

void add_card_list(LIST *list, ABS_CARD_LIST *card)
{
ABS_CARD_LIST *temp = card;
while(temp)
{
add_card(list, temp->card);
temp = temp->next;
}
}

void add_card_range(LIST *list, CARD_RANGE *range)
{
int i;
uint16 j;
for(i=0;i<range->num_ranges;i++)
{
for(j=range->start;j<range->end;j++)
{
add_card(list, j);
}
}
}


Updated with required typedefs and header files.
Fixed some compile errors.
 
B

bart.c

#define MAX_CARD 503
#define MAX_CARD_BITMAP 64
typedef struct
{
unsigned char card_bitmap[MAX_CARD_BITMAP];
}LIST;

typedef struct _ABS_CARD_LIST
{
uint16 card;
struct _ABS_CARD_LIST *next;
}ABS_CARD_LIST;

typedef struct _CARD_RANGE
{
uint8 num_ranges;
uint16 *start;
uint16 *end;
}CARD_RANGE;

void init_cards(LIST *list)
void add_card(LIST *list, uint16 card)
void add_card_list(LIST *list, ABS_CARD_LIST *card)
void add_card_range(LIST *list, CARD_RANGE *range)

Seems reasonable. Although I would have had the add_card_range() function
add just *one* range:

add_card_range(LIST *list, int first, int last)

Which could save having the complex card range struct type (to represent
multiple ranges, the LIST type does that much better..).
 
K

Keith Thompson

bigbang said:
typedef struct _ABS_CARD_LIST
{
uint16 card;
_ABS_CARD_LIST *next;
}ABS_CARD_LIST;
[...]

The above is legal in C++ but not in C. _ABS_CARD_LIST is a struct
tag; you can refer to the type as "struct _ABS_CARD_LIST", but not
as just "_ABS_CARD_LIST". I suggest you either tell your compiler
to compile C rather than C++, or just admit that you're programming
in C++.

Where is uint16 declared?

Identifiers starting with an underscore and an uppercase letter
(or by another underscore) are reserved for all purposes. To be
safe, avoid declaring any identifiers starting with underscores.

It's conventional to use all-caps names for macros, not for
type names. ("FILE" in <stdio.h> is an exception.)

If you insist on using typedefs for structs, it's not necessary to
use distinct identifiers for the struct tag and the typedef. This
is perfectly legal (assuming uint16 is visible):

typedef struct abs_card_list {
uint16 card;
struct abs_card_list *next;
} abs_card_list;

Or if you prefer to use distinct identifiers (which I understand
can make some things easier in some IDEs), pick a convention other
than a leading underscore:

typedef struct abs_card_list_s {
uint16 card;
struct abs_card_list_s *next;
} abs_card_list;

My own preference is to drop the typedef altogether:

struct abs_card_list {
uint16 card;
struct abs_card_list *next;
};

and just refer to the type as "struct abs_card_list". Why define
a new name for something that already has a perfectly good one?

(The valid counterargument to this last point is that it's annoying
to have to type "struct" every time you refer to the type.)
 
B

Bill Reid

Hi all,
I'm trying to implement some game logic. First i would like to give an
example.
We have 3 different colors of cards. In each color there are 504 cards
(numbered from 0 to 503).
Now each player is given some cards. The cards given to each player
shall be represented by a combination of following
a). Individual card number
b). Range of card numbers.
c) Note: each player will have cards belonging to only one color. one
player cannot have same color cards as another player.
eg. player 1 has : yellow cards (1,3, 20-30,50, 99, 200-310)
     player 2 has : green cards (1-100, 301-305, 499)

I want to implement a structure which can represent the cards each
player has.

typedef struct
{
 T_COLOR color;
 int length; /*length of absolute card numbers */
 int *num;  /* array of standalone numbers, ie not represented by
ranges */
 int num of range; /*length of number of ranges */
 int  *start;  /* indicate start of each range */
 int  *end;   /* indicate end of each range */

}

For example:player 1 has : yellow cards (1,3, 20-30,50, 99, 200-310)
This is represented in the above structure like,
{
 color = YELLOW
 length = 3;
 num  = [1,3,99]
 num_of_range = 2
 start = [20,200]
 end = [30,310]

}

Adding some complexity on top of this is, i should be able to
dyanmically add and remove number of cards to each player. Again this
dynamic input is represented by
eg: Add the following cards for player 1 : Yellow cards (320, 401-419)
     remove the following cards for player 2: green cards (40-50, 301)

I thought of implementing this in bitmaps. But memory is of concern
here (sometimes a player can have only one card, so pre-allocating a
bitmap of size 504 seemed overkill). Can someone comment on the
structure ? Is there a better way to implement these ?
OK, I'll blow over what I did in C++ (ooooh, I know) to
create some generic card game classes for simulations...what's
really important here (at least to me) are the concepts, not the
specific code or language...

Look, for any card game you are going to have the following:

- Cards, or really a deck of cards, which is a set of cards of
certain types, in a particular sequence

- A table, which can have several "spots" on which cards are
"dealt", in a particular sequence

- A "discard" tray where cards wind up after being used for
play, in a particular sequence (note carefully I've used
the term "in a particular sequence" for both the card "deck",
"table", and "discard tray")

- Players, all of whom perform actions according to a
"strategy", which can include a special player called a
"dealer", who performs dealing functions according to
the "game rules"

- Game rules, which govern the flow of the game and how
the cards are dealt and who wins and loses based on their
final hand

So your first job is to code the "deck class" (or
structure, if you prefer to code more slowly and less
extensibly), or REALLY first, the "card class", how
can we distinguish between cards of different types
(color, suit, rank)? Then go ahead and put them in
"new deck order" for your initial "deck class", which
is the "base class" for your "deck", "table", and
"discard tray"...which is nothing more than an array
of pointers to "card" objects, arranged chronologically
or sequentially...

Now skipping ahead of the dealer possibly "washing"
and "shuffling" the "deck", you now need the "game
rules" to cause the dealer to deal the cards in the
deck to the players in a particular sequence. For
a fairly-dealt game (no seconds!) they'll just move
in sequence to the "table", but the "table" sequence
can be broken up into the aforementioned "spots"
where particular sub-sequences of cards are dealt,
and each "spot" is assigned to a "player" according
to the "game rules". A "spot" has a first card
pointer in the table sequence and the number of
cards in the sub-sequence, and yes, for maximum
extensibility you need to have as many "spots" as
there are cards, because a "spot" can only have
one card or maybe the entire "table" of cards, but
remember, a "spot" doesn't contain a lot of data,
just a pointer to the first card of the spot in the
"table" sequence and the number of cards in the "spot",
and of course each pointer in the "table" sequence
eventually points back to specific card in the
"new deck order", which may include a bitmap of
the card.

Now if you've been following all of this, you're
ready to automatically code up all the "classes"
(or whatever). A card "structure" is something
like:

typedef struct card {
unsigned color;
unsigned rank;
unsigned suit;
} t_card;

(Or you might use enumerations for the above, and
include a pointer to a bitmap.) So a "deck" (of
any kind) is simply:

typedef struct deck {
unsigned num_cards;
t_card *cards;
} t_deck;

And then you can "extend" the "deck" to be
a "table" by declaring a "spot" object:

typedef struct spot {
unsigned discarded; /* hmmm, what is this */
unsigned num_cards;
t_card *first_card;
} t_spot;

Then "table" is:

typedef struct table {
unsigned num_cards;
unsigned num_spots;
t_card *cards;
t_spot *spots;
} t_table;

Well, you either get the idea or not...implementing the
functions to "deal" the cards to the "players" on the
"table" according to the "game rules" is left as an
exercise to the reader...
 
F

Fire Crow

If you work it through, you will see that homework is precisely what we
*should* be answering here in this newsgroup.  I just don't see it as a
problem.
[snip]

Let me ask you something, what service do you suppose you're providing
if you do peoples homework and they don't ever learn anything?

Tom

Homework is BS anyway, people will probably learn more from the
responses on this forum than from there assignments anyway.
because the forum responses include perspective, variety, and context.

the main reason is that responses from developers often include a well
formed reason and situation for the given solution.

please, graduates who skip their homework and spend more time
collaboratively exploring, come work at a company near me :)

~fire
(e-mail address removed)
http://firecrow.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,091
Messages
2,570,604
Members
47,224
Latest member
Gwen068088

Latest Threads

Top