【问题标题】:Can't randomize cards. Some of them are duplicates不能随机卡。其中一些是重复的
【发布时间】:2020-05-11 14:25:31
【问题描述】:

我是 C 新手,我正在尝试随机化 16 张卡片。在较长的 cmets 中,我写了一些我不太清楚的东西......顺便说一句,这是代码:

#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)
}

例如,在第 38 行,我不明白为什么我应该只使用一个 *,因为如果我只使用一个,它应该是比较地址,而不是值。如果我输入**,它就不会起作用(无限期地加载),所以我只留下了一个*,但我不知道为什么。 我认为问题出在检查器内部的某个地方(可能是** 的东西)。

其中一个随机输出,如您所见,有重复。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

【问题讨论】:

  • 制作一个包含所有可能值的数组,打乱数组(可能是fischer-yates algorithm?
  • @pmg 如何处理重复?
  • mixed_cards 当前是char * 的二维数组,但看起来它应该是char 的二维数组:char mixed_cards[FACES*SUITS][20] = {0};。然后wMixed(和wwMixed)函数参数应声明为:char wMixed[][20]char (*wMixed)[20]wwMixed 相同)。可以使用sprintf(wMixed[j], "%s of %s", wFace[face], wSuit[suit]);等数组索引操作。
  • 处理扑克牌的常用方法是将0 编码为12 为黑桃A,将13 编码为25 为黑桃A红桃 A,2638 是梅花,3951 是方块(或附近),所以序列 0, 1, 2, ..., 51 包含所有 52 张牌且没有重复。

标签: c arrays pointers random shuffle


【解决方案1】:

你应该首先用数组中没有重复的每张卡片创建套牌:

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*/

}

然后使用Fisher-Yates shuffle算法对数组进行洗牌...

【讨论】:

    【解决方案2】:

    (*(wwMixed+current) == *(wwMixed+i))本质上和写是一样的:

    (wwMixed[current] == wwMixed[i])
    

    这就是为什么您只需要 1 个*

    由于wwMixed[i]包含一个字符串,而你想比较字符串,我建议你使用strcmp()

    if ( (strcmp(*(wwMixed+current),*(wwMixed+i)) == 0) && (current!=i) )
        return 1;
    
    

    【讨论】:

    • 这解决了问题!!但是现在我问你,为什么在它不起作用之前和 strcmp 一起工作?还有,为什么 **(wwMixed+current) 和 *(wwMixed+current) 是一样的?
    • @Mnkisd 在 C 语言中,您需要使用函数 strcmp 来比较字符串,无法使用比较运算符来比较数组。而*(array+i)和array[i]是一样的,它们是可以互换的,不同的写法。
    • @isrnick 不应该 **(wwMixed+current) 获取该数组位置内的值?不使用 strcmp 就没有另一种比较字符串的方法吗?另外,你写 *(array+i) 和 array[i] 是一样的,但我问的是 **(array+i) 和 *(array+i)
    • **(array+i) 将为您提供字符串array[i] 中的第一个字符(即array[i][0])。 *(array + i) 会给你array 中的第 i 个字符串(即array[i])。
    • @Mnkisd 要按字母顺序进行比较,您必须使用 strcmp、strncmp 或 strcoll,或者实现您自己对数组中字符的比较。而且**(array+i)*(array+I) 不一样,哪里都没有说过。
    猜你喜欢
    • 2011-06-19
    • 2020-05-13
    • 2011-07-02
    • 2020-07-22
    • 1970-01-01
    • 2016-03-21
    • 2012-10-31
    • 1970-01-01
    • 2013-10-28
    相关资源
    最近更新 更多