问题
I'm new to C, I am trying to randomize 16 cards. In the longer comments I wrote something that I don't have much clear... Btw this is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FACES 4
#define SUITS 4
void shuffle(char *wFace[], char *wSuit[], char *wMixed[][20]); // prototype
size_t checker(char *wwMixed[][20], size_t current); // prototype
int main(){
char *face[] = {"Jack", "Queen", "King", "Ace"};
char *suit[] = {"Hearts", "Spades", "Diamonds", "Clubs"};
char *mixed_cards[FACES*SUITS][20] = {0}; // initialize the final array
shuffle(face,suit,mixed_cards); // send to shuffle the pointer array
for (size_t k=0; k<FACES*SUITS;++k){ // at the end
printf("%s\n", *(mixed_cards+k)); // it prints the results
}
}
void shuffle(char *wFace[], char *wSuit[], char *wMixed[][20]){
srand(time(NULL));
for (size_t j = 0; j<(FACES*SUITS); ++j){ // for every card
do {
size_t face = rand() % FACES; // choose randomly
size_t suit = rand() % SUITS; // choose randomly
sprintf(*(wMixed+j), "%s of %s", *(wFace+face), *(wSuit+suit)); // copy to *(wMixed+j) so in mixed_card[j][0] matrix
} while (checker(wMixed, j)); // it does the cycle until checker function says that the string is unique
}
}
size_t checker(char *wwMixed[][20], size_t current){
for (size_t i=0; i<FACES*SUITS;++i){
if ( (*(wwMixed+current) == *(wwMixed+i)) && (current!=i) ) { // I don't get why I should use ONLY ONE *, since if I use only one it should be comparing ADDRESSES, NOT VALUES. if I put ** it doesn't work though, but I don't know why.
return 1; // the string is already in use, so it has to continue to randomize. it returns 1 and the while cycle continues so new rand string is created
}
}
return 0; // otherwise, if this for cycle doesn't find any duplicate, it returns 0 to shuffle function and while stops so j is increased (in the other for)
}
For example in line 38 I don't get why I should use ONLY ONE *
, since if I use only one it should be comparing ADDRESSES, NOT VALUES. if I put **
it doesn't work tough (loads indefinitely) so I left only one *
, but I don't know why.
I think that the problem is somewhere inside checker (maybe this **
thing).
One of the randomized outputs, as you can see, there are duplicates.c
Jack of Diamonds
Queen of Clubs
Ace of Hearts
Jack of Clubs
Ace of Diamonds
King of Diamonds
Ace of Spades
Jack of Spades
King of Spades
Jack of Clubs
Jack of Spades
King of Spades
King of Clubs
Queen of Hearts
King of Spades
King of Spades
回答1:
You should first create the deck with every card without duplicates in the array:
void shuffle(const char *wFace[], const char *wSuit[], char wMixed[][20]){
srand(time(NULL));
for (size_t i=0; i<FACES; ++i){
for (size_t j=0; j<SUITS; ++j){
sprintf(wMixed[i*SUITS+j], "%s of %s\n", *(wFace+i), *(wSuit+j)); // save the card string
printf("%s", wMixed[i*SUITS+j]); // print card string
}
}
/*Add Fisher-Yates shuffle here*/
}
Then use the Fisher-Yates shuffle algorithm to shuffle the array...
回答2:
Writing (*(wwMixed+current) == *(wwMixed+i))
is essentially the same as writing:
(wwMixed[current] == wwMixed[i])
That is why you only need 1 *
.
Since wwMixed[i]
contains a string, and you want to compare strings, I suggest you use strcmp()
:
if ( (strcmp(*(wwMixed+current),*(wwMixed+i)) == 0) && (current!=i) )
return 1;
来源:https://stackoverflow.com/questions/61732065/cant-randomize-cards-some-of-them-are-duplicates