C语言每日一练——第64天:自动发牌程序

Posted 小辉_Super

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言每日一练——第64天:自动发牌程序相关的知识,希望对你有一定的参考价值。

C语言每日一练
2021年12月7日

题目描述

一副扑克有52张牌,打桥牌时应将牌分给4个人。请设计一个程序完成自动发牌的工作。要求:黑桃用S (Spaces)表示,红桃用H (Hearts)表示,方块用D (Diamonds)表示,梅花用C (Clubs)表示。

问题分析

个人思路:
这题实现起来还是比较简单的,只需定义两个多维的字符数组,第一个用来存放扑克的编号,第二个用来存放4个玩家的手牌。

52张牌发给4个人,需要发13轮,每轮按玩家的编号顺序给他们发牌,发牌时,用随机函数生成要发牌的编号(随机函数的介绍可以参考我第61天的练习),如果该牌之前没被发放(已发放的牌用'\\0'标记),则将牌的编号存放到玩家的手牌数组中,同时将该牌的编号赋值为'\\0'。如果生成的随机数对应的牌已经被发过了,则继续生成新的随机数。当52张牌全部发放完毕,打印发牌的结果。

扑克数组char poker[4][13];中的4表示花色种类有四种,13表示每种有13张(13个编号),扑克牌的编号(名字)用字符表示,分别为:'2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A''0'表示10)

玩家的手牌数组是一个三维字符数组,char players[PLAYER_NUMBER][4][13] = 0; (PLAYER_NUMBER是玩家数量,4表示牌的花色种类有4种,13为某种花色的牌最多13张)
初始化时,手牌数组的所有值设置为'\\0',表示手上无牌。

代码实现

#include <stdio.h>
#include <stdlib.h>       //srand()/rand()
#include <time.h>         //time()

#define CARD_NUMBER   52  //总牌数(目前仅支持52)
#define PLAYER_NUMBER 4   //玩家数量

/******************************************************************************
 * @brief 给某个玩家发牌
 * @param player_id  玩家编号
 * @param players    玩家手牌数组
 * @param left_num   剩余可发放牌数
 * @param poker      扑克牌数组
 * @return   返回0表示发牌成功,返回-1表示无牌可发
 ******************************************************************************/
int Distribute_Card(int player_id, char players[][4][13], int *left_num, char poker[][13])

    if(*left_num <= 0)
        return -1;       //无牌可发
    int card_id = 0;     //扑克牌编号
    int card_index = 0;  //手牌数组下标
    do
    
        /* 随机获取一个扑克牌的编号(0~52) */
        card_id = rand() % CARD_NUMBER;
    while(poker[card_id / 13][card_id % 13] == '\\0'); //如果该牌已经发放,继续获取编号
    (*left_num)--;       //剩余可发牌数减1

    while(players[player_id][card_id / 13][card_index] != '\\0')
    
        card_index++;    //到达该玩家的手牌数组有效值的下一个下标('\\0'表示无效值)
    

    /* 给玩家手牌数组赋值(加一张牌) */
    players[player_id][card_id / 13][card_index] = poker[card_id / 13][card_id % 13];

    /* 将该牌标记为无效牌(已发放) */
    poker[card_id / 13][card_id % 13] = '\\0';

    return 0;


/******************************************************************************
 * @brief 打印发牌结果
 * @param players    玩家手牌数组
 ******************************************************************************/
void Print_Result(char players[][4][13])

    int i = 0, j = 0, k = 0;

    /* 牌的类别 */
    char card_name[][8] = "黑桃", "红桃", "方块", "梅花";

    for(i = 0; i < PLAYER_NUMBER; i++)
    
        printf("\\n玩家%d:\\n", i + 1);
        for(j = 0; j < 4; j++)
        
            printf("%s: ", card_name[j]); //打印卡牌类型

            //依次打印某玩家该类型的手牌
            for(k = 0; players[i][j][k]!= '\\0' && k < 13; k++)
            
                if(players[i][j][k] == '0')
                    printf("10 ");        //'0'对应10
                else
                    printf("%c ", players[i][j][k]);
            
            printf("\\n");
        
    


int main()

    /* 扑克牌数组 */
    char poker[4][13] = '2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A',\\
                         '2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A',\\
                         '2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A',\\
                         '2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A';
    int left_num = sizeof(poker);             //剩余可发放牌数(应该等于CARD_NUMBER)
    char players[PLAYER_NUMBER][4][13] = 0; //玩家手牌数组
    int i = 0, j = 0, k = 0;

    //用系统秒数初始化随机数种子
    srand((unsigned)time(NULL));

    /* 给每个玩家发牌 */
    for(i = 0; i < CARD_NUMBER/PLAYER_NUMBER + 1; i++) //当玩家是奇数时,需要+1(这个值只能多不能少)
    
        for(j = 0; j < PLAYER_NUMBER; j++)
        
            //给某一个玩家发牌
            if(!Distribute_Card(j, players, &left_num, poker))
                k++;  //发牌成功次数+1
        

    
    printf("\\n成功发牌%d次!\\n", k); //总发牌次数
    Print_Result(players); //打印结果

    return 0;

运行结果

网上参考

原文链接:http://c.biancheng.net/cpp/html/3363.html

这份代码的实现思路和我差不多,但是还是存在许多细节上的差异,同时他还在发牌结束后给每个人的手牌进行了排序(从大到小)。【不过他的随机函数的随机数种子是固定的,这样会导致每次运行的结果都相同】

#include<stdlib.h>
#include<stdio.h>
int comp(const void *j, const void *i);
void p(int b[], char n[]);
int main(void)

    static char n[]='2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A';
    int a[53], b1[13], b2[13], b3[13], b4[13];
    int b11=0, b22=0, b33=0, b44=0, t=1, m, flag, i;
    while( t<=52 )  /*控制发52张牌*/
    
        m=rand()%52;  /*产生0到51之间的随机数*/
        for(flag=1,i=1; i<=t&&flag; i++)  /*查找新产生的随机数是否已经存在*/
            if(m==a[i])
                flag=0;  /*flag=1表示产生的是新的随机数,flag=0表示新产
                          生的随机数已经存在*/
        if(flag)
        
            a[t++]=m;  /*如果产生了新的随机数,则存入数组*/
            /*根据t的模值,判断当前的牌应存入哪个数组中*/
            if(t%4==0)
                b1[b11++]=a[t-1];
            else
                if(t%4==1)
                    b2[b22++]=a[t-1];
                else
                    if(t%4==2)
                        b3[b33++]=a[t-1];
                    else
                        if(t%4==3)
                            b4[b44++]=a[t-1];
        
    
    qsort(b1, 13, sizeof(int), comp);  /*将每个人的牌进行排序*/
    qsort(b2, 13, sizeof(int), comp);
    qsort(b3, 13, sizeof(int), comp);
    qsort(b4, 13, sizeof(int), comp);
    p(b1, n);  /*分别打印每个人的牌*/
    p(b2, n);
    p(b3, n);
    p(b4, n);
    return 0;

void p(int b[], char n[])

    int i;
    printf("\\n\\006 ");  /*打印黑桃标记*/
    for(i=0; i<13; i++)  /*将数组中的值转换为相应的花色*/
        if(b[i]/13==0)  /*找到该花色对应的牌*/
            printf("%c ", n[b[i]%13]);
    printf("\\n\\003 ");  /*打印红桃标记*/
    for(i=0; i<13; i++)
        if((b[i]/13)==1)
            printf("%c ", n[b[i]%13]);
    printf("\\n\\004 ");  /*打印方块标记*/
    for(i=0; i<13; i++)
        if(b[i]/13==2)
            printf("%c ", n[b[i]%13]);
                printf("\\n\\005 ");  /*打印梅花标记*/
                for(i=0; i<13; i++)
                    if(b[i]/13==3 || b[i]/13==4)
                        printf("%c ", n[b[i]%13]);
    printf("\\n");

int comp(const void *j, const void *i)  /*qsort调用的排序函数*/

    return(*(int*)i-*(int*)j);

以上是关于C语言每日一练——第64天:自动发牌程序的主要内容,如果未能解决你的问题,请参考以下文章

C语言每日一练——第154天:牛顿迭代法求方程根

C语言每日一练——第105天:杨辉三角形

C语言每日一练——第126天:佩奇借书问题

C语言每日一练——第147天:兔子产子问题

C语言每日一练——第90天:青蛙跳台阶(升级版)

C语言每日一练——第61天:掷骰子游戏