From 442a49ad5a48d417345959b903ae6a6d32d55759 Mon Sep 17 00:00:00 2001 From: Haidong Ji Date: Fri, 15 Apr 2022 15:51:30 -0500 Subject: Great C programming fun Excellent fundamentals and displine training, many tools and techniques exercises: gdb, emacs, valgrind, git --- c2prj1_cards/.gitignore | 1 + c2prj1_cards/Makefile | 9 +++ c2prj1_cards/README | 179 ++++++++++++++++++++++++++++++++++++++++++++ c2prj1_cards/cards.c | 131 ++++++++++++++++++++++++++++++++ c2prj1_cards/cards.h | 38 ++++++++++ c2prj1_cards/deck-c4.o | Bin 0 -> 4752 bytes c2prj1_cards/deck.o | Bin 0 -> 4144 bytes c2prj1_cards/eval-c4.o | Bin 0 -> 2504 bytes c2prj1_cards/eval.o | Bin 0 -> 10480 bytes c2prj1_cards/future.o | Bin 0 -> 3216 bytes c2prj1_cards/grade.txt | 25 +++++++ c2prj1_cards/input.o | Bin 0 -> 5504 bytes c2prj1_cards/main.o | Bin 0 -> 5264 bytes c2prj1_cards/my-test-main.c | 5 ++ 14 files changed, 388 insertions(+) create mode 100644 c2prj1_cards/.gitignore create mode 100644 c2prj1_cards/Makefile create mode 100644 c2prj1_cards/README create mode 100644 c2prj1_cards/cards.c create mode 100644 c2prj1_cards/cards.h create mode 100755 c2prj1_cards/deck-c4.o create mode 100644 c2prj1_cards/deck.o create mode 100755 c2prj1_cards/eval-c4.o create mode 100644 c2prj1_cards/eval.o create mode 100644 c2prj1_cards/future.o create mode 100644 c2prj1_cards/grade.txt create mode 100644 c2prj1_cards/input.o create mode 100644 c2prj1_cards/main.o create mode 100644 c2prj1_cards/my-test-main.c (limited to 'c2prj1_cards') diff --git a/c2prj1_cards/.gitignore b/c2prj1_cards/.gitignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/c2prj1_cards/.gitignore @@ -0,0 +1 @@ +test diff --git a/c2prj1_cards/Makefile b/c2prj1_cards/Makefile new file mode 100644 index 0000000..be1c5b4 --- /dev/null +++ b/c2prj1_cards/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-ggdb3 -Wall -Werror -pedantic -std=gnu99 +GIVEN_OBJS=deck.o eval.o future.o input.o main.o eval-c4.o deck-c4.o + +test: cards.o my-test-main.o + gcc -o test -ggdb3 cards.o my-test-main.o +poker: $(GIVEN_OBJS) cards.o + gcc -o poker -ggdb3 cards.o $(GIVEN_OBJS) +clean: + rm test poker cards.o my-test-main.o *~ diff --git a/c2prj1_cards/README b/c2prj1_cards/README new file mode 100644 index 0000000..73848b1 --- /dev/null +++ b/c2prj1_cards/README @@ -0,0 +1,179 @@ +At the end of each course, you will be working on building +a program that estimates the chances of each hand +winning in poker in a situation described by an input file. + +In this portion of the project, you are going write some +functions that work with cards (specifically, a struct +that represents a card): printing them +in human-readable format, converting the pair of letters +that describe a card back into a struct (which gets +used to read the input from a file), etc. + +There is a lot that will be required to complete +the project that you will learn in the later +courses (e.g., arrays, strings, dynamic memory allocation, +file IO). To make it so you can still run the poker +simulation when you complete this project, we have provided +object files (.o) for the later parts. The included +Makefile will build your cards.c with our .o files +if you do: + +make poker + +You'll write all these parts later on, when you +finish Courses 3 and 4 and have learned the +corresponding concepts. + +In the meantime, you can test your functions +for this assignment by writing any code you +want in my-test-main.c. If you do "make" +(or "make test") then the included Makefile +will build this and link it with your cards.o +(compiling that if needed). + +To get started, take a look at cards.h. + +You will see that it starts by defining +an enum suits (SPADES, HEARTS, DIAMONDS, +and CLUBS). This enum also has NUM_SUITS, +which will have a numeric value of 4 (indicating +how many suits there are), and can also +be used to indicate an invalid suit. + +Next, you will see a struct for a card. +This struct has two parts, a value +(2,3,4,5,6,7,8,9,10,J,Q,K,A) and a suit (s,h,d,c). +Following the struct declaration, there +are some #defines for constants for +the values of Ace, King, Queen, and Jack. +Accordingly, a card's value should +be between 2 and 14 (inclusive). + +There is also an enum for the hand +ranking (what kind of poker hand you get). +We won't be doing anything with these +at this point, except for writing a function +to convert from the enumerated values +to a string. + +Last are some function prototypes. +You will write each of these in cards.c. + +Now go into cards.c, and write each of these +functions. Here are the specifics: + +- void assert_card_valid(card_t c); + This function should use assert() to check + that the card passed in has valid values. + In particular, its value should be between + 2 and VALUE_ACE (inclusive of both), + and its suit should be between SPADES + and CLUBS (inclusive of both). + +- const char * ranking_to_string(hand_ranking_t r); + This function should convert the + hand_ranking_t enumerated value passed + in to a string that describes it. Remember + that Drew showed you a nice way to do this + with emacs keyboard macros! + +- char value_letter(card_t c); + This function should return the character that textually represents + the value of the passed-in card. For values 2-9, this should + be that digit. For 10, it should be '0', and for Jack, Queen, King, and Ace, + it should be 'J', 'Q', 'K', and 'A' respectively. + Hint: remember everything is a number. + For example, the character '0' has the decimal value 48, + and the character '5' has the decimal value 53, so you could represent + '5' as '0' + 5. + +- char suit_letter(card_t c); + This function should return the letter that textually represents + the suit of the card passed in ('s', 'h', 'd', or 'c' for SPADES, + HEARTS, DIAMONDS, or CLUBS). + +- void print_card(card_t c); + This function should print out the textual + representation of the card (hint: use the functions + you previously wrote). It should print + the value first, then the suit. For example, + As (for Ace of spades) + 0d (for 10 of diamonds) + Kc (for King of clubs) etc. + This function should not print any additional + spaces or newlines after the card's text. + +- card_t card_from_letters(char value_let, char suit_let); + This function should make and return a + card_t whose value and suit correspond + to the letters passed in. If the values passed + in are invalid, you should use assert() + or print an error message and exit(EXIT_FAILURE). + +- card_t card_from_num(unsigned c); + This function should take a number from 0 (inclusive) + to 52 (exclusive) and map it uniquely to + a card value/suit combination. Exactly + how you map the numbers to values/suits + is up to you, but you must guarantee + that each valid value/suit combination + corresponds to exactly one input value + in the range [0,52). Hint: you may want to use the mod + operator % to find the remainder of a number divided by 13. + (In Course 3, this function will be used + to make a deck of cards by iterating + over that range and calling it once + for each value--you just need + to learn about arrays first so you + have a place to put all those + cards.) + +---------------------------------------------------- +Once you have done all of these (and tested +them to your satisfaction with my-test-main.c), +you can + +make poker + +and try out the poker odds computation. It +requires one command line argument--the input file to read. +In the input file, +each line corresponds to one hand and lists +the cards (with textual representation +you were working with above). It also +has placeholders for future cards, which +are a ? followed by a number. For example, +this input: + +As Ah Kc Qd 6c ?0 ?1 +2c 3d Kc Qd 6c ?0 ?1 +Ks Qs Kc Qd 6c ?0 ?1 + +describes 3 hands (as might occur +in a game of Texas Hold'em). All +three hands share the King of clubs, +the Queen of diamonds, and the 6 +of clubs (called the "flop" +in Texas Hold'em--these are the +3rd, 4th, and 5th cards). Each +hand has its own private cards +to start (the first has the +Ace of Spades and the Ace of Hearts, +for example). + +The remainder of the hand will be +played by dealing two more cards +(?0 and ?1), which will be shared +by the three hands. + +You could also craft an input +where each player's cards are private +(no cards shared), such as this: + +As Kh ?0 ?1 ?2 +Ac Kc ?3 ?4 ?5 +Ad Ah ?6 ?7 ?8 + +9 cards remain in the future (?0 +through ?8), each appearing exactly +once in one hand. diff --git a/c2prj1_cards/cards.c b/c2prj1_cards/cards.c new file mode 100644 index 0000000..c335826 --- /dev/null +++ b/c2prj1_cards/cards.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include "cards.h" + + +void assert_card_valid(card_t c) { + assert(c.value >= 2 && c.value <= VALUE_ACE); + assert(c.suit >= SPADES && c.suit <= CLUBS); +} + +const char * ranking_to_string(hand_ranking_t r) { + switch (r) { + case STRAIGHT_FLUSH: + return "STRAIGHT_FLUSH"; + case FOUR_OF_A_KIND: + return "FOUR_OF_A_KIND"; + case FULL_HOUSE: + return "FULL_HOUSE"; + case FLUSH: + return "FLUSH"; + case STRAIGHT: + return "STRAIGHT"; + case THREE_OF_A_KIND: + return "THREE_OF_A_KIND"; + case TWO_PAIR: + return "TWO_PAIR"; + case PAIR: + return "PAIR"; + default: + return "NOTHING"; + } +} + +char value_letter(card_t c) { + switch(c.value) { + case VALUE_ACE: + return 'A'; + case VALUE_KING: + return 'K'; + case VALUE_QUEEN: + return 'Q'; + case VALUE_JACK: + return 'J'; + case 10: + return '0'; + default: + return '0' + c.value; + } +} + + +char suit_letter(card_t c) { + switch(c.suit) { + case SPADES: + return 's'; + case HEARTS: + return 'h'; + case DIAMONDS: + return 'd'; + default: + return 'c'; + } + +} + +void print_card(card_t c) { + printf("%c%c", value_letter(c), suit_letter(c)); +} + +card_t card_from_letters(char value_let, char suit_let) { + card_t temp; + switch(value_let) { + case 'A': + temp.value = VALUE_ACE; + break; + case 'K': + temp.value = VALUE_KING; + break; + case 'Q': + temp.value = VALUE_QUEEN; + break; + case 'J': + temp.value = VALUE_JACK; + break; + case '0': + temp.value = 10; + break; + default: + temp.value = value_let - '0'; + break; + } + switch(suit_let) { + case 's': + temp.suit = SPADES; + break; + case 'h': + temp.suit = HEARTS; + break; + case 'd': + temp.suit = DIAMONDS; + break; + case 'c': + temp.suit = CLUBS; + break; + } + assert_card_valid(temp); + return temp; +} + +card_t card_from_num(unsigned c) { + card_t temp; + if (c <= 12) { + temp.value = c + 2; + temp.suit = SPADES; + } + else if (c > 12 && c <= 25) { + temp.value = c % 13 + 2; + temp.suit = HEARTS; + } + else if (c > 25 && c <= 38) { + temp.value = c % 13 + 2; + temp.suit = DIAMONDS; + } + else { + temp.value = c % 13 + 2; + temp.suit = CLUBS; + } + assert_card_valid(temp); + return temp; +} diff --git a/c2prj1_cards/cards.h b/c2prj1_cards/cards.h new file mode 100644 index 0000000..fef0529 --- /dev/null +++ b/c2prj1_cards/cards.h @@ -0,0 +1,38 @@ +#ifndef CARD_H +#define CARD_H +#define VALUE_ACE 14 +#define VALUE_KING 13 +#define VALUE_QUEEN 12 +#define VALUE_JACK 11 +typedef enum { + SPADES, + HEARTS, + DIAMONDS, + CLUBS, + NUM_SUITS +} suit_t; + +struct card_tag { + unsigned value; + suit_t suit; +}; +typedef struct card_tag card_t; +typedef enum { + STRAIGHT_FLUSH, + FOUR_OF_A_KIND, + FULL_HOUSE, + FLUSH, + STRAIGHT, + THREE_OF_A_KIND, + TWO_PAIR, + PAIR, + NOTHING +} hand_ranking_t; +card_t card_from_num(unsigned c); +void assert_card_valid(card_t c); +const char * ranking_to_string(hand_ranking_t r) ; +char value_letter(card_t c); +char suit_letter(card_t c) ; +void print_card(card_t c); +card_t card_from_letters(char value_let, char suit_let); +#endif diff --git a/c2prj1_cards/deck-c4.o b/c2prj1_cards/deck-c4.o new file mode 100755 index 0000000..5fc5541 Binary files /dev/null and b/c2prj1_cards/deck-c4.o differ diff --git a/c2prj1_cards/deck.o b/c2prj1_cards/deck.o new file mode 100644 index 0000000..bddad7c Binary files /dev/null and b/c2prj1_cards/deck.o differ diff --git a/c2prj1_cards/eval-c4.o b/c2prj1_cards/eval-c4.o new file mode 100755 index 0000000..8cca00b Binary files /dev/null and b/c2prj1_cards/eval-c4.o differ diff --git a/c2prj1_cards/eval.o b/c2prj1_cards/eval.o new file mode 100644 index 0000000..364ceb4 Binary files /dev/null and b/c2prj1_cards/eval.o differ diff --git a/c2prj1_cards/future.o b/c2prj1_cards/future.o new file mode 100644 index 0000000..a770c6a Binary files /dev/null and b/c2prj1_cards/future.o differ diff --git a/c2prj1_cards/grade.txt b/c2prj1_cards/grade.txt new file mode 100644 index 0000000..8a52657 --- /dev/null +++ b/c2prj1_cards/grade.txt @@ -0,0 +1,25 @@ +Grading at Mon 29 Nov 2021 02:19:48 AM UTC +Compiling cards.c +Testing card_from_letters +Passed +Testing value_letter and suit_letter +Passed +Testing print_card +Passed +Testing card_from_num +Passed +Testing ranking_to_string +ranking_to_string(STRAIGHT_FLUSH) resulted in STRAIGHT_FLUSH (Correct) +ranking_to_string(FOUR_OF_A_KIND) resulted in FOUR_OF_A_KIND (Correct) +ranking_to_string(FULL_HOUSE) resulted in FULL_HOUSE (Correct) +ranking_to_string(FLUSH) resulted in FLUSH (Correct) +ranking_to_string(STRAIGHT) resulted in STRAIGHT (Correct) +ranking_to_string(THREE_OF_A_KIND) resulted in THREE_OF_A_KIND (Correct) +ranking_to_string(TWO_PAIR) resulted in TWO_PAIR (Correct) +ranking_to_string(PAIR) resulted in PAIR (Correct) +ranking_to_string(NOTHING) resulted in NOTHING (Correct) +Passed +Testing assert_card_valid +Passed + +Overall Grade: PASSED diff --git a/c2prj1_cards/input.o b/c2prj1_cards/input.o new file mode 100644 index 0000000..65cc44b Binary files /dev/null and b/c2prj1_cards/input.o differ diff --git a/c2prj1_cards/main.o b/c2prj1_cards/main.o new file mode 100644 index 0000000..0f486ec Binary files /dev/null and b/c2prj1_cards/main.o differ diff --git a/c2prj1_cards/my-test-main.c b/c2prj1_cards/my-test-main.c new file mode 100644 index 0000000..fefe47e --- /dev/null +++ b/c2prj1_cards/my-test-main.c @@ -0,0 +1,5 @@ +#include "cards.h" + +int main(void) { + +} -- cgit v1.2.3