求大神给补充完整这个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编辑过]