
#include < iostream >

#include < algorithm >

#include < functional >

#include < vector >
using namespace std;


#include < cstdlib >

#include < ctime >

#include < cctype >
static char program_name[] = " bd " ;
#define THE_VERSION "0.1"
namespace info {
enum { WEST = 0 ,NORTH = 1 ,EAST = 2 ,SOUTH = 3 ,} ;

} ;
static char * deno[] = { " Spade " , " Heart " , " Diamond " , " Cotton " ,} ;
static char card_symbol[] = " 23456789TJQKA " ;

// p - pointer to argument
// idx - index in argument
// default value
static int 
get_number_arg(
char * p,
int def)

{
if (isdigit( * p))

{

def = atoi(p);

}
return def;

}
static void 
print_help()

{

cout << " Usage: " << program_name << " [OPTION]

" << endl;

cout << " Bridge Dealer " << endl;

cout << " Example: " << program_name << " -p4 " << endl;

cout << endl;

cout << " -p number of players, value ranges from 1 to 4 " << endl;

cout << " \ "" <<program_name<< " \ " with NO option equals \ "" <<program_name<< " - p1\ " " << endl;

cout << " -n number of deals, default \ " 1 \ "" << endl;

cout << " -v,--version print version information and exit " << endl;

cout << " -h,--help display this help and exit " << endl;

cout << endl;

exit( 0 );

}
static void 
print_version()

{

cout << program_name << " version " << THE_VERSION << endl;

exit( 0 );

}
static void 
dump_one_hand(vector <
int > ::iterator ori,
int sps = 0 )

{

vector <
int > ::iterator iter = ori;
for (
int i = 0 ;i <
sizeof (deno) /
sizeof (deno[ 0 ]);i ++ )

{
for (
int j = 0 ;j < sps;j ++ ) cout << " " ;

cout << deno[i][ 0 ] << " : " ;
for (;(iter != ori + 13 ) && ( * iter) / 13 == i;iter ++ )

{

cout << card_symbol[( * iter) % 13 ] << " " ;

}

cout << endl;

}

}
static void 
dump_two_hands(vector <
int > ::iterator o1, vector <
int > ::iterator o2,
int sps = 0 )

{

vector <
int > ::iterator iter1 = o1;

vector <
int > ::iterator iter2 = o2;
int j;
int cnt;
for (
int i = 0 ;i <
sizeof (deno) /
sizeof (deno[ 0 ]);i ++ )

{

cout << deno[i][ 0 ] << " : " ;

cnt = 2 ;
for (;(iter1 != o1 + 13 ) && ( * iter1) / 13 == i;iter1 ++ )

{

cout << card_symbol[( * iter1) % 13 ] << " " ;

cnt = cnt + 2 ;

}
for (j = 0 ;j < sps + sps - cnt;j ++ ) cout << " " ;

cout << deno[i][ 0 ] << " : " ;
for (;(iter2 != o2 + 13 ) && ( * iter2) / 13 == i;iter2 ++ )

{

cout << card_symbol[( * iter2) % 13 ] << " " ;

}

cout << endl;

}

}
// error message routines---------------begin
static char * bs_errors[] =

{

" Unknown option " ,
#define BS_UNKNOWN_OPTION 0

" Too many arguments " ,
#define BS_TOO_MANY_ARGS 1

" Argument missing after " ,
#define BS_ARG_MISSING 2

" Garbage after option " ,
#define BS_GARBAGE 3

" Too many extra commands " ,
#define BS_EXTRA_CMD 4

" Invalid argument for " ,
#define BS_INVALID_ARG 5

} ;
// error message routines---------------end
int 
main(
int argc,
char ** argv)

{
int argv_idx = 1 ;
/* active option letter is argv[0][argv_idx] */
int players = 1 ;
int number_of_deals = 1 ;
bool want_argument =
false ;

while (argc > 0 )

{
if (argv[ 0 ][ 0 ] == ' - ' )

{
char c = argv[ 0 ][argv_idx ++ ];
switch (c)

{
case 0 :
// do nothing
argv_idx =- 1 ;
break ;
case ' - ' :
// "--" don't take any more options
if (strcmp(argv[ 0 ] + argv_idx, " version " ) == 0 ) {

print_version();

}
else if (strcmp(argv[ 0 ] + argv_idx, " help " ) == 0 ) {

print_help();

}

argv_idx =- 1 ;
break ;
case ' h ' :

print_help();
break ;
case ' v ' :

print_version();
break ;
case ' p ' :
// 1,2,3,4 players, default 1
if (argv[ 0 ][argv_idx]) {
// "-p{tag}"
players = get_number_arg(argv[ 0 ] + argv_idx, 1 );

argv_idx =- 1 ;

}
else {
// "-p {tag}"
want_argument =
true ;

}
break ;
case ' n ' :
// number of deals, default 1
if (argv[ 0 ][argv_idx]) {
// "-n{tag}"
number_of_deals = get_number_arg(argv[ 0 ] + argv_idx, 1 );
if (number_of_deals <= 0 ) number_of_deals = 1 ;

argv_idx =- 1 ;

}
else {
// "-n {tag}"
want_argument =
true ;

}
break ;
default :
break ;

}
// handle options with argument
if (want_argument)

{
if (argv[ 0 ][argv_idx]) {

cerr << bs_errors[BS_GARBAGE] << " : \ "" <<argv[0]<< " \ "" << endl;

exit( 1 );

}

-- argc;
if (argc < 1 ) {

cerr << bs_errors[BS_ARG_MISSING] << " : \ "" <<argv[0]<< " \ "" << endl;

exit( 1 );

}

++ argv;

argv_idx = - 1 ;

switch (c)

{
case ' p ' :

players = get_number_arg(argv[ 0 ], 1 );

argv_idx =- 1 ;
break ;
case ' n ' :

number_of_deals = get_number_arg(argv[ 0 ], 1 );
if (number_of_deals <= 0 ) number_of_deals = 1 ;

argv_idx =- 1 ;
break ;
default :

;
// impossible
}

}

}
else {

argv_idx =- 1 ;
// do nothing
}
// If there are no more letters after the current "-", go to next
// argument. argv_idx is set to -1 when the current argument is to be
// skipped.
if (argv_idx <= 0 || argv[ 0 ][argv_idx] == 0 )

{

-- argc;

++ argv;

argv_idx = 1 ;

}

}
// init
srand(time( 0 ));

// original card
// value: spade, 0-12; heart, 13-25; diamond 26-38; cotton 39-51;
// array index: west, 0-12; north, 13-25; east 26-38; south 39-51;
const int dim = 52 ;
int cards[dim];

for (
int i = 0 ;i < dim;i ++ )

{

cards[i] = i;

}

vector <
int > h(dim);

h.assign(cards,cards + dim);

// redeal
bool need_id = number_of_deals > 1 ;
for (
int k = 0 ;k < number_of_deals;k ++ )

{

random_shuffle(h.begin(),h.end());

sort(h.begin() + info::WEST * 13 ,h.begin() + info::WEST * 13 + 13 );

sort(h.begin() + info::NORTH * 13 ,h.begin() + info::NORTH * 13 + 13 );

sort(h.begin() + info::EAST * 13 ,h.begin() + info::EAST * 13 + 13 );

sort(h.begin() + info::SOUTH * 13 ,h.begin() + info::SOUTH * 13 + 13 );

// dump
if (need_id) {

cout << " ID: " << k + 1 << endl;

}
switch (players)

{
case 1 :

dump_one_hand(h.begin() + info::SOUTH * 13 );
break ;
case 2 :

dump_two_hands(h.begin() + info::EAST * 13 ,h.begin() + info::WEST * 13 , 26 );
break ;
case 3 :

dump_one_hand(h.begin() + info::NORTH * 13 , 26 );

dump_one_hand(h.begin() + info::EAST * 13 );

dump_one_hand(h.begin() + info::SOUTH * 13 , 26 );
break ;
case 4 :

dump_one_hand(h.begin() + info::NORTH * 13 , 26 );

dump_two_hands(h.begin() + info::EAST * 13 ,h.begin() + info::WEST * 13 , 26 );

dump_one_hand(h.begin() + info::SOUTH * 13 , 26 );
break ;
default :

;
// impossible
}

cout << endl;

}
return 0 ;

}
