> Should the interface to the program (menu, options, input, and what is printed > out) be *exactly* like it is in the example in the specification and on the > website? YES!! The specification tells you exactly what the interface should be. This is extremely important in any software development effort. If you get a job in software, you will be required to create systems that follow the exact specification that the design dictates. Also, few software systems outside of the academic environment will be small and contained enough for you to program by yourself. You will find that even working with one other person is sometimes difficult due to module interfacing problems. So, you need to follow interface guidelines (often designated by function prototypes) to the letter. Fortunately, you are afforded that opportunity in this project. If you're concerned about stifled creativity, excercise your ingenuity in the design and implementation of the underlying code. Create useful and efficient algorithms so that others will ooh and aah at your code. Of course, this practice should not be taken so far as to make your code esoteric or "clever" to the point of absurdity. -------------------------------------------------------------------------- > I'm a bit confused about the assignment, and how to get started. I think it's > the .h files that are throwing me off. > > I defined CARD_T and DECK_T in poker.h, and defined STATS_T in poker.c. > > So now, I need to list the function prototypes (init_cards, read_deck, etc) in > poker.c....right? And since some of those functions take DECK_T or CARD_T types > as arguments, I need to #include poker.h in poker.c....right? Yes, everything is right up to here. > If that is right, where exactly do poker_hands.h and poker_hands.c come in? and > what is poker_other.c? Just some code for us to copy into poker.c? Functions in poker.c will call functions that are in poker_hands.c. You will need to include poker_hands.h in poker.c to get the function prototypes. And yes, the code in poker_other.c is for you to use in poker.c. -------------------------------------------------------------------------- > Do you want us to print a Winning % as a number between 0.0 and 1.0 (as in the > assignment specification) or between 0.0 and 100.0 (as in the on-line example)? Use the 0.0 to 100.0 range -- it makes more sense in this context. -------------------------------------------------------------------------- > i'm pretty much done with the program, but have a couple of comments: > 1] I added a function, int one_pair(card_t hand []), to poker_hands.c > 2] I went ahead and changed the parameter to init_cards to a deck pointer > instead of a deck It's OK to add a function to test for one pair, though you don't need it. You're right, though, the parameter to init_cards needs to be a pointer. -------------------------------------------------------------------------- > Do we need to include any special files to get the init_rand() function > to work? Yes, put the following at the top of your code: #include to get the prototypes for the time functions. -------------------------------------------------------------------------- > I guess I'm confused about the set_seed and shuffle > methods. The shuffle method uses a random number to swap > cards...so is that where we would use init_rand? If so, I > don't really understand how, since init_rand doesn't return > any value and neither does set_seed. > > Why can't we just say random_number= rand()%52 inside > shuffle to get an index number? The init_rand() function initializes the random number generator; therefore, you only need to call it once at the beginning of the program. If you didn't initialize the random number generator with a different value each time you started you program, you would probably start with the same cards each time and, if you made the same decisions, you'd play exactly the same set of hands. This behavior is not consistent across all systems, but you wouldn't want it to ever occur. So, you need to seed the random number generator with another semi-random value (the number of seconds after the hour in the code I made available) to make the game more interesting across program executions. To make the program easier to grade, the specifications call for an additional option to allow the user to enter a value to act as the seed. This will guarantee that the program will work in a predictable fashion for a given system. -------------------------------------------------------------------------- > Is replace_cards supposed to call deal_cards to get the > replacement cards? Or can replace_cards get the top of the > deck by itself? It should call deal_cards. -------------------------------------------------------------------------- > So if I understand right, I just need to call init_rand(0) > in the beginning, then if the user wants to set the seed, > they can call set_seed and put in some value. And that > will "over ride" the original call to init_rand? Yes, that's right. -------------------------------------------------------------------------- > I don't understand how to use the HAND_T you've written in > poker.h. I guess we are to use it in conjunction with > get_hand_type and get_dealer_hand but I don't understand > how. What does typedef enum HAND HAND_T do? HAND_T is an enumerated type. That is, if you declare a variable of that type HAND_T example; then you can do things like example = ROYAL_FLUSH; Of course, you can also use such types as return types from functions. So, you can use meaningful names for the values associated with a certain type of data. Similarly, the boolean type in Java has values with names true and false. The C compiler really just assigns int values to these names in the order that they're listed in the enum, but it helps the programmer to write more readable code. As an additional bonus, you can use such a type name as an index into another array, such as an array of strings (that in the poker program, will enable you to print out the type of hand without doing a large switch statement). -------------------------------------------------------------------------- > Is it ok to add a print_deck function into our program? > Can we leave it in their even when turning it in or will points > be counted off? I think it's a good idea to add a print_deck function -- it will help with debugging your program. You'll be able to leave the function in the program without a point deduction. -------------------------------------------------------------------------- > Can we use global variables in the program? No. Point deductions will be assessed for global variables. -------------------------------------------------------------------------- > Do we need to use fflush (stdin) for this program? No, you won't need to do this kind of I/O processing for this assignment. You can use all scanf()'s. As a matter of fact, the TAs and I have decided that calling fflush(stdin) is not a good idea in general, so you should no longer use it in *any* of your programs. -------------------------------------------------------------------------- > What kind of style guidelines (commenting, code formatting, etc.) > should we use? There are style guidelines available off the lab homepage. Your program will be graded according to those standards. -------------------------------------------------------------------------- > I am confused about the due date of Program 3. I am pretty sure you gave > us an extension but I cant remember what date it was extended to. Could > you please clarify? The new due date is Friday, October 26, 9:00 a.m. -------------------------------------------------------------------------- > I remember you said in the review session that the poker_other.c code goes > into the poker.c...so do we have to define the structs in poker_other.c? What I meant was that you should copy the code from poker_other.c into the file poker.c. So, you never need to compile or use poker_other.c for the final program. All of the structs are defined in poker.h or poker.c. -------------------------------------------------------------------------- > I was trying to set the topdeck to point at the beginning of the array and > this was the logic that first came to mind but as you know is incorrect: > > deck->topdeck->cards[0]; Almost, but keep in mind that you want to assign the top of the deck to the first card in the deck. That is, deck -> topdeck = something The "something" is the address of the card in the first position of the deck. > Also, my shuffle works & used rand()%52 but I get the same random #'s all of > the time. Should I use the init_rand(seed) to obtain a random # in shuffle? Only now can you understand why the random number generator needs to be seeded. So, yes, call init_rand() with 0 and you'll get a different shuffle. Later, when you're testing other parts of the program, you won't want the shuffle to be so randomized. -------------------------------------------------------------------------- > Should we set the cards in the deck to 0 after we deal them? No, you should *not* set card values to 0 once they're used. That's what top is for -- it's a pointer to the current top card in the deck. Plus, things are going to go horribly wrong if you try to use this deck after shuffling for the next hand (which you are required to do). -------------------------------------------------------------------------- > Should I initialize the deck before each play session? No, you should only call init_cards only once at the very beginning of the program before any menu option is selected. -------------------------------------------------------------------------- > poker_other.c won't compile alone or with poker.c. "FILE", "fp", and > other things are undefined. Is there some sort of missing library file that > I'm supposed to include besides time.h? poker_other.c is not supposed to be a separate source file to compile and link in with your code -- it's there with additional code for you to use where appropriate (e.g., in poker.c). In order to get file I/O to work, you'll need to include stdio.h (that makes sense, right?). -------------------------------------------------------------------------- > Do sequences that contain Ace but do not end with Ace, such as Ace, 2, 3, > 4, 5, and King, Ace, 2, 3, 4, count as straight flush? A straight may begin or end with an Ace, but an Ace cannot be a middle card allowing the wrap-around example you cite above. > If the player wants to play the game again, is the player always dealt > cards from a complete deck or from the remaining cards left after the > previous play? When playing again, the cards are dealt from a complete deck (the top card pointer needs to be reset to the first card in the deck array). > Does the play function call shuffle()? Yes, *after* each hand is played. -------------------------------------------------------------------------- > Since Straight flush is a special kind of straight , and Full House is also > three of a kind, and one pair, should we eliminate the special cases in the > functions of poker_hands.c, or can we make get_hand_type call these 8 > functions in a specific priority order to serve the same purpose? The best way to do this is the second way you suggest: start with the highest possible hand and go downward until you find a match, then quit. > Also, do we need to implement One Pair in poker_hands.c? You should be able to use n_of_a_kind to check for one pair. You can't use n_of_a_kind for Two Pair since there's no way to tell the function that you've found the first pair and now you need to find the other. -------------------------------------------------------------------------- > just want to make sure I'm doing the set_seed( ) right.... > so, we can copy your init_rand() function and call it in set_seed(), and > also at the beginning of main. is that right? Yes -- call init_rand() with the user-specified seed in set_seed(). Also, call init_rand() with 0 at the very beginning of main. -------------------------------------------------------------------------- > why can we not define STATS_T in poker.h? it would be nice to define > STATS_T in poker.h instead of in poker.c since I would like to list > function prototypes in poker.h. It's better to keep prototypes in .c files unless they need to be accessed by other .c files -- then they go in a .h file. Since neither STATS_T, nor the functions that use STATS_T in their parameter definitions, are called outside poker.c, it's better to keep them in poker.c. -------------------------------------------------------------------------- > What should happen when the top of the deck (pointer) reaches the end? > Should it be shuffled again or should the pointer just rest to the top of > the original deck? The top card pointer should never reach the end of the deck. It is reset to the first card in the deck every time a new hand is played. -------------------------------------------------------------------------- > What happens if both players are playing high card and the highest > card in the player's hand has the same value as the card drawn by > the computer? The specifications do not address this possibility. > > 1. The player wins > 2. Both the player and computer draw another card until one beats the other > 3. The card is ranked according to suit > 4. The game is a draw (if so, how would we score this?) Alternative 1 above -- the player wins a high card hand tie. -------------------------------------------------------------------------- > How do you print a %? I've tried: > printf("Winning \%: %f", float_variable); > and I get the warning: dubious escape: \% Use double percent ("%%") inside the string to print out "%". -------------------------------------------------------------------------- > Do we need to initialize the cards in any specific order? Yes, initialize the cards in the following manner: 1 C 2 C 3 C ... 12 C 13 C 1 D 2 D 3 D ... 12 D 13 D 1 H 2 H 3 H ... 12 H 13 H 1 S 2 S 3 S ... 12 S 13 S That is, initialize each set of 13 cards by suit, where the four suits are in alphabetical order. -------------------------------------------------------------------------- > Do we need to sort cards in the the hand that have the same value by suit? Yes. This is a change from the original specification. If you have the hand: A C 9 H 9 D 9 C J H it should be sorted as A C 9 C 9 D 9 H J H Note the difference in the order of the 9's. -------------------------------------------------------------------------- > In the case of a dealer & player High Card, the dealer's high card is > determined by drawing a card from the top of the deck...The problem I was > pondering was if the dealer draws a 2 from the top of the deck, that is > supposed to be the high card? Obviously this is impossible, because all > cards must be less than or equal to the 2, thus a 5 card hand can consist > of ONLY Aces and 2s...thus resulting in a hand that is 4 Aces and one > 2. This is not a high card hand. In fact, the only way the dealer could > have a high card hand would be for the card drawn to be a 6 or > higher. Should I then program it so that the the top card would continue > to be drawn until it has a value >= 6???? If the dealer draws a 2 from the deck, that is the high card, even though it's impossible. -------------------------------------------------------------------------- > In project # 3, should an ACE be considered the highest card in the > case of the player and the dealer both having a High Card hand? That > is, should an ACE beat a KING, etc... Also, should the same set of > stats be kept throughout the whole program execution or should the > stats be reinitialized before each play session within the program > execution? In other words, if we play a game and then shuffle the > cards a few times or read in a deck or something without quitting and > then choose option # 1 again, should the stats be left alone or reset? The ace should be considered the highest card in a high card hand. Yes, keep the same set of stats throughout the program's execution. The only time the stats are initialized is at the beginning of the program. -------------------------------------------------------------------------- > This may be dumb to ask, but am I right in assuming that only the part of > the deck that has not been used should be shuffled ie from the top of the > deck and so on? Otherwise, although the probability is small, it is still > possible to deal cards that have already been played. On each new play, the entire deck should be shuffled and the top card pointer reset to the first card in the deck. -------------------------------------------------------------------------- > How do you want us to turn this in? handin command with > poker.c, poker.h, poker_hands.c, poker_hands.h? Yes, please turn in all four files with those exact names. -------------------------------------------------------------------------- > The webpage makes it very clear about init_rand and set_seed, but I'm > hearing conflicting reports about whether or not we are supposed to > shuffle the deck after we initialize it or not. Are we supposed to > shuffle at the beginning of execution before the first game is played? You should not automatically shuffle the cards before the first hand is played. Recall in class and on the sample run on the webpage that the first hand dealt is 1: A C 2: 2 C 3: 3 C 4: 4 C 5: 5 C which shows that the cards are obviously unshuffled. If you want to play the game for fun, you need to select option 3 before the first hand is dealt so that you'll get different cards than the ones above. -------------------------------------------------------------------------- > Here is my problem: > > printf("Would you like to play again? (y/n) "); > /* fflush(stdin); */ > scanf("%c", &again); > > You said not to use fflush, but if i omit it, the program skips the question. > I left it in for that reason, but now when I test it with input from a file, > it screws up because I used the fflush. I'm afraid that you might use an > input file to test my program when I turn it in, so how can I take out > fflush without it skipping the scanf when it runs? This is a good question. This situation unfortunately occurs often. One solution is to read the input as a string ("%s") into a character array, and then copy the first character of that string into the variable again. -------------------------------------------------------------------------- > I'm having trouble w/ my shuffle. > > I declare two pointers of type CARD_T, as in > > void shuffle_cards (DECK_T *deck){ > > CARD_T *x1; > CARD_T *x2; > > then set them > > x1 = &deck.cards[i]; > x2 = deck.cards[rand_indx]; > > but when I try to define x1 and x2 I get the following errors. > "poker.c", line 168: left operand of "." must be struct/union object > "poker.c", line 169: left operand of "." must be struct/union object > > I have tried removing the ampersand and using (*deck).cards[i] and > x1->deck.cards[i] etc etc... Keep in mind that you're passing deck in as a pointer. So, whenever you access any of its fields, you need to use the pointer ("->") notation. So your assignment would look more like x1 = &(deck -> cards [i]); and similarly for x2. -------------------------------------------------------------------------- > Exactly what time is the project due on Friday? With the latest extension, the due date is Saturday at 9 a.m. -------------------------------------------------------------------------- > I'm having trouble writing the two_pair function. One way to look at this is that since you're checking for two pairs in a sorted hand, they can only occur in three different positions. For example, let's say you had two 4's and two J's in your hand, with the other card unknown (represented by ? below). The only possible hands you could have would be 4 4 ? J J ? 4 4 J J 4 4 J J ? So you could just make if statements to check these three possibilities and you'd be done. (See the code for the full_house function to get some ideas). Note that this function would also return true for 4-of-a-kind, since you have two pairs (but they're pairs of the same card value), so you need to order the tests for different hands from highest (ROYAL_FLUSH) to lowest (HIGH_CARD) so that you know by the time you check for two pairs that you've already checked for 4-of-a-kind and failed. One other note: even though ROYAL_FLUSH is the highest hand, it has the lowest enum value. Take that into account when comparing hands. -------------------------------------------------------------------------- > I am trying to set the top of the deck to the first card in the deck, but I am > getting an assignment error because top_of_deck is a pointer to DECK_T and the > address of the card is a pointer to CARD_T. What am I missing here???? The field in DECK_T representing the top of the deck should be a pointer to CARD_T, not a pointer to DECK_T. -------------------------------------------------------------------------- > I thought you were asking us to shuffle after a replacement of cards is made. > It did not make sense to me that you would want us to shuffle in the middle > of a play ... You should only shuffle after all the replacements have been made for a hand. -------------------------------------------------------------------------- > You told us to put the cards in order of SUIT (C , D, H, S) and THEN > in order of value. For initializing the *deck*, you order the cards by suit first, then by value. For sorting cards in the *hand*, you sort by value first, then by suit. See the examples above and in the sample test run. -------------------------------------------------------------------------- > What is the late penalty for assignments? Is the same as the last > assignment? Yes, same as last assignment: 3^(num of days late). -------------------------------------------------------------------------- > What is the final word on the sorting of the hand. On the Q&A it says > to sort by suit then value but on the sample test run out put it is just > sorted by value. What are we suppose to do??? If we do it by suit then > value then how are we suppose tell if it is a straight if all the values > are mixed?? I don't think there are any errors on the sample output. I did change it when I added the extra part about sorting, so get the latest version if you're looking at an old one. You need to first sort by value. Then if any of the values are the same, you need to sort just those by suit. Example hand: 9S 2S 9D 9C 2H Sorted by value: 2S 2H 9S 9D 9C Sorted by suit: 2H 2S 9C 9D 9S --------------------------------------------------------------------------