Permalink
Browse files

First commit of files

  • Loading branch information...
1 parent 97f0156 commit bd15f283303dfc56dd1a17cfccc70e585d20514f @dblack committed Feb 23, 2011
Showing with 1,062 additions and 0 deletions.
  1. +5 −0 Makefile
  2. +5 −0 README
  3. +112 −0 cards.c
  4. +76 −0 cards.h
  5. +142 −0 hand-comp.c
  6. +273 −0 hand.c
  7. +9 −0 main.c
  8. +21 −0 profile.c
  9. +419 −0 test/cards.c
View
@@ -0,0 +1,5 @@
+tests: test/cards.c
+ gcc -o test/cards cards.c hand.c hand-comp.c profile.c test/cards.c -L/usr/local/lib -lcunit
+
+test: tests
+ test/cards
View
5 README
@@ -0,0 +1,5 @@
+A C-learning project of mine: implementing playing cards and the logic to
+evaluate a poker hand and compare two poker hands. It's a bit of a mashup
+of different ideas on how to evaluate the hands, and isn't a great model of
+a poker algorithm. But the main point is to give me some practice writing and
+unit-testing C.
View
112 cards.c
@@ -0,0 +1,112 @@
+#include "cards.h"
+#include <string.h>
+
+
+/* cards.c -- basic card implementation
+
+Example:
+
+ Card *card1 = create_card("3", "hearts");
+ Card *card2 = create_card("4", "diamonds");
+ Card *card3 = create_card("4", "spades");
+
+ card_eq(card2, card3); // true
+ card_lt(card1, card2); // true
+ card_gt(card2, card1); // true
+
+There's a set_suit and set_rank API:
+
+ set_rank(card1, "K");
+ set_suit(card1, "clubs");
+
+which is useful mainly if you create hands (see hand.c) and
+want to manipulate the cards. (See test/cards.c for examples.)
+
+To free a card:
+
+ Card *card;
+ // ...
+ free_card(card);
+
+*/
+
+char *suits[] = { "clubs", "diamonds", "hearts", "spades" };
+char *ranks[] = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };
+
+static void init_card(Card **cpp) {
+ *cpp = malloc(sizeof(Card));
+ Card *cp = *cpp;
+ cp->rank = NULL;
+ cp->suit = NULL;
+}
+
+Card *create_card(char *rank, char *suit)
+{
+ Card *cp;
+ init_card(&cp);
+ set_rank(cp, rank);
+ set_suit(cp, suit);
+ return cp;
+}
+
+void free_card(Card *cp)
+{
+ free(cp->rank);
+ free(cp->suit);
+ free(cp);
+}
+
+void set_rank(Card *cp, char *rank)
+{
+ cp->rank = realloc(cp->rank, strlen(rank) + 1);
+ strcpy(cp->rank, rank);
+}
+
+void set_suit(Card *cp, char *suit)
+{
+ cp->suit = realloc(cp->suit, strlen(suit) + 1);
+ strcpy(cp->suit, suit);
+}
+
+void pretty_format_card(char *buffer, Card *cp) {
+ sprintf(buffer, "%s of %s", cp->rank, cp->suit);
+}
+
+int card_compare_for_qsort(const void *vp1, const void *vp2)
+{
+ Card *cp1 = *(Card **)vp1;
+ Card *cp2 = *(Card **)vp2;
+ return rank_difference(cp1, cp2);
+}
+
+int card_lt(Card *cp1, Card *cp2)
+{
+ return (rank_difference(cp1, cp2) < 0);
+}
+
+int card_eq(Card *cp1, Card *cp2)
+{
+ return (rank_difference(cp1, cp2) == 0);
+}
+
+int card_gt(Card *cp1, Card *cp2)
+{
+ return (rank_difference(cp1, cp2) > 0);
+}
+
+int rank_difference(Card *cp1, Card *cp2)
+{
+ return index_of_rank(cp1->rank) - index_of_rank(cp2->rank);
+}
+
+int index_of_rank(char *rank)
+{
+ int i;
+ for (i = 0; i < 13; i++) {
+ if (!strcmp(rank, ranks[i])) {
+ return i;
+ }
+ }
+ return -1;
+}
+
View
76 cards.h
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define RANK_N 13;
+
+typedef struct {
+ char *rank;
+ char *suit;
+} Card;
+
+typedef struct {
+ Card **cards;
+ int len;
+ char profile[6];
+} Hand;
+
+typedef struct {
+ int mult;
+ int kickers[4];
+} Mult;
+
+typedef struct {
+ char ranking[20];
+ int(*ranking_function)(Hand *);
+ int(*chooser_function)(Hand *, Hand *);
+} ranking_datum;
+
+typedef int (*ranking_function)(Hand *);
+typedef int (*chooser_function)(Hand *, Hand *);
+
+Hand *sample_hand();
+Hand *empty_hand();
+void free_hand(Hand *);
+void copy_cards(Hand *, Card **);
+int straight_flush_chooser(Hand *, Hand *);
+int fours_chooser(Hand *, Hand *);
+int full_house_chooser(Hand *, Hand *);
+int flush_chooser(Hand *, Hand *);
+int straight_chooser(Hand *, Hand *);
+int trips_chooser(Hand *, Hand *);
+int two_pair_chooser(Hand *, Hand *);
+int pair_chooser(Hand *, Hand *);
+int high_card_chooser(Hand *, Hand *);
+int *rank_hand(Hand *);
+Card *high_card(Hand *hand);
+char *hand_ranking_description(Hand *hand);
+Hand *create_batch_hand(char *info);
+Card *create_card(char *rank, char *suit);
+Hand *create_hand();
+void free_card(Card *cp);
+void free_hand(Hand *hp);
+void set_rank(Card *cp, char *rank);
+void set_suit(Card *cp, char *suit);
+Card *create_card_from_pretty(char *pretty);
+void pretty_format_card(char *, Card *);
+int card_compare_for_qsort(const void *, const void *);
+int card_compare(Card *, Card *);
+int is_5_high_straight(Hand *hand);
+int card_lt(Card *cp1, Card *cp2);
+int card_eq(Card *cp1, Card *cp2);
+int card_gt(Card *cp1, Card *cp2);
+int hand_has_nothing(Hand *hand);
+int hand_has_pair(Hand *hand);
+int hand_has_two_pair(Hand *hand);
+int hand_has_three_of_a_kind(Hand *hand);
+int hand_has_straight(Hand *hand);
+int hand_has_flush(Hand *hand);
+int hand_has_full_house(Hand *hand);
+int hand_has_four_of_a_kind(Hand *hand);
+int hand_has_straight_flush(Hand *hand);
+int rank_difference(Card *cp1, Card *cp2);
+int index_of_rank(char *rank);
+int hand_n_of_a_kinds(Hand *hand, int n);
+int rank_of_multiples(int[], int);
+int highest_unmatched_card(Hand *, int[]);
+int two_pair_hash(Hand *);
View
@@ -0,0 +1,142 @@
+#include "cards.h"
+
+/* The chooser methods. Each method implements logic for choosing between
+ two hands with the same ranking. Pairs, trips, and fours are all
+ handled by multiples_chooser.
+*/
+
+int high_card_chooser(Hand *hand1, Hand *hand2)
+{
+ Card *high1 = high_card(hand1);
+ Card *high2 = high_card(hand2);
+ return index_of_rank(high1->rank) - index_of_rank(high2->rank);
+}
+
+static int high_kickers(int k1[], int k2[], int len)
+{
+ int i, j;
+ for (i = 0; i < len; i++) {
+ j = k1[i] - k2[i];
+ if (j) {
+ return j;
+ }
+ }
+ return 0;
+}
+
+static int multiples_chooser(Hand *hand1, Hand *hand2, int n)
+{
+ int buck1[13], buck2[13], result;
+ Mult *mult1 = malloc(sizeof(Mult));
+ Mult *mult2 = malloc(sizeof(Mult));
+ n_of_a_kind_hash(hand1, mult1, 2);
+ n_of_a_kind_hash(hand2, mult2, 2);
+
+ result = ((mult1->mult - mult2->mult) ||
+ high_kickers(mult1->kickers, mult2->kickers, 3));
+
+ free(mult1);
+ free(mult2);
+
+ return result;
+}
+
+int pair_chooser(Hand *hand1, Hand *hand2)
+{
+ multiples_chooser(hand1, hand2, 2);
+}
+
+int two_pair_chooser(Hand *hand1, Hand *hand2)
+{
+ return two_pair_hash(hand1) - two_pair_hash(hand2);
+}
+
+int trips_chooser(Hand *hand1, Hand *hand2)
+{
+ multiples_chooser(hand1, hand2, 3);
+}
+
+int straight_chooser(Hand *hand1, Hand *hand2)
+{
+ high_card_chooser(hand1, hand2);
+}
+
+int flush_chooser(Hand *hand1, Hand *hand2)
+{
+ high_card_chooser(hand1, hand2);
+}
+
+int full_house_chooser(Hand *hand1, Hand *hand2)
+{
+ int buck1[13], buck2[13];
+ make_rankings_histogram(hand1, buck1);
+ make_rankings_histogram(hand2, buck2);
+ int pair1 = rank_of_multiples(buck1, 2);
+ int trip1 = rank_of_multiples(buck1, 3);
+ int pair2 = rank_of_multiples(buck2, 2);
+ int trip2 = rank_of_multiples(buck2, 3);
+ return (trip1 - trip2) || (pair1 - pair2);
+}
+
+int fours_chooser(Hand *hand1, Hand *hand2)
+{
+ return multiples_chooser(hand1, hand2, 4);
+}
+
+int straight_flush_chooser(Hand *hand1, Hand *hand2)
+{
+ return high_card_chooser(hand1, hand2);
+}
+
+
+/* Helper methods for the chooser logic */
+
+
+/* Finds, e.g., the first occurrence of trips (n = 3) in the rank
+ histogram of a hand.
+*/
+
+int rank_of_multiples(int rank_histogram[], int n)
+{
+ int i;
+ for (i = 0; i < 13; i++) {
+ if (rank_histogram[i] == n) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/* Returns a three-digit hex number indicating the ranks of the high pair,
+ the low pair, and the kicker. This can then be compared across hands to
+ determine a winner between two two-pair hands.
+*/
+
+int two_pair_hash(Hand *hand)
+{
+ int i, hash, high = 0, low, kicker, buckets[13];
+ char num[4];
+
+ make_rankings_histogram(hand, buckets);
+
+ for (i = 12; i >= 0; i--) {
+ if (buckets[i] == 2) {
+ if (high) {
+ low = i;
+ }
+ else {
+ high = i;
+ }
+ }
+ if (buckets[i] == 1) {
+ kicker = i;
+ }
+ }
+
+ sprintf(num, "%x%x%x", high, low, kicker);
+ sscanf(num, "%x", &hash);
+ return hash;
+}
+
+
Oops, something went wrong.

0 comments on commit bd15f28

Please sign in to comment.