3

First, here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

#define NUM_SUITS 4
#define NUM_RANKS 13

bool in_hand[NUM_SUITS][NUM_RANKS] = {false};
bool newcard = {false};
int num_cards, rank, suit, totrank;
const char rank_code[] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K',};
const char suit_code[] = {'C','D','H','S'};

int main_hand ()
{
    suit = rand() % NUM_SUITS;
    rank = rand() % NUM_RANKS;
    if (!in_hand[suit][rank]) {
        in_hand[suit][rank] = true;
        num_cards--;
        if (suit == 0){
            printf("%c of Clubs \n", rank_code[rank]);
        }
        else if (suit == 1){
            printf("%c of Diamonds \n", rank_code[rank]);
        }
        else if (suit == 2){
            printf("%c of Hearts \n", rank_code[rank]);
        }
        else if (suit == 3){
            printf("%c of Spades \n", rank_code[rank]);
       }
    }
}

int print_hand (suit)
{

}

int totrank_check (totrank)
{
    if (totrank > 21) {
        printf ("You lose!");
    }
    else if (totrank == 21) {
        printf ("You win!");
    }
}

int main()
{
     bool stay = {false};
     srand((unsigned) time(NULL));

     totrank = 0;
     num_cards = 2;
     printf("Your hand: ");
     while (num_cards > 0) {
         main_hand();
         totrank = totrank + (rank + 1);
     }
     printf("Total rank: %d\n", totrank);
     totrank_check(totrank);
     printf("\n");
     while (totrank < 24 && stay == false) {
        printf("Another card? 1. Yes 0. No\n");
        scanf("%d", &newcard);
        if(!newcard) {
            main_hand();
        }
        totrank = totrank + (rank + 1);
        totrank_check(totrank);
        printf("Total rank: %d\n", totrank);
        printf("Stay? 1. Yes 0. No\n");
        scanf("%d", &stay);
     }
    return 0;
}

Basically it's a code that "simulates" and hand of blackjack. It starts, rand() chooses two numbers, the rank and the suit of the cards, that are set as true in a matrix so that they can't be chosen again in the same combination and then printed. There's a check for the total rank of the cards (so that if it exceeds 21 you automatically lose) and then you are asked if you want another card or you want to stay.

Here's the error: if you choose that you want another cards, this new card will be the same as the last one. Basically, you get a Ace of Spades, the and Two of Diamonds, then you want another card and you get another Two of Diamonds. And the another, and another. If you remove the rank check in the second while you can see that the rank grows based on the rank of the last card.

Before, the printfs were in that print_hand() function, and you could see that you always got the same card, now I moved them in the main_hand() function because I thought that it might be the problem (it wasn't) and because having a separate function for the print was redundant. But you can see that technically, the if(!in_hand[suit][rank]) works, because, since the card is the same, it doesn't enter the if and it doesn't get printed.

I don't know what's causing this problem. Any idea?

Please note I'm already using srand((unsigned) time(NULL)); to seed rand().

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Paul
  • 473
  • 6
  • 19
  • 1
    Your `main_hand` routine picks a random card only once, even if it already has been taken. You need to retry until an untaken is found (crude but it does the job) or maintain an array of 'free' cards out of which you pick. – Jongware Dec 18 '14 at 21:32
  • Am I not doing that? Once rand() picks the card, there's an if that checks if the suit and the rank are present in an array. If they're not present, they are added, the counter of the cards to give is dimished, and the card picked is printed. If the card is already present, the if doesn't start, the counter is not diminshed, the card is not printed and the while-loop keeps on going until a new card is picked. – Paul Dec 18 '14 at 22:08
  • You keep increasing `totrank`, regardless of the result. (I wonder what `totrank` is supposed to represent.) – Jongware Dec 18 '14 at 22:19
  • totrank is supposed to be the sum of the various rank, since this is supposed to be an hand of blackjack, if your total rank is more than 21 you lose. But you're right, I moved the second increase in the same if where I call main_hand() for the second time, this way it increases only if a different card is drawn. – Paul Dec 18 '14 at 22:26
  • I'll go bury myself. – Paul Dec 19 '14 at 00:20

1 Answers1

3

scanf("%d", &newcard); and scanf("%d", &stay); are a problem as the variables are bool, but the format specifier is for int. In 2 places, change like:

// scanf("%d", &newcard);
int t;
scanf("%d", &t);
newcard = !!t;

3 functions return int but do not return anything. Change to void functions.

// int main_hand() {
void main_hand() {    

There appears to be other logic issues too.
1) Code sometimes exists without knowing if won/loss
2) @Jongware comment above correct:

Lastly: If the same random sequence is still coming up, strip code to a bare main srand time printf rand and see if that works. time(), if not working always returns -1.
Or simple add the following and verify srand() called with different values.

 int main(void) {
   unsigned now = (unsigned) time(NULL);
   printf("now = %u\n", now);
   srand(now);
Chnossos
  • 9,971
  • 4
  • 28
  • 40
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I changed the bool variables to int (by the way, what's the correct specifier for bool? I googled and i found %d, that's why I was using it). I also changed the functions from int to void. Now, I added that part to my code and the problems still presents itself. I noticed that now is always equal to 4201408, even if I launch the program many times. Might that be the problem? For that logic error, I'm aware, I want to fix it, but I'd like to understand why I can't get more than 2 random numbers first. – Paul Dec 18 '14 at 22:01
  • I also answered to @jongware, I think I'm already doing what he's suggesting (unless I'm doing everything wrong, that is). – Paul Dec 18 '14 at 22:09
  • @Paul, well at least we know the issue is not a card one, but a `time()` one. Try `printf("%lld\n", (long long) time());` so we get the entire time. – chux - Reinstate Monica Dec 18 '14 at 22:12
  • 1
    @Paul, confident `scanf()` does not have a format specifier for `bool`. See http://stackoverflow.com/questions/12920694/format-specifier-in-scanf-for-bool-datatype-in-c – chux - Reinstate Monica Dec 18 '14 at 22:14
  • 1
    I added NULL to time() (because I was getting a "too few arguments" error), and what I get is 1418941711 (And it increases slightly between re-runs of the program) while now is the same as before. – Paul Dec 18 '14 at 22:30
  • @Paul Your `time(NULL)` is returning a reasonable value - the expected number of seconds since Jan 1, 1970. Certain code wasn't something like `unsigned now = (unsigned) time;`? `srand((unsigned) time(NULL));` _should_ be working. `4201408` looks like a pointer value. – chux - Reinstate Monica Dec 18 '14 at 22:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67269/discussion-between-chux-and-paul). – chux - Reinstate Monica Dec 18 '14 at 22:46
  • If you're still getting the problem after making the fixes suggested here, then update the code in your past so that others can reproduce – M.M Dec 19 '14 at 00:16