training

Code I wrote during training
git clone git://git.bitsmanent.org/training
Log | Files | Refs | README

poker.c (16537B)


      1 /* Exercise 7.14 */
      2 
      3 /* Fig. 7.24: fig07_24.c
      4    Card shuffling dealing program */
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <time.h>
      8 
      9 #define CARDS 5
     10 #define DECK 26
     11 #define PLAYERS 2
     12 
     13 /* Points setting *
     14  * NOTE: the points *must* have an offset >= 15 and P_PAIR
     15  *       must should be >= 15 too to works properly. Else,
     16  *       Else, the game will sh0w only INVALID results and
     17  *       wrong winners.
     18  */
     19 #define OFFSET 15 
     20 
     21 /* I'll tweak these, maybe.. a day :-) */
     22 #define P_PAIR 		OFFSET
     23 #define P_DOUBLE	P_PAIR + OFFSET
     24 #define P_TRIS		P_DOUBLE + OFFSET
     25 #define P_SCALE		P_TRIS + OFFSET
     26 #define P_FULL		P_SCALE + OFFSET
     27 #define P_POKER		P_FULL + OFFSET
     28 #define P_COLOR		P_POKER + OFFSET
     29 #define P_SFLUSH	P_COLOR + OFFSET
     30 #define P_RFLUSH	P_SFLUSH + OFFSET
     31 
     32 /* prototypes */
     33 void shuffle( int wDeck[][ 13 ] );
     34 
     35 void deal( int wDeck[][ 13 ], const char *wFace[], const char *wSuit[],
     36            int cards[][CARDS][2], int player, int wCards, int show);
     37 
     38 int getp(int cards[][CARDS][2], int player, const char *wFace[],
     39          const char *wSuit[], int n_cards, int *r_suit, int type[]);
     40 
     41 void order(int a[][CARDS][2], int p, int size);
     42 void rswap(int *a, int *b);
     43 
     44 int chcs(int cards[][CARDS][2], int player, int type[], const char *wFace[], 
     45          const char *wSuit[], int wDeck[][13], int n_cards); 
     46 
     47 int main(void)
     48 {
     49    int i, type[1 + PLAYERS], winner[3] = { 0 }, points[1 + PLAYERS] = { 0 };
     50    int p[1 + PLAYERS][2] = { { 0 } };
     51    int cards[1 + PLAYERS][CARDS][2] = { { { 0 } } };
     52 
     53    /* initialize suit array */
     54    const char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };
     55    
     56    /* initialize face array */
     57    const char *face[ 13 ] = 
     58       { "Ace", "Deuce", "Three", "Four", 
     59         "Five", "Six", "Seven", "Eight",
     60         "Nine", "Ten", "Jack", "Queen", "King" };
     61 
     62    /* initialize deck array */
     63    int deck[ 4 ][ 13 ] = { { 0 } };
     64 
     65    srand( time( 0 ) ); /* seed random-number generator */
     66 
     67    shuffle( deck );
     68 
     69    /* S t a r t */
     70    printf("GaMe STaRTeD!\n\n");
     71    printf("Deck: %d\nCards for player: %d\nNumber of players: %d\n\n\n",
     72       DECK, CARDS, PLAYERS);
     73 
     74    for(i = 0; i < PLAYERS + 1; i++) {
     75       if(!i)
     76          printf("*** Computer is playing..\n");
     77       else
     78          printf("*** Player %d is playing..\n", i);
     79 
     80       printf("-----------------------------------------\n");
     81       deal( deck, face, suit, cards, i, CARDS, !i ? i : 1);
     82 
     83       printf("\n\n");
     84 
     85       /* p[i][0] == points
     86        * p[i][1] == suit of highest card (whitin the highest kind)
     87        * i == the player
     88        * p[0][?] == the computer 
     89        */
     90       p[i][0] = getp(cards, i, face, suit, CARDS, &p[i][1], type);
     91 
     92       printf("\nScore: %d ", p[i][0]);
     93       if(i) printf("(suit points reserved: %d)", 4 - p[i][1]);
     94 
     95       printf("\n");
     96       printf("-----------------------------------------\n");
     97 
     98       /* so */
     99       points[i] = p[i][0] - p[i][1]; /* points - seed(0 highest, 3 lowest) */
    100       printf("\n\n");
    101    }
    102 
    103    /* Changes */
    104 
    105    /* Change the cards, if needed */
    106    if( chcs(cards, 0, type, face, suit, deck, CARDS) ) {
    107       /* If cards are changed */
    108       p[0][0] = getp(cards, 0, face, suit, CARDS, &p[0][1], type);
    109       printf("\n");
    110    }
    111 
    112    /* F i n i s h */
    113 
    114    /* Check the winner and print the classifies */
    115    for(i = 0; i < PLAYERS + 1; i++) {
    116       if(p[i][0] > winner[0]) {
    117 	 winner[0] = p[i][0];
    118 	 winner[1] = p[i][1];
    119 	 winner[3] = i;
    120       }
    121       else if(p[i][0] == winner[0]) { /* Pair: check the suit */ 
    122 	 if(p[i][1] < winner[1]) {
    123 	    winner[0] = p[i][0];
    124 	    winner[1] = p[i][1];
    125 	    winner[3] = i;
    126 	 }
    127       }
    128    } /* end for (i) */
    129 
    130    printf("\n\tC l a s s i f i e s\n\n");
    131    printf("%16s%9s\n", "Player", "Points");
    132    printf("%16s%9d\n", "PC", p[0][0]);
    133    for(i = 1; i < PLAYERS + 1; i++) {
    134       printf("%16d%9d\n", i, p[i][0]);
    135    }
    136    printf("\n");
    137    
    138    if(!winner[3])
    139       printf("* Computer won with %d points.\n", winner[0]);
    140    else
    141       printf("* Player %d won with %d points.\n", winner[3], winner[0]);
    142 
    143    printf("\n");
    144    return 0; /* indicates successful termination */
    145 
    146 } /* end main */
    147 
    148 /* shuffle cards in deck */
    149 void shuffle( int wDeck[][ 13 ] )
    150 {
    151    int row;    /* row number */
    152    int column; /* column number */
    153    int card;   /* counter */
    154 
    155    /* for each of the 52 cards, choose slot of deck randomly */
    156    for ( card = 1; card <= DECK; card++ ) {
    157 
    158       /* choose new random location until unoccupied slot found */
    159       do {
    160          row = rand() % 4;
    161          column = rand() % 13;
    162       } while( wDeck[ row ][ column ] != 0 ); /* end do...while */
    163 
    164       /* place card number in chosen slot of deck */
    165       wDeck[ row ][ column ] = card;
    166    } /* end for */
    167 
    168 } /* end function shuffle */
    169 
    170 /* deal cards in deck */
    171 void deal( int wDeck[][ 13 ], const char *wFace[], const char *wSuit[],
    172            int cards[][CARDS][2], int player, int wCards, int show)
    173 {
    174    int card;   /* card counter */
    175    int row;    /* row counter */
    176    int column; /* column counter */
    177    int i = 0;
    178 
    179    if(show == 2)
    180       printf("==> Computer is changing cards..\n\n");
    181 
    182    /* deal each of the 52 cards */
    183    for ( card = 1; card <= DECK; card++ ) {
    184       /* loop through rows of wDeck */
    185       for ( row = 0; row <= 3; row++ ) {
    186 
    187          /* loop through columns of wDeck for current row */
    188          for ( column = 0; column <= 12; column++ ) {
    189             /* if slot contains current card, display card */
    190             if ( wDeck[ row ][ column ] == card ) {
    191 
    192 	       if(show == 2)
    193 		  printf( "%5s of %-8s => ", wFace[cards[player][i][0]],
    194 	             wSuit[cards[player][i][1]]);
    195 
    196                cards[player][i][0] = column;
    197 	       cards[player][i][1] = row;
    198 
    199 	       if(!show)
    200 	          printf("%15s", " HIDDEN ");
    201 	       else
    202 		  printf( "%5s of %-8s", wFace[ column ], wSuit[ row ]);
    203 
    204 	       ++i;
    205 
    206 	       if(show != 2) printf("%c", !(card % 2) ? '\n' : '\t');
    207 	       else printf("\n");
    208 
    209 	       wDeck[row][column] = 0;
    210 
    211                /* dealing only "wCards" cards */
    212 	       if(i == wCards) {
    213 		  printf("\n");
    214 		  return;
    215 	       }
    216 
    217             } /* end if */
    218 
    219          } /* end for */
    220 
    221       } /* end for */
    222 
    223    } /* end for */
    224 
    225 } /* end function deal */
    226 
    227 /* Get the points of a player */
    228 int getp(int cards[][CARDS][2], int player, const char *wFace[],
    229          const char *wSuit[], int n_cards, int *r_suit, int type[])
    230 {
    231    int i, points;
    232    int scale = 0, n;
    233    int o[13][2] = { { 0 } }; /* occurrences */
    234 
    235 
    236    int kind = 0, face, suit;
    237    /* 0 = nothing
    238     * 1 = Pair 
    239     * 2 = Double
    240     * 3 = Tris
    241     * 4 = scale
    242     * 5 = Full
    243     * 6 = Poker
    244     * 7 = Color
    245     * 8 = straight flush
    246     * 9 = royal flush
    247     */
    248 
    249    /* Inizitialize the o[0,12][1] to 4. Note that 4 is
    250     * a value (random) greather then highest suit (3). */
    251    for(i = 0; i < 13; i++)
    252       o[i][1] = 4;
    253 
    254    /* count the occurrences of each card's face and
    255     * save to the current index the highest suit */
    256    for(i = 0; i < n_cards; i++) {
    257       ++o[cards[player][i][0]][0];
    258 
    259       /* store the index of the highest suit */
    260       if(o[cards[player][i][0]][1] > cards[player][i][1])
    261          o[cards[player][i][0]][1] = cards[player][i][1];
    262 
    263    }
    264 
    265    /* Ok, now don't forget this:
    266     *
    267     * o[i][0] == the occurrences
    268     * o[i][1] == the suit 
    269     * i == the face
    270     */
    271 
    272    /* check if there is a pair/double/tris/full/poker */
    273    for(i = 0; i < 13; i++) {
    274       switch(o[i][0]) {
    275 	 case 2:
    276 	    /* if this is the 1st pair */
    277 	    if(!kind) /* is a pair */
    278 	       kind = 1; 
    279 
    280 	    /* else could be a double */
    281 	    else if(kind == 1)
    282 	       kind = 2;
    283 
    284 	    else /* else is full */
    285 	       kind = 3;
    286 
    287 	    break;
    288 	 case 3:
    289 	    /* If is the current game is a pair */
    290 	    if(kind == 1)
    291 	       kind = 5; /* then become "full" */
    292 
    293 	    else /* else is tris */
    294 	       kind = 3;
    295 
    296 	    break;
    297 	 case 4:
    298 	    /* Oh, this is Poker! :-) */
    299 	    kind = 6;
    300 	    break;
    301 	 default:
    302 	    /* !o[i][0] */
    303 	    ;
    304 
    305       } /* end switch (o[i]) */
    306 
    307       if( o[i][0] > 1 && (kind != 2 || (kind == 2 && face < i)) ) {
    308 	 /* If is double and the current pair is not greather
    309 	  * then previous, then i don't store its face/suit */
    310 
    311          face = i;
    312          suit = o[i][1];
    313       }
    314 
    315    } /* end for (i) */
    316 
    317 
    318    /* Here i've checked: pair, double, tris, full and poker.
    319     * "face" and "suit" contains the highest value of the current
    320     * "kind". The suit is required if there are an "equal" result
    321     * for change (increment or decrement) the current value of
    322     * each one basing on the suit. 
    323     * Missing: scale, color and "all cards are not equals". */
    324 
    325 
    326    /* if all cards are different store the highest of these */
    327    if(kind == 0 && !scale) {
    328       for(i = 0, face = -1; i < n_cards; i++) {
    329 
    330 	 /* search the highest */
    331 	 if((!face ? 13 : face) < (!cards[player][i][0] ? 13 :
    332 	    cards[player][i][0]) ) {
    333 	    face = cards[player][i][0];
    334 	    suit = cards[player][i][1];
    335 	 }
    336 
    337 	 /* if are equal, store the suit */
    338 	 else if(face == cards[player][i][0]) {
    339 	    if(suit < cards[player][i][1]) {
    340 	       suit = cards[player][i][1];
    341 	    }
    342 	 }
    343 	       
    344       }
    345    }
    346 
    347    /* check the color */
    348    for(i = 0, n = 4; i < n_cards; i++) {
    349       if(! (n == 4) ) {
    350          if(cards[player][i][1] != n)
    351             n = - 1;
    352       }
    353       else
    354 	 n = cards[player][i][1];
    355    }
    356    if(n != -1) /* live enjoy: life's colored :-) */
    357       kind = 7;
    358 
    359    /* check the scale / *_flush */
    360    order(cards, player, n_cards);
    361 
    362    for(i = n = 1; i < n_cards; i++) {
    363       if(cards[i - 1][0] + 1 != cards[i][0]) {
    364 	 n = 0;
    365 	 break;
    366       }
    367    }
    368    if(n) { /* This is scale / *_flush */
    369 
    370       if(kind == 7) { /* *_flush */
    371 	 if(face == 0) { /* royal flush */
    372 	    kind = 9;
    373 	 }
    374 
    375 	 else { /* straight flush */
    376             kind = 8;
    377 	 }
    378       }
    379       else { /* just scale */
    380          kind = 4;
    381       }
    382    }
    383 
    384    *r_suit = suit;
    385    type[player] = kind;
    386 
    387    /* Print the kind of game and assign the points */
    388    switch(kind) {
    389       case 0: /* Nothing */
    390 	 printf("All cards are differents!\n"
    391 	        "You could win with the %s of %s\n",
    392 	           wFace[face], wSuit[suit]);
    393 
    394 	 points = face;
    395 	 break;
    396       case 1: /* Pair */
    397 	 printf("Oh, it is a pair of %ss!\n", wFace[face]);
    398 
    399 	 points = P_PAIR + face;
    400 	 break;
    401       case 2: /* Double */
    402 	 printf("Double to %ss\n", wFace[face]);
    403 
    404 	 points = P_DOUBLE + face;
    405 	 break;
    406       case 3: /* Tris */
    407 	 printf("This is tris of %ss!\n", wFace[face]);
    408 
    409 	 points = P_TRIS + face;
    410 	 break;
    411       case 4: /* Scale */
    412 	 printf("Yeah, you have done a scale to %s\n", wFace[face]);
    413 
    414 	 points = P_SCALE + face;
    415 	 break;
    416       case 5: /* Full */
    417 	 printf("*** FULL of %ss!\n", wFace[face]);
    418 
    419 	 points = P_FULL + face;
    420 	 break;
    421       case 6: /* Poker */
    422 	 printf("Wow, it's Poker of %ss!\n", wFace[face]);
    423 
    424 	 points = P_POKER + face;
    425 	 break;
    426       case 7: /* Color */
    427 	 printf("%d points of color (%s)\n", P_COLOR, wSuit[suit]);
    428 
    429 	 points = P_COLOR + face;
    430 	 break;
    431       case 8: /* Straight flush */
    432 	 printf("* Straight flush to %s*\n", wFace[face]);
    433 
    434 	 points = P_SFLUSH + face;
    435 	 break;
    436       case 9: /* Royal flush */
    437 	 printf("*| Royal Flush (%s) |*\n", wSuit[suit]);
    438 
    439 	 points = P_RFLUSH + face;
    440 	 break;
    441       default: /* (?) */
    442 	 printf("### error in function getp()\n");
    443 	 exit(-1);
    444 
    445    } /* end switch(kind) */
    446 
    447    if(!face) points += 13; /* add the Ace's points */
    448 
    449    return points + 1; /* + 1 == [1,13] rather then [0,12] */
    450 } /* eof getp() */
    451 
    452 /* Order an array in descending mode */
    453 void order(int a[][CARDS][2], int p, int size)
    454 {
    455    int i, hold;
    456 
    457    for(i = 1; i < size; i++) {
    458       if(a[p][i - 1][0] > a[p][i][0]) {
    459 	 /* swap the face */
    460 	 hold = a[p][i][0];
    461 	 a[p][i][0] = a[p][i - 1][0];
    462 	 a[p][i - 1][0] = hold;
    463 
    464 	 /* swap the suit */
    465 	 hold = a[p][i][1];
    466 	 a[p][i][1] = a[p][i - 1][1];
    467 	 a[p][i - 1][1] = hold;
    468       }
    469    } /* end for (i) */
    470 
    471 } /* eof order() */
    472 
    473 /* Change the cards if needed, else return 0 */
    474 int chcs(int cards[][CARDS][2], int player, int type[], const char *wFace[],
    475          const char *wSuit[], int wDeck[][13], int n_cards) 
    476 {
    477    int i, ret;
    478 
    479    switch(type[player]) {
    480       case 9: /* Royal flush */
    481       case 8: /* Straight flush */
    482 
    483 	 ret = 0;
    484 	 break;
    485       case 7: /* Color */
    486 	 /* Try to do a Royal flush */
    487 	 ret = 0;
    488 
    489 	 for(i = 0; i < n_cards; i++) {
    490 	    if(cards[player][i][0] + 1 == cards[player][i + 1][0]) {
    491 	       ++ret;
    492 	    }
    493 	 }
    494 
    495          /* if miss only a card to Royal Flush */
    496 	 if(ret == 3) {
    497 	    /* risk: change one card */
    498 
    499 	    if(cards[player][0][0] + 1 == cards[player][1][0]) {
    500 	       rswap(&cards[player][0][0], &cards[player][n_cards - 1][0]);
    501 	       rswap(&cards[player][0][1], &cards[player][n_cards - 1][1]);
    502 	    }
    503 
    504 	    ret = 1;
    505 	 }
    506 	 else /* do nothing */
    507 	    ret = 0;
    508 
    509          break;
    510 
    511       case 5: /* Full */
    512       case 4: /* Scale */
    513 
    514 	 /* Stay */
    515 	 ret = 0;
    516 
    517 	 break;
    518 
    519       case 6: /* Poker */
    520 
    521          /* cards is ordered so the "intruder"
    522 	  * have to be at begin or at end */
    523 
    524 	 if(cards[n_cards - 1][0] != cards[2][0]) {
    525 
    526 	    /* copy [0] to [n_cards - 1] */
    527 
    528 	    /* the face */
    529 	    rswap(&cards[player][n_cards - 1][0], &cards[player][0][0]);
    530 
    531 	    /* the suit */
    532 	    rswap(&cards[player][n_cards - 1][1], &cards[player][0][1]);
    533 	 }
    534 
    535 	 /* else cards[player][n_cards - 1][0] <=> cards[player][2][0] */
    536 	  
    537 	 /* and insert a new card on [0] */
    538 	 deal( wDeck, wFace, wSuit, cards, player, 1, 2);
    539 
    540          ret = 1;
    541 	 break;
    542       case 2: /* Double */
    543 	 /* change 1 card */
    544 
    545          /* cards is ordered so the "intruder"
    546 	  * have to be at begin or at end */
    547 
    548 	  if(cards[player][n_cards - 1][0] != cards[player][5][1] &&
    549 	     cards[player][n_cards - 1][0] != cards[player][3][0]) {
    550 
    551 		/* the face */
    552 		rswap(&cards[player][n_cards - 1][0], &cards[player][0][0]);
    553 
    554 		/* the suit */
    555 		rswap(&cards[player][n_cards - 1][1], &cards[player][0][1]);
    556 	  }
    557 
    558 	  /* else cards[0][0] is already free */
    559 	 deal( wDeck, wFace, wSuit, cards, player, 1, 2);
    560 
    561 	 ret = 1;
    562 	 break;
    563       case 3: /* Tris */
    564          /* change 2 cards */
    565 
    566 	 /* cards is ordered so the "intruderS"
    567 	  * DON'T have to be at middle */
    568 
    569 	 for(i = 0; i < n_cards / 2; i++) {
    570 	    if(cards[i][0] == cards[2][0])
    571 	    break;
    572 	 }
    573 
    574 	 if(!i) {
    575 	    /* the face */
    576 	    rswap(&cards[player][n_cards - 1][0], &cards[player][0][0]);
    577 	    rswap(&cards[player][n_cards - 2][0], &cards[player][1][0]);
    578 
    579             /* the suit */
    580 	    rswap(&cards[player][n_cards - 1][1], &cards[player][0][1]);
    581 	    rswap(&cards[player][n_cards - 2][1], &cards[player][1][1]);
    582 	 }
    583 	 else if(i == 1) {
    584 	    /* the face */
    585 	    rswap(&cards[player][n_cards - 1][0], &cards[player][2][0]);
    586 
    587 	    /* the suit */
    588 	    rswap(&cards[player][n_cards - 1][1], &cards[player][2][1]);
    589 	 }
    590 
    591          /* insert 2 cards on [0] and [1] */
    592 	 deal( wDeck, wFace, wSuit, cards, player, 2, 2);
    593 
    594 	 ret = 2;
    595 	 break;
    596       case 1: /* Pair */
    597 	 /* change 3 cards */
    598 
    599 	 for(i = 0; i < n_cards; i++) {
    600 	    if(cards[player][i][0] == cards[player][i + 1][0])
    601 	       break;
    602 	 }
    603 
    604 
    605 	 /* The face */
    606 	 rswap(&cards[player][n_cards - 1][0], &cards[player][i][0]);
    607 	 rswap(&cards[player][n_cards - 2][0], &cards[player][i+1][0]);
    608 
    609          /* The suit */
    610          rswap(&cards[player][n_cards - 1][1], &cards[player][i][1]);
    611 	 rswap(&cards[player][n_cards - 2][1], &cards[player][i+1][1]);
    612 
    613          deal( wDeck, wFace, wSuit, cards, player, 3, 2);
    614 
    615 	 ret = 3;
    616 	 break;
    617       case 0: /* Nothing */
    618 	 /* Change all cards */
    619 	 ret = 0;
    620 
    621 	 /* If i have a Jack, a Queen, a King or an Ace, hold it */
    622 	 for(i = 0; i < n_cards; i++) {
    623 	    /* 9 == Ten */
    624 	    if( (!cards[player][i][0] ? 13 : cards[player][i][0]) > 9 &&
    625 		(!cards[player][i][0] ? 13 : cards[player][i][0]) > ret) {
    626 		    ret = (!cards[player][i][0] ? 13 : cards[player][i][0]);
    627 
    628 		    rswap(&cards[player][0][0], &cards[player][i][0]);
    629 		    rswap(&cards[player][0][1], &cards[player][i][1]);
    630 	    }
    631 	 }
    632 	 rswap(&cards[player][0][0], &cards[player][n_cards - 1][0]);
    633 	 rswap(&cards[player][0][1], &cards[player][n_cards - 1][1]);
    634 
    635 	 /* else change all cards */
    636 
    637          if(!ret) {
    638 	    deal( wDeck, wFace, wSuit, cards, player, n_cards, 2);
    639 	    ret = n_cards;
    640 	 }
    641 	 else {
    642 	    deal( wDeck, wFace, wSuit, cards, player, n_cards - 1, 2);
    643 	    ret = n_cards - 1;
    644 	 }
    645 
    646 	 break;
    647       default: /* (?) */
    648 	 printf("### error in function chcs()\n");
    649 	 exit(-1);
    650 
    651    } /* end switch (type[player]) */
    652 
    653 
    654    if(ret)
    655       printf("Computer has changed %d %s.\n\n",
    656 	 ret, ret > 1 ? "cards" : "card" );
    657 
    658    return ret;
    659 } /* eof chcs() */
    660 
    661 /* Swap two variable for reference */
    662 void rswap(int *a, int *b)
    663 {
    664    int hold;
    665 
    666    hold = *a;
    667    *a = *b;
    668    *b = hold;
    669 } /* eof rswap() */
    670