| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1324 人关注过本帖, 1 人收藏
标题:求大神给补充完整这个21点游戏完整版程序(C语言带解释)
只看楼主 加入收藏
sunchao16
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2016-10-24
结帖率:50%
收藏(1)
 问题点数:0 回复次数:0 
求大神给补充完整这个21点游戏完整版程序(C语言带解释)
21点游戏
一、规则:
该游戏由2到6个人玩,使用除大小王之外的52张牌,游戏者的目标是使手中的牌的点数之和不超过21点且尽量大。21点一般用到1-8副牌。
扑克点数的计算规则是:2至9牌,按其原点数计算;K、Q、J和10牌都算作10点,记作T;A牌既可算作1点也可算作11点,当玩家停牌时,点数一律视为最大而尽量不爆,如A+9为20,A+4+8为13,A+3+A视为15。
开局时,庄家给每个玩家牌面向上发两张牌(明牌),再给庄家自己发两张牌,一张明牌,一张暗牌(牌面朝下)。
当所有的初始牌分发完毕后,如果玩家拿到的是A和T(无论顺序),就拥有黑杰克(Black Jack);若庄家的明牌为T,且暗牌为A,应直接翻开并拥有Black Jack;如果庄家的明牌为A,则玩家可以考虑买不买保险(Insurance),保险金额是赌注的一半且不退(交给庄家),此时,如果庄家的暗牌为10点牌(构成Black Jack),那么翻开此牌,购买保险的玩家得到1倍赌注;如果庄家没有Black Jack则保持暗牌,玩家继续游戏。若玩家为Black Jack且庄家为其他,玩家赢得2倍赌注;若庄家为Black Jack且玩家为其他,庄家赢得赌注;若庄家和玩家均为Black Jack,平局,玩家拿回自己的赌注。
接下来是正常的拿牌流程:首名非黑杰克玩家选择拿牌(Hit)、停牌(Stand)、加倍(Double)或投降(Surrender,庄家赢得一半赌注);所谓加倍:玩家在拿到前两张牌之后,可以再下一注与原赌注相等的赌金,然后只能再拿一张牌。若选择拿牌,则后续只能选择拿牌或停牌。在发牌的过程中,如果玩家的牌点数的和超过21,玩家就输了——叫爆掉(Bust),庄家赢得赌注(哪怕庄家也超过21点)。假如玩家没爆掉,又决定不再要牌了(停牌,或因加倍、投降而终止),则轮到下一名非黑杰克玩家选择。如果玩家违规,即给出了保险(用i表示)、拿牌(用h表示)、停牌(用s表示)、加倍(用d表示)和投降(用u表示)之外的动作符号,则算作违规,会扣除所有本次的赌注给庄家。
当所有未爆掉的玩家停止拿牌后,庄家翻开暗牌,并持续拿牌直至点数不小于17(若有A,按最大而尽量不爆计算)。假如庄家爆掉了,那他就输了,玩家赢得1倍赌注;否则那么比点数大小,大为赢。点数相同为平局,玩家拿回自己的赌注。
每位玩者和庄家之间的游戏都是独立的,因此在同一局内,庄家有可能会输给某些玩家,但也同时击败另一些玩家。
每次洗牌可以玩若干局,如果剩余的牌数不足总数的1/4,则在完成本局游戏后重新洗牌、切牌。
初始情况下每个玩家有1000元的赌资,每次可以下注的金额不低于10元。
满足以下条件之一的玩家结束游戏:
(1)所有赌资都已经输光;
(2)洗过5次牌,第6次洗牌时游戏停止;
(3)总局数达到玩家数量*30局。

多人玩该游戏,相互之间PK,首先按照剩余赌资排序,剩余赌资多的胜,如果剩余赌资相等且都大于零,则并列;如果两个玩家的剩余赌资均为零,则比较轮次,轮次多的获胜,如果轮次相同,则并列。

二、选取该项目的得分标准:
(1)能够正常玩游戏(不违反游戏规则),得到最基础的分值,即该项目本身分值的60%;
(2)能够根据当前牌型智能选择不同策略(保险、加倍、投降、拿牌、停牌),且能够保持对于不加任何策略,每次直接停牌的玩家90%以上的胜率的,可以增加20%;
(3)能够根据目前已经出过的所有牌,推断剩余牌中各个点数出现的概率,并相应调整不同策略的,且能够保持对于第(2)中情况玩家60%以上的胜率的,可以继续在(2)的基础上增加20%;
(4)能够提出更有效策略的,酌情加分。
下面是代码(求补充):
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define TOTAL_MONEY 1000
typedef struct{
    char name[20]; //玩家昵称
    int account; //账户剩余金钱
    char mycards[20]; //本轮已经拿到的牌
    int count; //本轮已经拿到牌的数量
    char state; //当前状态;i,买保险;h,继续拿牌;s,停牌;d,加倍;u,投降
    int mybets; //本轮已经下的赌注
    int points; //本轮牌对应的点数
    int rounds; //已经玩的轮数
}Player;  

typedef struct{
    char mycards[20]; //本轮已经拿到的牌
    int count; //本轮已经拿到牌的数量
    char state; //状态;d,第二张是暗牌;l,第二张是明牌
    int points; //本轮牌对应的点数
}Banker;

void swap(char* a, char* b){
    char t;
    t=*a;
    *a=*b;
    *b=t;
}

//初始化牌数组
void init_cards(char* cards, int N)
{
    int i,j,k;
    for(i=0; i<N; ++i){
        for(k=0; k<4; ++k){
            cards[i*52+k*13]='A';
            for(j=1; j<9; ++j)
                cards[i*52+k*13+j]='1'+j;
            cards[i*52+k*13+9]='T';
            cards[i*52+k*13+10]='J';
            cards[i*52+k*13+11]='Q';
            cards[i*52+k*13+12]='K';
        }
    }
}

//洗牌
void shuffle_cards(char* cards, int N)
{
    srand((unsigned) time(NULL));
    int i;
    for(i=0; i<N*52; ++i){
        int pa, pb;
        pa=rand()%(N*52);
        pb=rand()%(N*52);
        swap(&cards[pa],&cards[pb]);
    }
}

//发牌
void first_deal(char* cards, int* ppos, Banker* pbanker, Player(*pplayers)[], int pNum){
    pbanker->mycards[0]=cards[(*ppos)++];
    pbanker->mycards[1]=cards[(*ppos)++];
    pbanker->count=2;
    pbanker->state='d';
    int i;
    for(i=0; i<pNum-1; ++i){
        if((*pplayers)[i].account>=0){
            (*pplayers)[i].mycards[0]=cards[(*ppos)++];
            (*pplayers)[i].mycards[1]=cards[(*ppos)++];
            (*pplayers)[i].count=2;
        }
    }
}

//每一轮的初始化
void round_init(Banker* pbanker, Player(*players)[], int pNum){
    pbanker->count=0;
    pbanker->points=0;
    pbanker->state='d';
    memset(pbanker->mycards,0,sizeof(pbanker->mycards));
   
    int i;
    for(i=0; i<pNum-1; ++i){
        Player* me=&(*players)[i];
        me->count=0;
        memset(me->mycards,0,sizeof(me->mycards));
        me->mybets=0;
        me->points=0;
        me->state=0;
    }
}

/*玩家1首轮动作
*  参数:tmpcards,临时数组,存依次放首轮
*          从庄家到每个玩家的牌,如果庄家第
*          二张牌是X,表示该牌是暗牌
*        len,该数组的长度
*  返回值,代表每个玩家给出的动作,
*        i,代表买保险,
*        h,代表继续拿牌,
*        s,代表停牌,
*        d,代表加倍,
*        u,代表投降
*/
char first_action1(char* tmpcards, int len){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    printf("请选择动作:\nh:拿牌;i:买保险;s:停牌;d:加倍;u:投降\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

/*玩家2首轮动作
*  参数:tmpcards,临时数组,存依次放首轮
*          从庄家到每个玩家的牌,如果庄家第
*          二张牌是X,表示该牌是暗牌
*        len,该数组的长度
*  返回值,代表每个玩家给出的动作,
*        i,代表买保险,
*        h,代表继续拿牌,
*        s,代表停牌,
*        d,代表加倍,
*        u,代表投降
*/
char first_action2(char* tmpcards, int len){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    //c=getchar();
    c='d';
    /******************************/
    return c;
}

/*玩家3首轮动作
*  参数:tmpcards,临时数组,存依次放首轮
*          从庄家到每个玩家的牌,如果庄家第
*          二张牌是X,表示该牌是暗牌
*        len,该数组的长度
*  返回值,代表每个玩家给出的动作,
*        i,代表买保险,
*        h,代表继续拿牌,
*        s,代表停牌,
*        d,代表加倍,
*        u,代表投降
*/
char first_action3(char* tmpcards, int len){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    c=getchar();
    /******************************/
    return c;
}

/*玩家4首轮动作
*  参数:tmpcards,临时数组,存依次放首轮
*          从庄家到每个玩家的牌,如果庄家第
*          二张牌是X,表示该牌是暗牌
*        len,该数组的长度
*  返回值,代表每个玩家给出的动作,
*        i,代表买保险,
*        h,代表继续拿牌,
*        s,代表停牌,
*        d,代表加倍,
*        u,代表投降
*/
char first_action4(char* tmpcards, int len){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    c=getchar();
    /******************************/
    return c;
}

/*玩家5首轮动作
*  参数:tmpcards,临时数组,存依次放首轮
*          从庄家到每个玩家的牌,如果庄家第
*          二张牌是X,表示该牌是暗牌
*        len,该数组的长度
*  返回值,代表每个玩家给出的动作,
*        i,代表买保险,
*        h,代表继续拿牌,
*        s,代表停牌,
*        d,代表加倍,
*        u,代表投降
*/
char first_action5(char* tmpcards, int len){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    c=getchar();
    /******************************/
    return c;
}

//抓一张牌
char getcard(const char* cards, int* ppos){
    return cards[(*ppos)++];
}

//第1个玩家下注
int bet1(){
    int mybet;
    scanf("%d",&mybet); //正式发布时学生需要替换成自己的业务逻辑,通过一些判断来决定下注的大小
    return mybet;
}

//第2个玩家下注
int bet2(){
    int mybet;
    scanf("%d",&mybet); //正式发布时学生需要替换成自己的业务逻辑,通过一些判断来决定下注的大小
    return mybet;
}

//第3个玩家下注
int bet3(){
    int mybet;
    scanf("%d",&mybet); //正式发布时学生需要替换成自己的业务逻辑,通过一些判断来决定下注的大小
    return mybet;
}

//第4个玩家下注
int bet4(){
    int mybet;
    scanf("%d",&mybet); //正式发布时学生需要替换成自己的业务逻辑,通过一些判断来决定下注的大小
    return mybet;
}

//第5个玩家下注
int bet5(){
    int mybet;
    scanf("%d",&mybet); //正式发布时学生需要替换成自己的业务逻辑,通过一些判断来决定下注的大小
    return mybet;
}

/*玩家1后续动作
*  参数:无
*  返回值,代表每个玩家给出的动作,
*        h,代表继续拿牌,
*        s,代表停牌,
*/
char continue_action1(Player(*players)[]){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    Player* me=&(*players)[0];
    printf("玩家%s当前持有的牌为:", me->name);
    int i;
    for(i=0;i<me->count;++i)
        printf("%c ", me->mycards[i]);
    printf("\n请选择下一步动作:\nh:拿牌;s:停牌\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

/*玩家2后续动作
*  参数:无
*  返回值,代表每个玩家给出的动作,
*        h,代表继续拿牌,
*        s,代表停牌,
*/
char continue_action2(){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    printf("请选择动作:\nh:拿牌;s:停牌\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

/*玩家3后续动作
*  参数:无
*  返回值,代表每个玩家给出的动作,
*        h,代表继续拿牌,
*        s,代表停牌,
*/
char continue_action3(){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    printf("请选择动作:\nh:拿牌;s:停牌\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

/*玩家4后续动作
*  参数:无
*  返回值,代表每个玩家给出的动作,
*        h,代表继续拿牌,
*        s,代表停牌,
*/
char continue_action4(){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    printf("请选择动作:\nh:拿牌;s:停牌\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

/*玩家5后续动作
*  参数:无
*  返回值,代表每个玩家给出的动作,
*        h,代表继续拿牌,
*        s,代表停牌,
*/
char continue_action5(){
    char c; //该变量是用于返回不同状态的字符
    /******************************/
    /***这里应该有自己的业务逻辑***/
    printf("请选择动作:\nh:拿牌;s:停牌\n");
    c=getche();
    //    c='h';
    /******************************/
    return c;
}

//第i个玩家买保险后,玩家及庄家所需做的动作
//参数:
//        banker,指向庄家的指针
//        i,第i个玩家
//        Player(*players)[],指向玩家数组的指针
//        tmpcards,当前已经发放的牌存放的数组
void insurance(Banker* pbanker, int i, Player(*players)[], char* tmpcards){
    Player* me=&(*players)[i];
    if(me->account>=0){
        me->account-=me->mybets/2; //扣除保险金
        char t=pbanker->mycards[1]; //获取庄家的第二张牌
        if(t=='T'||t=='J'||t=='Q'||t=='K') { //满足条件则设置为明牌
            tmpcards[1]=pbanker->mycards[1];
            pbanker->state='l';
        }
    }
}

//第1个玩家继续拿牌
//参数:
//        Player(*players)[],指向玩家数组的指针
//        card,当前拿到的牌
//        pbanker,指向庄家的指针
void hit1(Player(*players)[], char card, Banker* pbanker){
    Player* me=&(*players)[0];
//    if(me->account>=0){
        me->mycards[me->count++]=card;
        int bkp=calculate(pbanker->mycards,pbanker->count);
        int myp=calculate(me->mycards,me->count);
        //需要删除下面这句话
        int i;
        for(i=0; i<me->count; ++i)
            printf("%c ", me->mycards[i]);
        printf("\n");
        //删除到此为止
//        if(bkp<=21&&myp<bkp||myp<17){
//            me->state='h';
//        }else{
//            me->state='s';
//        }
//    }else
//        me->state='s';
}

//第2个玩家继续拿牌
//参数:
//        Player(*players)[],指向玩家数组的指针
//        card,当前拿到的牌
//        pbanker,指向庄家的指针
void hit2(Player(*players)[], char card, Banker* pbanker){
    Player* me=&(*players)[1];
    if(me->account>=0){
        me->mycards[me->count++]=card;
        int bkp=calculate(pbanker->mycards,pbanker->count);
        int myp=calculate(me->mycards,me->count);
        if(bkp<=21&&myp<bkp||myp<17){
            me->state='h';
        }else{
            me->state='s';
        }
    }
}

//第3个玩家继续拿牌
//参数:
//        Player(*players)[],指向玩家数组的指针
//        card,当前拿到的牌
//        pbanker,指向庄家的指针
void hit3(Player(*players)[], char card, Banker* pbanker){
    Player* me=&(*players)[2];
    if(me->account>=0){
        me->mycards[me->count++]=card;
        int bkp=calculate(pbanker->mycards,pbanker->count);
        int myp=calculate(me->mycards,me->count);
        if(bkp<=21&&myp<bkp||myp<17){
            me->state='h';
        }else{
            me->state='s';
        }
    }
}

//第4个玩家继续拿牌
//参数:
//        Player(*players)[],指向玩家数组的指针
//        card,当前拿到的牌
//        pbanker,指向庄家的指针
void hit4(Player(*players)[], char card, Banker* pbanker){
    Player* me=&(*players)[3];
    if(me->account>=0){
        me->mycards[me->count++]=card;
        int bkp=calculate(pbanker->mycards,pbanker->count);
        int myp=calculate(me->mycards,me->count);
        if(bkp<=21&&myp<bkp||myp<17){
            me->state='h';
        }else{
            me->state='s';
        }
    }
}

//第5个玩家继续拿牌
//参数:
//        Player(*players)[],指向玩家数组的指针
//        card,当前拿到的牌
//        pbanker,指向庄家的指针
void hit5(Player(*players)[], char card, Banker* pbanker){
    Player* me=&(*players)[4];
    if(me->account>=0){
        me->mycards[me->count++]=card;
        int bkp=calculate(pbanker->mycards,pbanker->count);
        int myp=calculate(me->mycards,me->count);
        if(bkp<=21&&myp<bkp||myp<17){
            me->state='h';
        }else{
            me->state='s';
        }
    }
}

//第i个玩家加倍
//参数:
//        i,第i个玩家
//        Player(*players)[],指向玩家数组的指针
//        card,加倍之后拿到的牌
void dbl(int i, Player(*players)[], char card){
    Player* me=&(*players)[i];
    if(me->account>=0){
        me->account-=me->mybets;
        me->mybets*=2;
        me->mycards[me->count++]=card;
        me->state='s';
    }
}

//第i个玩家投降
//参数:
//        i,第i个玩家
//        Player(*players)[],指向玩家数组的指针
void surrender(int i, Player(*players)[]){
    Player* me=&(*players)[i];
    if(me->account>=0){
        me->account+=me->mybets/2;
        me->mybets=0;
        me->state='u';
    }
}

//第i个玩家犯规(违规),赌注没收
//参数:
//        i,第i个玩家
//        Player(*players)[],指向玩家数组的指针
void foul(int i, Player(*players)[]){
    Player* me=&(*players)[i];
    if(me->account>=0){
        me->mybets=0;
        me->state='w';
    }
}

//根据牌计算总点数
//参数:
//        mycards,待计算的扑克牌数组
//        len,数组长度
//返回值:计算得到的点数
int calculate(char(*mycards)[20] , int len){
    int i, point=0, Acnt=0;
    for(i=0; i<len; ++i){
        if((*mycards)[i]>='2'&&(*mycards)[i]<='9')
            point+=(*mycards)[i]-'0';
        else if((*mycards)[i]=='T'||(*mycards)[i]=='J'||(*mycards)[i]=='Q'||(*mycards)[i]=='K')
            point+=10;
        else if((*mycards)[i]=='A')
            Acnt++;
    }
    for(i=Acnt; i>1; --i){ //如果有多个A,则除了最后一个,其他只能记作1点
        point++;
    }
    if(i==1){ //还剩一个A
        if(point<=10) {
            point+=11;
        }else{
            point++;
        }
    }
    return point;
}

//庄家的后续处理
//参数:
//        banker,指向庄家的指针
//        cards,扑克牌数组
//        ppos,指向当前已经发牌的位置的指针
void banker_continue(Banker* pbanker, const char* cards, int* ppos){
    pbanker->count=2;
    while(calculate(&pbanker->mycards, pbanker->count)<17){
        pbanker->mycards[pbanker->count++]=getcard(cards, ppos);
    }
    pbanker->points=calculate(&(pbanker->mycards), pbanker->count);
}

//比较大小,对赌注进行分配
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void judge(Banker* pbanker, Player(*players)[], int pNum, int* palive, int* ptotal_round){
    int i,dead=0;
    *ptotal_round++;
    for(i=0; i<pNum-1; ++i){
        Player* me=&(*players)[i];
        if(me->account>=0){
            me->rounds++;
            if(me->state=='i'&&pbanker->state!='l'){ //已经买保险,且猜中!
                me->account+=me->mybets*2;
                break;
            }
            if(me->points>21){ //玩家爆掉
                break;
            }else if(pbanker->points>21){ //玩家没爆,庄家爆,玩家赢
                me->account+=me->mybets*2;
                break;
            }else{ //都没爆,比大小
                if(me->points>pbanker->points)
                    me->account+=me->mybets*2;
                else if(me->points==pbanker->points)
                    me->account+=me->mybets;
                break;
            }
        }else{
            dead++;
        }
    }
    *palive=pNum-1-dead;
   
    printf("庄家本轮牌型如下:\n");
    for(i=0; i<pbanker->count; ++i){
        printf("%c ", pbanker->mycards[i]);
    }
    printf("\n");
   
    for(i=0; i<pNum-1; ++i){ //显示每个玩家本轮结果
        Player* me=&(*players)[i];
        if(me->account>=0){
            printf("%s本轮结果如下:\n",me->name);
            printf("剩余赌资:%d\n", me->account);
            int j;
            for(j=0; j<me->count; ++j)
                printf("%c ", me->mycards[j]);
            printf("\n");
        }
    }
}

//玩家1看所有人的牌
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void show1(Banker* pbanker, Player(*players)[], int pNum){
   
}

//玩家2看所有人的牌
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void show2(Banker* pbanker, Player(*players)[], int pNum){
   
}

//玩家3看所有人的牌
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void show3(Banker* pbanker, Player(*players)[], int pNum){
   
}

//玩家4看所有人的牌
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void show4(Banker* pbanker, Player(*players)[], int pNum){
   
}

//玩家5看所有人的牌
//参数:
//        pbanker,指向庄家的指针
//        Player(*players)[],指向玩家数组的指针
//        pNum,总人数(含庄家)
void show5(Banker* pbanker, Player(*players)[], int pNum){
   
}

int cmp(const void* p1, const void* p2){
    Player* player1=(Player*)p1;
    Player* player2=(Player*)p2;
    if(player1->account>=0&&player2->account>=0){
        if(player1->account>player2->account) return 1;
        else if(player1->account<player2->account) return -1;
        else if(player1->account==player2->account){
            if(player1->rounds>player2->rounds) return 1;
            else if(player1->rounds<player2->rounds) return -1;
            else if(player1->rounds==player2->rounds) return 0;
        }
    }else if(player1->account>=0) return 1;
    else if(player2->account>=0) return -1;
    else{
        if(player1->rounds>player2->rounds) return 1;
        else if(player1->rounds<player2->rounds) return -1;
        else return 0;
    }
}

//显示最终玩牌的结果,先按照赌资排序,赌资相同的按照轮次排序
void show_result(Player(*players)[], int pNum){
    qsort((*players),pNum-1,sizeof(Player),cmp);
    int i;
    for(i=0; i<pNum-1; ++i){
        Player* me=&(*players)[i];
        printf("玩家%s排名第%d,成绩如下:\n", me->name, i+1);
        printf("账户中剩余赌资:%d\n", me->account);
        printf("已经玩了%d轮。\n\n", me->rounds);
    }
}

void show_cards(const char* cards, int N){
    int i,j,k;
    for(k=0; k<N; ++k){
        printf("%d:========================\n",k+1);
        for(i=0; i<4; ++i){
            for(j=0; j<13; ++j)
                printf("%c ",cards[i*13+j+k*52]);
            printf("\n");
        }
    }
}

int main(int argc, char *argv[])
{
    int pos=0, pNum, i, N, cnt, alive, turns=0, total_rounds=0, threshold;
    Banker banker;
    printf("请输入多少个人玩(2-6):");
    scanf("%d",&pNum);
    alive=pNum-1;
    Player players[pNum];
    for(i=0; i<pNum-1; ++i){
        printf("请输入第%d个玩家的昵称(不要有空格):",i+1);
        scanf("%s",players[i].name);
        memset(players[i].mycards,0,sizeof(players[i].mycards));
        players[i].rounds=0;
        players[i].account=TOTAL_MONEY;
    }
    printf("请输入需要多少副扑克牌(4-8):");
    scanf("%d",&N);
    threshold=N*52*4/3;
    char* cards=malloc(52*N);
    init_cards(cards, N);
    shuffle_cards(cards, N);
    turns++;
    do{
        if(pos>=threshold){
            init_cards(cards, N);
            shuffle_cards(cards, N);
            turns++;
        }
        
        if(turns==5) break;
        
        round_init(&banker, &players, pNum);
        int (*betsarr[])()={bet1,bet2,bet3,bet4,bet5};
   
        //各个玩家依次下注
        for(i=0; i<pNum-1; ++i){
            if(players[i].account>=0){
                printf("请玩家%s下注:",players[i].name); //正式发布时需要删除该句话
                int mybet=betsarr[i]();
                players[i].mybets=mybet;
                players[i].account-=mybet;
            }
        }
        char tmpcards[pNum*2]; //用于存储给所有人看的首次已经发放的牌,暗牌用X表示
        memcpy(tmpcards, &cards[pos], sizeof(tmpcards));
        first_deal(cards, &pos, &banker, &players, pNum); //首轮发牌
        /***********这段代码后续删除*************/
        printf("庄家:%c  %c\n", banker.mycards[0], banker.mycards[1]);
        for(i=0; i<pNum-1; ++i)
            printf("玩家%d:%c  %c\n",i+1,players[i].mycards[0],players[i].mycards[1]);
        printf("目前已经发放到的位置:%d\n",pos);
        /************************/
        char t=tmpcards[0];
        if(!((t=='T'||t=='J'||t=='Q'||t=='K')&&tmpcards[1]=='A'))
            tmpcards[1]='X'; //设置暗牌
        /*********删除***************/
        for(i=0; i<pNum*2; ++i)
            printf("%c ",tmpcards[i]);
        printf("\n");
        /************************/
        char (*first_action_arr[])(char*, int)={first_action1, first_action2, first_action3,
            first_action4, first_action5};
        for(i=0; i<pNum-1; ++i){
            players[i].state=first_action_arr[i](tmpcards, sizeof(tmpcards));
        }
        void (*hitarr[])(Player(*players)[], char, Banker*)={hit1, hit2, hit3, hit4, hit5};
        for(i=0; i<pNum-1; ++i){
            char c;
            int point=calculate(&players[i].mycards,players[i].count);
            if(point>21){
                players[i].state='s';
            }
            switch (players[i].state){
                case 'i': //保险
                    printf("进入i分支\n");
                    if(tmpcards[0]!='A'){
                        players[i].state='w'; //违规
                    }else{
                        insurance(&banker, i, &players, tmpcards);
                    }
                    break;
                case 'h': //拿牌
                    printf("进入h分支\n");
                    c=getcard(cards, &pos);
                    hitarr[i](&players,c,&banker);
                    point=calculate(&players[i].mycards,players[i].count);
                    if(point>21){
                        players[i].state='s';
                    }
                    break;
                case 's': //停牌
                    printf("进入s分支\n");
                    break;
                case 'd': //加倍
                    printf("进入d分支\n");
                    c=getcard(cards, &pos);
                    dbl(i,&players,c);
                    break;
                case 'u': //投降
                    printf("进入u分支\n");
                    surrender(i,&players);
                    break;
                default: //违规
                    printf("进入w分支\n");
                    foul(i,&players);
                    break;
            }
        }
        char (*continue_actions[])()={continue_action1, continue_action2, continue_action3,
            continue_action4, continue_action5};
        do{
            for(i=0; i<pNum-1; ++i){
                char c;
                int point=calculate(&players[i].mycards,players[i].count);
                if(players[i].account>=0&&players[i].state!='s'){
                    players[i].state=continue_actions[i](&players[i]);
                }
                if(point>21){
                    players[i].state='s';
                }
                switch (players[i].state){
                    case 'h': //拿牌
                        printf("进入h分支\n");
                        c=getcard(cards, &pos);
                        hitarr[i](&players,c,&banker);
                        point=calculate(&players[i].mycards,players[i].count);
                        if(point>21){
                            players[i].state='s';
                        }
                        break;
                    case 's': //停牌
                        printf("进入s分支\n");
                        break;
                    default: //违规
                        printf("进入w分支\n");
                        foul(i,&players);
                        break;
                }
            }
            //统计拿牌指令个数,存入cnt
            cnt=0;
            for(i=0; i<pNum-1; ++i)
                if(players[i].state=='h') cnt++;
        }while(cnt>0);
        
        //庄家做后续处理
        banker_continue(&banker, cards, &pos);
        
        //计算每个人的点数
        for(i=0; i<pNum-1; ++i){
            players[i].points=calculate(&players[i].mycards, players[i].count);
        }
        
        //比较庄家与每个人的点数,更新每个人的账户
        judge(&banker, &players, pNum, &alive, &total_rounds);
        
        void (*show_arr[])(Banker*, Player(*players)[], int)={show1, show2, show3, show4, show5};
        //让每个人看到本轮目前所有人的牌
        for(i=0; i<pNum-1; ++i){
            show_arr[i](&banker, &players, pNum);
        }
    }while(alive>0&&total_rounds<100);
   
    //显示最终结果
    show_result(&players, pNum);
     
//    show_cards(cards, N);
    return 0;
}

[此贴子已经被作者于2017-9-4 18:26编辑过]

搜索更多相关主题的帖子: char int Player 代表 printf 
2017-09-04 13:38
快速回复:求大神给补充完整这个21点游戏完整版程序(C语言带解释)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019860 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved