rand()在第一次调用后返回相同的值

3

首先,这是我的代码:

#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;
}
基本上,这是一个“模拟”二十一点牌局的代码。它开始时,rand() 会选择两个数字,即卡牌的等级和花色,并将它们设为矩阵中的 true,以便不能在同一组合中再次选择,然后打印出来。 有一个检查卡牌总等级的功能(因此如果超过21,你就会自动输掉),然后询问你是否要再要一张牌或者停止。 问题在于:如果你选择再要一张牌,那么这张新牌将与上一张相同。基本上,你得到了黑桃A和方块2,然后你想再要一张牌,你又得到了方块2。如果你在第二个 while 循环中删除等级检查,你可以看到等级是根据上一张牌的等级增长的。 之前,printf 在 print_hand() 函数中,你可以看到你总是得到相同的牌,现在我将它们移到了 main_hand() 函数中,因为我认为这可能是问题所在(但实际上不是),而且将打印单独作为一个函数是多余的。但你可以看到技术上说,if(!in_hand[suit][rank]) 是有效的,因为由于卡牌相同,它不会进入 if 并且不会被打印出来。 我不知道是什么原因导致了这个问题。有什么想法吗? 请注意,我已经使用 srand((unsigned) time(NULL)); 来生成 rand() 的种子。

1
你的 main_hand 程序只会随机选择一张卡牌,即使它已经被选过了。你需要重试直到找到一张未被选中的卡牌(虽然有些粗糙,但可以完成任务),或者维护一个“自由”卡牌数组供你选择。 - Jongware
我没有做到吗?一旦rand()选择了牌,就会有一个if语句来检查花色和等级是否存在于一个数组中。如果它们不存在,它们将被添加,要给的卡牌计数器将减少,并且选择的卡牌将被打印出来。如果该卡已经存在,则if不会启动,计数器不会减少,卡不会被打印出来,while循环会继续进行,直到选择出新的卡牌。 - Paul
无论结果如何,您都在增加“totrank”。(我想知道“totrank”应该代表什么。) - Jongware
totrank 应该是各个排名之和,因为这是黑杰克的手牌,如果你的总排名超过21,你就输了。但你说得对,我把第二次增加放到了同一个 if 语句里,在第二次调用 main_hand() 的时候,它只会在抽取不同的牌时增加。 - Paul
我会去埋葬自己。 - Paul
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3

scanf("%d", &newcard);scanf("%d", &stay); 中的变量是 bool 类型,但格式说明符是 int。需要修改两处:

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

有3个函数返回int,但实际上并没有返回任何内容。请将它们改为void函数。

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

似乎还存在其他逻辑问题。
1)有时代码在不知道输赢的情况下就退出了。
2)@Jongware上面的评论是正确的:

最后:如果仍然出现相同的随机序列,请将代码简化为裸 main srand time printf rand,并查看是否起作用。 如果time()无法工作,则始终返回-1。
或者简单地添加以下内容,并验证已使用不同的值调用srand()

 int main(void) {
   unsigned now = (unsigned) time(NULL);
   printf("now = %u\n", now);
   srand(now);

我将布尔变量改为了整型(顺便问一下,bool 的正确说明符是什么?我谷歌了一下,发现是 %d,所以我就用它了)。我还将函数从 int 改为了 void。 现在,我已经将那部分代码添加到了我的程序中,但问题仍然存在。我注意到现在始终等于 4201408,即使我多次启动程序也是如此。这可能是问题所在吗? 对于那个逻辑错误,我知道要修复它,但我想先了解为什么我不能首先获得超过 2 个随机数。 - Paul
我也回复了@jongware,我认为我已经在做他建议的事情了(除非我做错了一切)。 - Paul
1
@Paul,确信scanf()没有针对bool的格式说明符。请参见https://dev59.com/Nmcs5IYBdhLWcg3wXSuU。 - chux - Reinstate Monica
1
我在time()函数中添加了NULL(因为我得到了“参数过少”的错误),结果我得到的是1418941711(并且在程序重新运行时略微增加),而现在与之前相同。 - Paul
如果您在按照此处建议的修复方法后仍然遇到问题,则请更新您过去的代码,以便其他人可以重现。 - M.M
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,