将扑克牌发给四个阵列

Posted

技术标签:

【中文标题】将扑克牌发给四个阵列【英文标题】:Dealing playing cards to four arrays 【发布时间】:2021-03-06 23:14:10 【问题描述】:

当我尝试使用结构向四个玩家发 52 张牌时,代码可以运行,但问题是在输出中出现了一些错误:

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

typedef struct 
    char *value;
    char *type;
card;


int main()

    srand(time(NULL));
    int i, r;
    char name[4][9] = "diamonds","clubs","hearts","spades";
    char num[13][6] = "ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king";
    
    card c[52];
    card temp;
    card player1[13], player2[13], player3[13], player4[13];
    
    for (i=0 ; i<52 ; i++)
        c[i].type = name[i % 4];
        c[i].value = num[i % 13];
    
    
    for (i=0 ; i<52 ; i++)
    r= rand() % 52;
    temp = c[i];
    c[i] = c[r];
    c[r] = temp;
        
    
    
    for (i=0 ; i<52 ; i++)
        switch(i+1 % 4)
            case 0:
                player1[i].type= c[i].type;
                player1[i].value= c[i].value;
                break;
            case 1:
                player2[i].type= c[i].type;
                player2[i].value= c[i].value;
                break;
            case 2:
                player3[i].type= c[i].type;
                player3[i].value= c[i].value;
                break;
            default:
                player4[i].type= c[i].type;
                player4[i].value= c[i].value;
        
    
    
    printf("Player 1 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player1[i].type, player1[i].value);
    
    printf("\n");
    
    printf("Player 2 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player2[i].type, player2[i].value);
    
    printf("\n");
    
    printf("Player 3 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player3[i].type, player3[i].value);
    
    printf("\n");
    
    printf("Player 4 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player4[i].type, player4[i].value);
    
    printf("\n");
    
    
    

    return 0;

输出: 玩家 1 红心九 钻石王 心十 钻石十 黑桃杰克 俱乐部之王 红心四 黑桃八 黑桃王 俱乐部杰克 黑桃二 钻石杰克 心杰克

玩家 2 黑桃六 红心皇后 钻石王牌 黑桃五 钻石六 红心七 俱乐部八 俱乐部七 黑桃王牌 三颗心 红心王 钻石二 俱乐部六

玩家 3 黑桃三 钻石七 俱乐部女王 红心六 红心五 钻石三 黑桃九 俱乐部三 黑桃皇后 俱乐部王牌 俱乐部二 钻石四 心王

玩家 4 à└ëD$@ï╪☼ê°♥ (null) (空) (空) 两颗心 红心八 钻石九 俱乐部五 黑桃七 俱乐部九 黑桃四 俱乐部十 钻石八 钻石皇后 俱乐部四

它进入了播放器 4 空和奇怪的字符,请任何解决方案。

【问题讨论】:

交易循环for (i=0 ; i&lt;52 ; i++) 会发生什么,例如player1[i]?播放器阵列有多大? (提示:不是52 一个播放器数组包含13个元素 i &gt; 12 时会发生什么? (提示:Undefined Behavior 由超出数组边界的写入引起) switch(i+1 % 4) ==> 如果必须... switch((i+1) % 4) 并添加default 案例 【参考方案1】:

当您循环for (i=0 ; i&lt;52 ; i++) 设置player1[i]player2[i] 等时,您的问题出现在您的交易循环中。你用13 元素声明你的播放器数组。所以在你的循环中,当i &gt; 12 你调用Undefined Behavior 试图写入13th 元素及以后。

要解决此问题,您需要将玩家索引限制为0-12,您可以使用i % 13,例如

    for (i=0 ; i<52 ; i++) 
        switch (i % 4)
            case 0:
                player1[i%13] = c[i];
                break;
            case 1:
                player2[i%13] = c[i];
                break;
            case 2:
                player3[i%13] = c[i];
                break;
            default:
                player4[i%13] = c[i];
        
    

或者为您的玩家索引保留单独的计数器,并在发牌时递增每个计数器。 进行更改,您将拥有,例如

    int p1 = 0, p2 = 0, p3 = 0, p4 = 0;
    ...
    for (i=0 ; i<52 ; i++) 
        switch (i % 4)
            case 0:
                player1[p1++] = c[i];
                break;
            case 1:
                player2[p2++] = c[i];
                break;
            case 2:
                player3[p3++] = c[i];
                break;
            default:
                player4[p4++] = c[i];
        
    

注意:你可以简单地分配结构,不需要单独的值。你可以从switch (i % 4)中删除+1。)

现在您的手将在没有 SegFault 的情况下处理。

【讨论】:

为什么这是正确答案?为什么使用 4 个不同的数组?此外,代码还有许多其他问题...***.com/a/64982690/14273548 你也可以用我的例子来做,修改代码,或者让播放器成为指向数组中那个索引的指针,有 4 个数组是不好的做法...@superzer101 @UriyaHarpeness 使用一维数组还是二维数组完全无关紧要。从微优化的角度来看,一维阵列具有性能优势。 首先,在这个概念上,您也可以避免使用一维数组,其次,它需要更多的内存,并且可读性要低得多。 @DavidC.Rankin 它占用的内存不多也不少——句号。你是从哪里想到的?数组是nelements * sizeof(type) 字节的连续块,无论是一维还是二维。不同之处在于二维数组,您需要计算正在完成的偏移量。【参考方案2】:

这是一个可能的实现,可以满足您的要求:

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

#define PLAYERS_NUM 4
#define CARDS_PER_PLAYER 13
#define NAMES_NUM 4
#define VALUES_NUM 13
#define TOTAL_CARDS NAMES_NUM*VALUES_NUM

typedef struct 
    char *value;
    char *type;
 card;

int main() 
    srand(time(NULL));

    unsigned int i, j, r;
    char *name[NAMES_NUM] = "diamonds", "clubs", "hearts", "spades";
    char *num[VALUES_NUM] = "ace", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack",
                             "queen", "king";

    // Initialize pile.
    card cards[TOTAL_CARDS];
    for (i = 0; i < NAMES_NUM; i++) 
        for (j = 0; j < VALUES_NUM; j++) 
            cards[(i * VALUES_NUM) + j] = (card) name[j], num[i];
        
    

    card tmp;
    // Shuffle pile.
    for (i = 0; i < TOTAL_CARDS; i++) 
        r = rand() % TOTAL_CARDS;
        tmp = cards[r];
        cards[r] = cards[i];
        cards[i] = tmp;
    

    card players[PLAYERS_NUM][CARDS_PER_PLAYER];

    // Deal cards.
    for (i = 0; i < PLAYERS_NUM; i++) 
        for (j = 0; j < CARDS_PER_PLAYER; j++) 
            players[i][j] = cards[i * CARDS_PER_PLAYER + j];
        
    

    // Printing.
    for (i = 0; i < PLAYERS_NUM; i++) 
        printf("Player %d\n", i);
        for (j = 0; j < CARDS_PER_PLAYER; j++) 
            printf("%s %s\n", players[i][j].type, players[i][j].value);
        
        printf("\n");
    

    return 0;

几点:

您没有包含#include &lt;stdlib.h&gt;。 您没有发牌,可能有重复的牌,此实现会洗牌并发牌,不会重复。 您不需要 4 个数组来保存玩家,二维数组更好(也可以稍后传递给函数)。 如果您使用定义的值而不是一遍又一遍地重复它们,代码看起来会更简洁,这样它们也可以在一个地方更改并在任何地方生效。 您不需要定义名称和值的大小,如果您不打算更改它们,它们将是静态常量字符串,因此只需定义为char *,这样就不需要找出最长的字符串,分配无用的数据。

【讨论】:

【参考方案3】:

由于您声明 Player 结构数组大小为 13,但您传递的最大为 52,这就是它显示空名称的原因。您应该始终在Player 结构中传递&lt;13 索引。为此,通过 Mod 为 13 传递 player[i%13] 值。

player[i%13].type= c[i].type;
player[i%13].value= c[i].value;

当你传递for(i=0 ; i&lt;52 ; i++) 你的循环传递大尺寸。 Mod 13 表示一个玩家最多可以获得 12 个值。

#include <stdio.h>
#include<math.h>

typedef struct 
    char *value;
    char *type;
card;


int main()

    int i, r;
    char name[4][9] = "diamonds","clubs","hearts","spades";
    char num[13][6] = "ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king";

    card c[52];
    card temp;
    card player1[13], player2[13], player3[13], player4[13];

    for (i=0 ; i<52 ; i++)
        c[i].type = name[i % 4];
        c[i].value = num[i % 13];
    

    for (i=0 ; i<52 ; i++)
    r= rand() % 51;
    temp = c[i];
    c[i] = c[r];
    c[r] = temp;

    
    for (i=0 ; i<52 ; i++)
        int ind=i+1;
        switch(ind % 4)
            case 0:
                player1[i%13].type= c[i].type;
                player1[i%13].value= c[i].value;
                break;
            case 1:
                player2[i%13].type= c[i].type;
                player2[i%13].value= c[i].value;
                break;
            case 2:
                player3[i%13].type= c[i].type;
                player3[i%13].value= c[i].value;
                break;
            default:
                player4[i%13].type= c[i].type;
                player4[i%13].value= c[i].value;
        
    

    printf("Player 1 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player1[i].type, player1[i].value);
    
    printf("\n");

    printf("Player 2 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player2[i].type, player2[i].value);
    
    printf("\n");

    printf("Player 3 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player3[i].type, player3[i].value);
    
    printf("\n");

    printf("Player 4 \n");
    for (i=0 ; i<13 ; i++)
        printf("%s %s\n" , player4[i].type, player4[i].value);
    
    printf("\n");

    return 0;

【讨论】:

以上是关于将扑克牌发给四个阵列的主要内容,如果未能解决你的问题,请参考以下文章

扑克牌发牌游戏程序(包括随机数解释)

python——德州扑克

UESTC1610 黑红梅方

如何在 Swift 中打乱数组?

随机出现的 UIImage

从四个点绘制填充形状