diff --git a/head.h b/head.h new file mode 100644 index 0000000..881bf78 --- /dev/null +++ b/head.h @@ -0,0 +1,44 @@ +#ifndef __HEAD_H__ +#define __HEAD_H__ +#define MAXLEVEL 15 +typedef struct CARD{ + int number; + int level; + char *flower; + char point; +}card;//卡 + +typedef struct DECK{ + int top; + int arr[55]; +}deck;//牌堆 + +typedef struct PLAYERS{ + int id; + int status; + card handcard[21]; + int size; +}players;//玩家 + +typedef struct GAMES{ + int type; + int level; + int sum; + int who; + int count; + int arr[16]; +}games;//桌面 + +typedef struct BUFFERS{ + int arr[16]; + int brr[20]; + int sum; +}buffers;//出牌缓冲区 +/*--------------------------------*/ +void game_init(); +void turning(); +void handcard_sort(); +void print(); +int win(); +void turn_switch(); +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..7040831 --- /dev/null +++ b/main.c @@ -0,0 +1,25 @@ +#include +#include"head.h" +int main(){ + while(1){ + int which; + game_init();//初始化游戏 + while(1){ + turning();//回合进行中 + printf("\n\n\n"); + if(which=win())//是否产生胜者 + break; + turn_switch();//切换出牌方 + } + printf("胜负已出!胜利者是玩家%d\n",which+1); + printf("是否重新游戏?(y为继续,其它退出程序):"); + char choice; + scanf("%c",&choice); + scanf("%*[^\n]"); + scanf("%*c"); + if(choice == 'y'||choice =='Y') + continue; + break; + } + printf("谢谢试玩\n"); +} diff --git a/op.c b/op.c new file mode 100644 index 0000000..7c76014 --- /dev/null +++ b/op.c @@ -0,0 +1,576 @@ +#include +#include +#include"head.h" +#include +#include + + +static int type_buffer(); +static char point[]={'0','3','4','5','6','7','8','9','X','J','Q','K','A','2','w','W'}; +static char *farr[]={"方片","梅花","红桃","黑桃"}; +static char* type_arr[]={"弃权","单张","对子","王炸","骷髅","骷髅单","炸弹","骷髅对","炸带单","顺子","炸带一对","飞机不带","连对","飞机单","飞机带对"}; +static char* sta_arr[2]={"农民","地主"}; +static players player[3];//玩家 +static games game; + +/* 洗牌堆 */ +static deck* deck_init(){ + int i,j; + srand(time(0)); + deck *p_deck=(deck*)malloc(sizeof(deck)); + if(!p_deck){ + printf("分配内存失败\n"); + return NULL; + } + for(i=1;i<=54;i++){ + p_deck->arr[i]=rand()%54; + for(j=1;jarr[i]==p_deck->arr[j]){ + i--; + break; + } + } + } + p_deck->top=54; + return p_deck; +} + +/* 初始化玩家(洗牌,id,身份 手牌,总数) */ +static void player_init(){ + int i,j; + for(j=0;j<3;j++){ + for(i=1;i<=20;i++){ + player[j].handcard[i].number=100; + player[j].handcard[i].level =0; + } + } + deck *p=deck_init(); + if(!p){ + printf("没有牌堆\n"); + return ; + } + int which=0; + which=rand()%3; + game.who=which; + for(i=0;i<3;i++){ + player[i].id=i; + if(i==which){//地主 + player[i].status=1; + for(j=1;j<=20;j++){ + player[i].handcard[j].number=p->arr[(p->top)--]; + } + player[i].size=20; + } + else{//农民 + player[i].status=0; + for(j=1;j<=17;j++){ + player[i].handcard[j].number=p->arr[(p->top)--]; + } + player[i].size=17; + } + } + free(p); + p=NULL; +} + +/* 手牌信息补完 */ +static void handcard_init(){ + int i,j; + for(i=0;i<3;i++){ + for(j=1;j<=20;j++){ + int number=player[i].handcard[j].number; + int *p_level=&(player[i].handcard[j].level); + char **pp_flower=&(player[i].handcard[j].flower); + char *p_point=&(player[i].handcard[j].point); + if(number>=0&&number<=51){ + *p_level=number/4+1; + *p_point=point[number/4+1]; + *pp_flower=farr[number%4]; + } + else if(number==52){ + *p_level=14; + *p_point='w'; + *pp_flower="小王"; + } + else if(number==53){ + *p_level=15; + *p_point='W'; + *pp_flower="大王"; + } + else { + *p_level=0; + *p_point=' '; + *pp_flower=" "; + } + } + } +} + +/* 打印当前玩家手牌 */ +void print(){ + int i,j; + for(i=0;i<3;i++){ + if (i!=game.who) continue; + for(j=1;j<=player[i].size;j++){ + //printf("======"); + if(player[i].handcard[j].number == 100){ + printf(" "); + } + else { + char *p_tmp=player[i].handcard[j].flower; + printf("%s ",p_tmp); + } + } + printf("\n"); + for(j=1;j<=player[i].size;j++){ + if(player[i].handcard[j].number == 100){ + printf(" "); + } + else { + printf(" %c ",player[i].handcard[j].point); + } + } + } + printf("\n"); + for(j=1;j<=player[game.who].size;j++){ + if(! (j>9)) + printf("(%d) ",j); + else + printf("(%d) ",j); + } + printf("\n"); +} + +/* 游戏初始化 */ +void game_init(){ + game.count=2;//弃权次数 + player_init();//洗牌 发牌 + handcard_init();//手牌信息补完 +} + +int fcmp(const void *pa,const void *pb){//升序 + return *(int*)pa-*(int*)pb; +} + +static void rehandcard_sort(players *p_player,int* p_number){//真正的排序函数 + int *base=p_number; + size_t nmemb=p_player->size; + size_t size= sizeof(card); + qsort(base,20,size,fcmp); +} + +void handcard_sort(){//外壳排序函数 + rehandcard_sort(&player[0],&(player->handcard[1].number)); + rehandcard_sort(&player[1],&((player+1)->handcard[1].number)); + rehandcard_sort(&player[2],&((player+2)->handcard[1].number)); +} + +/* 询问是否出牌 */ +static int require(){ //1表示出牌 0表示弃权 + if(game.type == 3 ){ + if(game.count != 2){ + printf("要不起!\n"); + return 0; + } + else + return 1; + } + if(game.count !=2){ + printf("出牌吗?(y表示出牌,n弃权):"); + char choice; + scanf("%c",&choice); + scanf("%*[^\n]"); + scanf("%*c"); + if(choice == 'n' || choice == 'N'){ + return 0; + } + else return 1; + } else { + printf("继续出牌\n"); + return 1; + } +} + +buffers buffer={0};//出牌缓冲区 + +/* 清空出牌缓冲区 */ +static void reset(){ + int a; + for(a=0;a<16;a++) buffer.arr[a]=0; + + for(a=0;a<20;a++) buffer.brr[a]=0; + + buffer.sum=0; +} + +/* 放牌进入缓冲区 */ +static void buffer_put(){ + char intput[40]={0};//把字符串转换为数字 + int brr[20]={0}; + int i=0; + int j; + int sum; + int flag=0; + while(1){ + reset(); + sig: + printf("请输入要放的牌...:"); + fgets(intput,40,stdin); + if(strlen(intput)==39&&intput[38]!='\n'){ + scanf("%*[^\n]"); + scanf("%*c"); + } + for(j=0,i=0,sum=0;i='0'&&intput[i]<='9'){ + sum=sum*10+(intput[i]-'0'); + flag=1; + } + else { + if(flag) + brr[j] = sum; + sum=0; + j++; + flag=0; + } + } + int k; + printf("要出: "); + for(k=0;brr[k];k++) printf("%d ",brr[k]); + + printf("号牌\n"); + + int who = game.who; + players* p_player=&(player[who]); + + int index; + for(i=0;brr[i];i++){//记录出的牌是什么 + index=brr[i]; + if(index>(p_player->size) || index<=0 ){//输入的字符串范围有误 + printf("输入内容超出范围,重新输入\n"); + goto sig; + } + else{ + int level=p_player->handcard[index].level; + ++(buffer.arr[level]); + buffer.brr[i] =brr[i]; + } + } + for(i=1;i<=15;i++) buffer.sum+=buffer.arr[i];//记录出了多少张牌 + + char aff= 'N'; + int type = type_buffer(); + if(type != -1) + printf("要出的类型是:%s\n\n",type_arr[type]); + else { + printf("不存在此类型的牌\n\n"); + reset(); + return; + } + printf("确定要这样出吗?(确定输入y,否则按其它)"); + scanf("%c",&aff); + scanf("%*[^\n]"); + scanf("%*c"); + if(aff == 'y' || aff =='Y') break; + } +} + +static void turnstart(){ + char u; + printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==============================================================小浩斗地主======================================================\n\n\n\n\n"); + printf("轮到下一家"); + scanf("%c",&u); + int i; + printf("\n\n\n\n\n\n\n牌面张数为%d张\n",game.sum); + printf("牌面类型为: %s%c\n",type_arr[game.type],point[game.level]); + printf("=============================================================%s的回合==========================================================\n\n",sta_arr[player[game.who].status]); + printf("现在轮到玩家%d",game.who+1); + printf(" 玩家1(%s)手牌%d ",sta_arr[player[0].status],player[0].size);if(game.who==0) printf("<=====\n");else printf("\n"); + printf(" 玩家2(%s)手牌%d ",sta_arr[player[1].status],player[1].size);if(game.who == 1) printf("<=====\n"); else printf("\n"); + printf(" 玩家3(%s)手牌%d ",sta_arr[player[2].status],player[2].size);if(game.who == 2) printf("<=====\n"); else printf("\n"); +} + +/* 判断是否连续 */ +static int continuum(int num,int total){ + int i,count=0; + int flag=0;//有值则标记为1 + int sig=0;//从 有到无 改标记为1 + for(i=1;i<=15;i++){ + if(buffer.arr[i]==num){ + if(sig) return 0;//非连续 + + count++; + if(count==total) return 1;//连续 + + flag=1; + }else { + if (flag) sig=1; + } + } +} + +static bool if_repeat_card(int *arr, int totalCount) { + int i, j; + for (i=0;arr[i]!=0 && i+1=6){ + if((!one) && (pair == 1) && (!triple) && (quattuor == 1) )//炸带对 + return 10; + else if(!one && !pair && !quattuor){//只有2个以上个三张相同 飞机不带 + if(continuum(3,triple))//所有3连续 + return 11; + else return -1; + } + else if(!one && !triple && !quattuor){//连对 + if(continuum(2,pair)) + return 12; + else return -1; + } + else if(buffer.sum == 4*triple){//飞机单 + if(continuum(3,triple)) + return 13; + else return -1; + } + else if((buffer.sum == 5*triple) && (triple == pair)){//飞机对 + if(continuum(3,triple)) + return 14; + else return -1; + } + else if(!pair && !triple && !quattuor &&(!buffer.arr[14] && !buffer.arr[15])){ + if(continuum(1,one)) + return 9; + else return -1; + } + else return -1; + } +} + +/* 最大下标 */ +static int maxindex(int count){ + int i; + for (i=15;i>=1;i--){ + if(buffer.arr[i] == count) return i; + } +} + +/* 获取缓冲区牌类等级 */ +static int level_buffer(int type){ + switch(type){ + case 1: + return maxindex(1); + break; + case 2: + return maxindex(2); + break; + case 3: + return 15; + break; + case 4: + return maxindex(3); + break; + case 5: + return maxindex(3); + break; + case 6: + return maxindex(4); + break; + case 7: + return maxindex(3); + break; + case 8: + return maxindex(4); + break; + case 9: + return maxindex(1); + break; + case 10: + return maxindex(4); + break; + case 11: + return maxindex(3); + + break; + case 12: + return maxindex(2); + break; + case 13: + return maxindex(3); + break; + case 14: + return maxindex(3); + break; + } +} + +/* 消减手牌 */ +static void annealation(){ + int i=1; + int j=0; + int who=game.who; + for(i = 1,j=0;buffer.brr[j];i++,j++){ + int index = buffer.brr[j]; + player[who].handcard[index].number = 100; + player[who].size = player[who].size - 1; + } + game.sum=buffer.sum; + game.count=0; + handcard_sort(); + //printf("出牌成功\n"); +} + +/* 回合进行中 */ //这个模块有很大的修改空间 例如return 改为break... +void turning(){ + turnstart(); /* 开始阶段 */ + handcard_sort(); + print(); + int level= 0; + while(1){ + if(!require()){ + printf("\n\n\n\n\n\n\n\n不要\n"); + game.count++; + if(game.count == 2){ + game.type=0; + game.level=0; + game.sum=0; + } + return ; /* 开始阶段 */ + } + buffer_put(); /* 出牌阶段在这函数判断是否弃权比较好 */ + + int type = type_buffer(); + int level=level_buffer(type); + if(type == -1){ + printf("牌类非法!-----\n"); + continue; + } + if(type == 3){//王炸 + printf("\n\n\n\n\n王炸!!\n"); + annealation(); + game.type=3; + game.level=MAXLEVEL; + return ; + } + else if(type == 6){//炸弹 + if(game.type != 6){ + printf("\n\n\n\n炸弹\n"); + annealation(); + game.type = 6; + game.level = level_buffer(type); + return; + } + else { + if(level > game.level){ + printf("\n\n\n\n\n压死\n"); + annealation();//消减手牌 + game.type = 6; + game.level = level; + return; + } + else if(level < game.level||level == game.level){ + printf("牌的等级不够大\n"); + continue; + } + } + } + else if(game.count == 2 ){//两家弃权 + annealation(); + game.type = type; + game.level = level; + return ; + } + else {//除了炸弹 两家弃权 王炸 非法 以外的合理牌类 + if(type != game.type){ //不对应 + printf("类型不对应\n"); + continue; + } + else { //对应 + if(buffer.sum != game.sum){ + printf("数量不对应\n"); + continue; + } + if(level < game.level|| level==game.level){ + printf("牌的等级不够大\n"); + continue; + } + else if(level > game.level){ + printf("\n\n\n\n\n压死\n"); + annealation(); + game.type = type; + game.level = level; + return ; + } + } + } + } +} + +/* 0 1 2 3判断是否是谁胜利 0表示没有 1表示玩家一 */ +int win(){ + int now = game.who; + if(!player[now].size) + return now; + else return 0; +} + +/* 切换当前玩家为下家 */ +void turn_switch(){ + int who = game.who; + who++; + game.who = who%3; +}