1. game.h
/* * Copyright (c) 2007, javaF.org * @author <a href="mailto:xhm_cn@hotmail.com">hyamine</a> */ #ifndef GAME_H #define GAME_H #include <pthread.h> #include <semaphore.h> #include <mysql.h> #define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5)) /* #include <malloc.h> #include <sys/time.h> #include <string.h> #include <stdio.h> */ #include "base64.h" #define GM_VERSION 1 /*游戏版本*/ #include "squid.h" #include "game_client_parse.h" #include "game_active.h" #include "game_db.h" #include "game_test.h" #include "game_req.h" #include "game_prot.h" #define GAME_NET_TIMEOUT 80 /*网络超时时间*/ #define ROOM_COUNT 4 /*房间数量*/ #define LEVEL_COUNT 3 /* 游戏协议游戏类型标识 目前只有 1=斗地主 */ #define GAME_TYPE_DDZ 0x01 #define MAX_NUMBER_TO_STRLEN 20 #define uint32 unsigned long int /* 最大游戏种类数 */ #define MAX_GAME_TYPE 5 /* 中英文信息提示 */ #define MESSAGE_LANGUAGE_COUNT 0x02 #define MESSAGE_LANGUAGE_EN 0x01 #define MESSAGE_LANGUAGE_CN 0x00 /* 默认语言设置 */ #define showGameOrderMessaeFlag 1 #define showMessagelanguage MESSAGE_LANGUAGE_CN /* int gameDEBUG(int); */ unsigned char game_type_run[MAX_GAME_TYPE+1]; /* 每个房间游戏桌数 */ #define MAX_DESK_COUNT 3000 /*释放游戏空间*/ void gxfree(void *); /* 斗地主的牌局信息 */ typedef struct _oppose_landocrat_playing_info oppose_landocrat_playing_info; /*进行中的游戏*/ int game_doing[ROOM_COUNT][MAX_DESK_COUNT]; #define MAX_SEQ_COUNT 0xFFFF unsigned int *csequence; unsigned int maxcSequence; float game_rate; /* 下列参数根据炸*弹出现的频率控制炸*弹数量 */ int minBombCount,maxBombCount,minbombFrq,maxbombFrq,noBomGCount; oppose_landocrat_playing_info ol_games[ROOM_COUNT][MAX_DESK_COUNT]; int is_init_game; /* 游戏桌 */ typedef struct _game_desk game_desk; /* 斗地主设置信息 */ struct _oppose_landocrat oppose_landocrat; /* 房间级别信息 */ typedef struct _root_level root_level; /*typedef enum {PS_NORMAL,PS_OFFLINE,PS_SYSTEM_PROXY} player_status;*/ /* 设置游戏 */ void set_oppose_landocrat(); PF requestTimeout; /* 按照牌型:4张,3张,一对,一张进行排序 前提条件:牌必须已经sort_card()排好序*/ void sort_card_by_type(unsigned char *,int); /* 排序 */ void sort_card(unsigned char *,int); /* 是否是指定的num顺 */ int cardsIsNumSequence(const unsigned char *,int,int); /* 从cards中获取count张同数值牌命中次数 */ int *getSameValueNum(unsigned char *,int,int); /* 斗地主游戏洗牌 */ int oppose_landocrat_shuffle(unsigned char *,int *,int); /* 斗地主游戏发牌 */ int oppose_landocrat_deal(oppose_landocrat_playing_info *); void init_game(); void destroy_game(); int addGame(oppose_landocrat_playing_info *); void removeGame(oppose_landocrat_playing_info *); void resetPlayInfo(oppose_landocrat_playing_info *); /* 系统自动出牌 */ unsigned char * systemAutoDiscard(oppose_landocrat_playing_info *,int *); /* 斗地主游戏出牌 */ int oppose_landocrat_sendcard(oppose_landocrat_playing_info *,unsigned char *,unsigned char); /* 斗地主游戏发底牌 */ void oppose_landocrat_deal_remain(oppose_landocrat_playing_info *); #include "player.h" /* 牌型 */ typedef enum { CARD_TYPE_ERROR, /* 错误牌型 */ CARD_TYPE_SIGNAL, /* 单张牌 01 */ CARD_TYPE_DOUBLE, /* 一对牌 02 */ CARD_TYPE_ROCKET, /* 火箭(一对王) 03 */ CARD_TYPE_THREE, /* 三张牌 04 */ CARD_TYPE_THREE_SIGNAL, /* 三带一 05 */ CARD_TYPE_THREE_DOUBLE, /* 三带一对 06 */ CARD_TYPE_FOUR_BOMB, /* 炸*弹 07 */ CARD_TYPE_SEQUENCE_SIGNAL, /* 单顺 08 */ CARD_TYPE_SEQUENCE_DOUBLE, /* 双顺 09 */ CARD_TYPE_SEQUENCE_THREE, /* 三顺 10 */ CARD_TYPE_SEQUENCE_THREE_WINGS_SIGNAL, /* 飞机带翅膀:三顺+同数量的单牌 11 */ CARD_TYPE_SEQUENCE_THREE_WINGS_DOUBLE, /* 飞机带翅膀:三顺+同数量的对牌 12 */ CARD_TYPE_FOUR_DOUBLE_SIGNAL, /* 四带两个单牌 13 */ CARD_TYPE_FOUR_DOUBLE_DOUBLE /* 四带两对 14 */ } card_type; /* 分析牌型 */ card_type oppose_get_card_type(const unsigned char *,int); #include "card_op.h" /* 斗地主基本设置 */ struct _oppose_landocrat { int game_id; int player_count; /* 斗地主每局玩家数 */ int card_count; /* 斗地主每副牌数目 */ int card_set_count; /* 几副牌 */ int card_count_peer_player; /* 斗地主每局非地主玩家牌数 */ int card_count_for_landocrat; /* 斗地主每局非地主玩家牌数 */ int more_card_count_for_landocrat; /* 斗地主每局底牌数 */ int emperor_count; /* 王的数目 */ int room_counts; /* 房间等级数 */ root_level *rooms; /* 各个房间 */ }; /* 游戏房间等级 */ struct _root_level { unsigned char level; /* 当前房间等级 */ unsigned char score_counts; /* 当前房间分数的级别数目 */ int *score; /* 各个分数级别 */ int currentGameCount; int currentPlayerCount; int currentWaitPlayer; }; struct _game_desk { player **players; int desk_index; game_desk *next; game_desk *pre; }; /* 斗地主的牌局信息 */ struct _oppose_landocrat_playing_info { player **players; /* 参与的玩家 */ /*player_status *players_status;*/ /* 玩家的状态 */ int *fds; /* 每个玩家的socket fd */ /*unsigned char *cards; 洗过的牌 */ unsigned char card_landocrat_flag; /* 随机翻出的一张牌,谁拿到谁拥有作为地主的优先权 */ int landocrat; /* 地主 */ unsigned char *cards_deal_for_landocrat; /* 底牌 */ unsigned char **player_cards; /* 每个玩家所发的牌 */ unsigned char **player_remain_cards; /* 每个玩家剩余的牌 */ unsigned char *player_remain_count; /* 每个玩家剩余的牌数 */ int pre_player; /* 上一个出牌的玩家(用数据下标表示 -1 表示没有) */ int next_player; /* 下一出牌的玩家(用数据下标表示)*/ int room; /* 当前房间等级 */ int call_score; /* 叫分 */ int deskSeq; /* 桌号 */ unsigned char *pre_cards; /* 上一出牌玩家的出牌 */ unsigned int pre_card_count; /* 上一出牌玩家出牌的张数 */ card_type pre_card_type; /* 上一出牌玩家出牌的牌型 */ int bomb_counts; /* 玩家已炸的炸*弹数 */ }; #endif /* GAME_H */
2. game.c
/* * Copyright (c) 2007, javaF.org * @author <a href="mailto:xhm_cn@hotmail.com">hyamine</a> * * DEBUG: section 80 */ #include "game.h" /* 炸*弹限制 */ #define MAX_GAME_BC 100 static int gameMBoms[MAX_GAME_BC]; static int limbombFrq = MAX_GAME_BC; /* 不同级别房间的叫分差异 */ int game_roomlevel_score[ROOM_COUNT+1][LEVEL_COUNT] = {{0,0,0},{2,4,6},{5,10,15},{10,20,30},{20,40,60}}; /* 牌的ASCII值(详见doc/牌映射.xls) */ unsigned char cardsMap[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26, 27,28,29,30,31,32,33,34,35,36,37, 38,39,40,41,42,43,44,45,46,47,48, 53,54,55,56,57,61 }; /* 初始化 */ void init_game() { int i = 0,j = 0; minBombCount = 0; maxBombCount = 4; minbombFrq = 3; maxbombFrq = 5; noBomGCount = 0; bzero(&gactive,sizeof(game_active)); if(minbombFrq > limbombFrq) minbombFrq = limbombFrq; if(maxbombFrq > limbombFrq) maxbombFrq = limbombFrq; if(minbombFrq > maxbombFrq) minbombFrq = maxbombFrq; if(minBombCount > maxBombCount) minBombCount = maxBombCount; /*showGameOrderMessaeFlag = 1; showMessagelanguage = MESSAGE_LANGUAGE_CN; */ maxcSequence = MAX_SEQ_COUNT; game_rate = 0.03F; set_oppose_landocrat(); for(i = 1; i < MAX_GAME_TYPE; i++) { game_type_run[i] = 0; } game_type_run[1] = 1; /* 斗地主 */ for(i = 0; i< ROOM_COUNT; i++) { for(j = 0; j < MAX_DESK_COUNT; j++) { game_doing[i][j] = j; ol_games[i][j].deskSeq = -1; ol_games[i][j].players = (player **)xmalloc(sizeof(player *)*3); ol_games[i][j].fds = (int *)xmalloc(sizeof(int)*3); ol_games[i][j].player_remain_count = (unsigned char *)xmalloc(sizeof(unsigned char)*3); } } init_db_thread(); sleep(2); setClientReqMethod(); init_players(); } /* int gameDEBUG(char *fmt,char *msgCN,char *msgEN) { #if showGameOrderMessaeFlag == 1 #if showMessagelanguage == MESSAGE_LANGUAGE_EN debug(82,2)(fmt,msgEN); #else debug(82,2)(fmt,msgCN); #endif #endif } */ void destroy_game() { int i = 0,j = 0; root_level *level = oppose_landocrat.rooms; for(i = 0; i< ROOM_COUNT; i++) { for(j = 0; j < MAX_DESK_COUNT; j++) { xfree(ol_games[i][j].players); xfree(ol_games[i][j].fds); xfree(ol_games[i][j].player_remain_count); } } release_player(); releaseGameMessage(); for(i = 1; i <= oppose_landocrat.room_counts; i++) { /*xfree(level[i].score);*/ } xfree(level); } void gxfree(void *P) { if(P) xfree(P); } /* 斗地主游戏基本设置 */ void set_oppose_landocrat() { int i = 0; root_level *level; oppose_landocrat.player_count = 3; /* 设置玩家数目 */ oppose_landocrat.card_count = 54; /* 设置每副牌数目 */ oppose_landocrat.card_set_count = 1; /* 设置玩几副牌 */ oppose_landocrat.card_count_peer_player = 17; /* 斗地主每局非地主玩家牌数 */ oppose_landocrat.card_count_for_landocrat = 20; /* 斗地主每局非地主玩家牌数 */ oppose_landocrat.more_card_count_for_landocrat = 3; /* 斗地主每局底牌数 */ oppose_landocrat.emperor_count = 2; /* 王的数目 */ oppose_landocrat.room_counts = ROOM_COUNT; oppose_landocrat.game_id = 1; oppose_landocrat.rooms = xmalloc(sizeof(root_level)*(oppose_landocrat.room_counts+1)); level = oppose_landocrat.rooms; for(i = 1; i <= oppose_landocrat.room_counts; i++) { level[i].level = i; level[i].score_counts = 3; level[i].score = game_roomlevel_score[i]; /*xmalloc(sizeof(int)*(level[i].score_counts));*/ oppose_landocrat.rooms[i].currentGameCount = 0; oppose_landocrat.rooms[i].currentPlayerCount = 0; oppose_landocrat.rooms[i].currentWaitPlayer = 0; } setClientReqMethod(); /* 设置斗地主响应客户端处理方法 */ } int addGame(oppose_landocrat_playing_info *playing_info) { int room = gamePlayers[playing_info->fds[0]].game_room; int cGameCount = oppose_landocrat.rooms[room].currentGameCount; debug(82, 2)("%s:%s()\n",__FILE__,__FUNCTION__); debug(82, 2)("before add room=%d,cGameCount=%d\n",room,cGameCount); playing_info->deskSeq = cGameCount; cGameCount++; oppose_landocrat.rooms[room].currentGameCount = cGameCount; debug(82, 2)("before add room=%d,cGameCount=%d\n",room,oppose_landocrat.rooms[room].currentGameCount); return cGameCount; } void removeGame(oppose_landocrat_playing_info *playing_info) { if(playing_info) { int deskSeq = playing_info->deskSeq; int i = 0,j = 0; int room = playing_info->room; int cGameCount = oppose_landocrat.rooms[room].currentGameCount; if(room <= 0 || deskSeq < 0) return; debug(82, 2)("%s:%s()\n",__FILE__,__FUNCTION__); debug(82, 2)("before remove:\n"); debug(82, 2)("cGameCount= %d,deskSeq=%d\n",cGameCount,deskSeq); /* for(i = 0; i < 3; i++) { playing_info->players[i]->playing_info = NULL; playing_info->players[i] = NULL; } */ i = game_doing[room-1][cGameCount]; game_doing[room-1][cGameCount] = game_doing[room-1][deskSeq]; j = game_doing[room-1][deskSeq]; game_doing[room-1][deskSeq] = game_doing[room-1][cGameCount-1]; game_doing[room-1][cGameCount-1] = i; playing_info->deskSeq = -1; ol_games[room-1][game_doing[room-1][deskSeq]].deskSeq = deskSeq; cGameCount--; oppose_landocrat.rooms[room].currentGameCount = cGameCount; debug(82, 2)("after remove:\n"); debug(82, 2)("cGameCount= %d\n",cGameCount); } } /* 考虑性能和目前实际情况,以下所有功能暂时只实现一副牌的功能并且进行优化 */ /* 斗地主游戏洗牌 */ int oppose_landocrat_shuffle(unsigned char *cards,int *bombCard,int bombCount) { debug(82, 2) ("%s(%s,%d)\n",__FUNCTION__,__FILE__,__LINE__); int i,j; unsigned char tmpcard = 0; unsigned char rindex = 0; int card_num = 0; int setforBomb[14]; if(bombCount > 0) { for(i = 0; i < 14; i++) { setforBomb[i] = i; } for(i = bombCount - 1,j = 14; i >= 0; i--,j--) { rindex = rand() % j; bombCard[i] = setforBomb[rindex]; setforBomb[rindex] = setforBomb[j - 1]; } } /* 初始化牌: 3 -- A */ for(i = 0; i < 13; i++) { int isfit = 0; for(j = 0; j < bombCount; j++) { if(i == bombCard[j]) { bombCard[j] = bombCard[bombCount - 1]; bombCard[bombCount - 1] = i; isfit = 1; bombCount--; break; } } if(!isfit) for(j = 0; j < 4; j++) { cards[card_num] = cardsMap[i * 4 + j]; card_num++; } } /* 初始化牌: 小大王 */ if(bombCount == 0) { cards[card_num++] = cardsMap[52]; cards[card_num++] = cardsMap[53]; } /* 洗牌 */ for(i = card_num; i > 0; i--) { rindex = rand() % i; tmpcard = cards[i-1]; cards[i-1] = cards[rindex]; cards[rindex] = tmpcard; } return card_num; } unsigned char *oppose_landocrat_shuffle1() { debug(82, 2) ("%s(%s,%d)\n",__FUNCTION__,__FILE__,__LINE__); unsigned char i; unsigned char tmpcard = 0; unsigned char rindex = 0; unsigned char *cards = xmalloc(55); minBombCount = 0; maxBombCount = 5; if(!cards) { debug(80, 1) ("%s(%s,%d):洗牌分配内存错误\n",__FUNCTION__,__FILE__,__LINE__); return NULL; } /* 初始化牌: 3 -- A */ for(i = 0; i < 48; i++) { cards[i] = i + 1; } /* 初始化牌: 2 */ cards[48] = 53; cards[49] = 54; cards[50] = 55; cards[51] = 56; /* 初始化牌: 小大王 */ cards[52] = 57; cards[53] = 61; /* 结束标志 */ cards[54] = 0; /* 洗牌 */ for(i = 54; i > 0; i--) { rindex = rand() % i; tmpcard = cards[i-1]; cards[i-1] = cards[rindex]; cards[rindex] = tmpcard; } return cards; } /* 系统自动出牌 */ unsigned char * systemAutoDiscard(oppose_landocrat_playing_info *playing_info,int *ncardnum) { /* 必须的前提条件:玩家的牌已经排序 */ unsigned char player = playing_info->next_player; unsigned char *cards = playing_info->player_remain_cards[player]; unsigned char card_num = playing_info->player_remain_count[player]; unsigned char *playcards = NULL; unsigned char play_num; *ncardnum = 0; card_type ctype; int isSend = 0; /* 当前玩家发起的出牌 */ int fd = playing_info->fds[playing_info->next_player]; printf("systemAutoDiscard\n=============\n%s\n", gamePlayers[fd].play_name); if(playing_info->pre_player == -1) { /* 暂定系统出最小的牌 */ play_num = 1; isSend = 1; ctype = CARD_TYPE_SIGNAL; playcards = (unsigned char *)xmalloc(2); playcards[0] = cards[0]; playcards[1] = 0; *ncardnum = 1; } /* 其他玩家发起的出牌 */ else { ctype = playing_info->pre_card_type; play_num = getMinFitCards(&ctype, playing_info->pre_cards,playing_info->pre_card_count,cards,card_num); if(play_num) { isSend = 1; playcards = (unsigned char *)xmalloc(play_num); memcpy(playcards,cards,play_num); *ncardnum = play_num; } else sort_card(cards,card_num); } if(isSend) { /*afterPlayHander(playing_info,player,playcards,play_num,ctype);*/ } sort_card(playing_info->player_remain_cards[player],playing_info->player_remain_count[player]); return playcards; } void resetPlayInfo(oppose_landocrat_playing_info *playing_info) { int y; int player_count = oppose_landocrat.player_count; for(y = 0; y < player_count; y++) { xfree(playing_info->player_remain_cards[y]); xfree(playing_info->player_cards[y]); } playing_info->landocrat = -1; playing_info->pre_player = 0; playing_info->next_player = 0; playing_info->call_score = -1; playing_info->bomb_counts = 0; xfree(playing_info->cards_deal_for_landocrat); xfree(playing_info->player_remain_cards); xfree(playing_info->player_cards); } /* 斗地主游戏发牌 */ int oppose_landocrat_deal(oppose_landocrat_playing_info *playing_info) { unsigned char *cards; int player_count = oppose_landocrat.player_count; int card_count_for_landocrat = oppose_landocrat.card_count_for_landocrat; int card_count_peer_player = oppose_landocrat.card_count_peer_player; int i = 0,y=0,ccount=0; int *bombCard = NULL; int sendCardNum[3]={0,0,0}; int bombCount; int shuffleCardNum = 0; int *tmpnum; if(maxbombFrq <= noBomGCount) noBomGCount = 0; if(noBomGCount == 0) { int rindex = 0; for(i = 0; i < maxbombFrq; i++) { gameMBoms[i] = 0; } for(i = 0; i < minbombFrq; i++) { if(maxBombCount == minBombCount) gameMBoms[i] = minBombCount; else gameMBoms[i] = rand() % (maxBombCount - minBombCount) + minBombCount; } for(i = maxbombFrq; i > 0; i--) { rindex = rand() % i; ccount = gameMBoms[i-1]; gameMBoms[i-1] = gameMBoms[rindex]; gameMBoms[rindex] = ccount; } } bombCount = gameMBoms[noBomGCount]; if(bombCount > 0) bombCard = xmalloc(sizeof(int)*bombCount); cards = xmalloc(54); shuffleCardNum = oppose_landocrat_shuffle(cards,bombCard,bombCount); playing_info->player_cards=xmalloc(sizeof(unsigned char*)*player_count); playing_info->player_remain_cards = xmalloc(sizeof(unsigned char*)*player_count); playing_info->cards_deal_for_landocrat = xmalloc(sizeof(unsigned char)*oppose_landocrat.more_card_count_for_landocrat); if(!playing_info->player_cards) { debug(80, 1) ("%s(%s,%d):发牌分配内存错误\n",__FUNCTION__,__FILE__,__LINE__); return 0; } //playing_info->player_remain_cards=(unsigned char **)xcalloc(player_count,sizeof(unsigned char)*card_count_for_landocrat); if(!playing_info->player_remain_cards) { debug(80, 1) ("%s(%s,%d):发牌分配内存错误\n",__FUNCTION__,__FILE__,__LINE__); return 0; } /*memset(playing_info->player_cards,0,sizeof(unsigned char)*card_count_for_landocrat);*/ /*memset(playing_info->player_remain_cards,0,sizeof(unsigned char)*card_count_for_landocrat);*/ for(y = 0; y < player_count; y++) { playing_info->player_cards[y] = (unsigned char*)xmalloc(sizeof(char)*card_count_for_landocrat); playing_info->player_remain_cards[y] = (unsigned char*)xmalloc(sizeof(char)*card_count_for_landocrat); playing_info->player_remain_count[y] = card_count_peer_player; playing_info->players[y]->isCallValuePause = 0; playing_info->players[y]->isPlayPause = 0; } for(i = 0; i < bombCount; i++) { ccount = 4; if(bombCard[i] == 13) ccount = 2; y = rand()% 3; while(sendCardNum[y] + ccount > 17) { y = (y + 1) % 3; } for(;ccount > 0; ccount--) { playing_info->player_cards[y][sendCardNum[y]] = cardsMap[bombCard[i] * 4 + ccount - 1]; playing_info->player_remain_cards[y][sendCardNum[y]] = playing_info->player_cards[y][sendCardNum[y]]; sendCardNum[y]++; } } /*for(y = 0; y < player_count; y++)*/ y = 0; for(ccount = 0; ccount < shuffleCardNum - 3; y++) { y = y % 3; if(sendCardNum[y] >= 17) continue; /* if(ccount == playing_info->card_landocrat_flag) { } */ playing_info->player_cards[y][sendCardNum[y]] = cards[ccount]; playing_info->player_remain_cards[y][sendCardNum[y]]=cards[ccount]; sendCardNum[y]++; ccount++; } for(i = 0; i < 3; i++) { playing_info->cards_deal_for_landocrat[i]=cards[ccount]; ccount++; } if(0) for(y = 0; y < 3; y++) { int isc4 = 0; int hasRocket = 0; sort_card(playing_info->player_cards[y],sendCardNum[y]); tmpnum = getSameValueNum(playing_info->player_cards[y],sendCardNum[y],1); isc4 = tmpnum[3]; hasRocket = tmpnum[4]; xfree(tmpnum); if(isc4 || hasRocket) { noBomGCount = -1; break; } } noBomGCount++; y = rand() % 3; playing_info->card_landocrat_flag = playing_info->player_cards[y][rand() % 17]; playing_info->landocrat = -1; playing_info->pre_player = 0; playing_info->next_player = y; playing_info->call_score = -1; playing_info->bomb_counts = 0; playing_info->call_score = 0xFF - 1; if(bombCount > 0) xfree(bombCard); xfree(cards); return 1; } /* 斗地主游戏发底牌 */ void oppose_landocrat_deal_remain(oppose_landocrat_playing_info *playing_info) { int i; int card_count_peer_player = oppose_landocrat.card_count_peer_player; for(i=0;i<oppose_landocrat.more_card_count_for_landocrat;i++) { playing_info->player_remain_cards[playing_info->landocrat][i+card_count_peer_player]=playing_info->cards_deal_for_landocrat[i]; playing_info->player_cards[playing_info->landocrat][i+card_count_peer_player]=playing_info->cards_deal_for_landocrat[i]; } playing_info->player_remain_count[playing_info->landocrat] = oppose_landocrat.card_count_for_landocrat; } /* 斗地主游戏出牌 */ int oppose_landocrat_sendcard(oppose_landocrat_playing_info *playing_info,unsigned char *cards,unsigned char play_num) { int i,j; int player; card_type ctype = oppose_get_card_type(cards,play_num); int isSend = 1; player = playing_info->next_player; for(i = 0; i < play_num; i++) { for(j = i; j < playing_info->player_remain_count[player]; j++) { if(playing_info->player_remain_cards[player][j] == cards[i]) { playing_info->player_remain_cards[player][j] = playing_info->player_remain_cards[player][i]; playing_info->player_remain_cards[player][i] = cards[i]; break; } } } if(isSend) { afterPlayHander(playing_info,playing_info->next_player,cards,play_num,ctype); sort_card(playing_info->player_remain_cards[player],playing_info->player_remain_count[player]); } return 0; } /* 是否是大王(详见doc/牌映射.xls) */ static int isBigemperor(unsigned char card) { if(card == 61) return 1; return 0; } /* 是否是小王(详见doc/牌映射.xls) */ static int isSmallemperor(unsigned char card) { if(card == 57) return 1; return 0; } /* 排序 */ void sort_card(unsigned char *cards,int card_num) { int i,j; unsigned char tmpc; for(i=0;i<card_num;i++) { int isBreak = 1; for(j=1;j<card_num-i;j++) { if(cards[j-1] > cards[j] || (cards[j-1] == 0 && cards[j] != 0)) { isBreak = 0; tmpc = cards[j-1]; cards[j-1] = cards[j]; cards[j] = tmpc; } } if(isBreak) return; } } /* 按照4张,3张,一对,一张进行排序 前提条件:牌必须已经排好序*/ void sort_card_by_type(unsigned char *cards,int card_num) { int i,j,k=0; int sorted = 0; int fitcount = 0; unsigned char sortcards[card_num]; for(i = 4;i>0;i--) { fitcount = 1; for(j = 0;j<card_num;j++) { if(cards[j] == 0) { continue; } if(j<card_num-1 && (cards[j]-1)/4 == (cards[j+1]-1)/4 && cards[j+1] != 0) fitcount++; else fitcount = 1; if(fitcount == i) { if(fitcount > 1) j++; for(k = 0; k<i; k++) { sortcards[sorted++] = cards[j-i+1+k]; cards[j-i+1+k] = 0; } fitcount = 1; } } } memcpy(cards,sortcards,card_num); } /* 从cards中获取count张同数值牌命中次数 */ int *getSameValueNum(unsigned char *cards,int card_num,int count) { int i,j,k=0; int sorted = 0; int fitcount = 0; int *rvalue =(int *) xmalloc(sizeof(int)*(6-count)); unsigned char sortcards[card_num]; bzero(rvalue,sizeof(int)*(6-count)); for(i = 4;i>count-1;i--) { fitcount = 1; for(j = 0;j<card_num;j++) { if(cards[j] == 0) { continue; } if(j<card_num-1 && (cards[j]-1)/4 == (cards[j+1]-1)/4 && cards[j+1] != 0) fitcount++; else fitcount = 1; if(fitcount == i) { if(fitcount > 1) j++; for(k = 0; k<i; k++) { sortcards[sorted++] = cards[j-i+1+k]; cards[j-i+1+k] = 0; } fitcount = 1; rvalue[i-count]++; } } } memcpy(cards,sortcards,card_num); if(card_num >= 2 && isBigemperor(cards[card_num-1]) && isSmallemperor(cards[card_num-2])) rvalue[5-count]++; return rvalue; } /* 是否是单顺 CARD_TYPE_SEQUENCE_SIGNAL */ static int cardsIsSignalSequence(const unsigned char *cards,int card_num) { int i; if(card_num <5) return 0; for(i=1;i<card_num;i++) { if( (cards[i] -1) / 4 != ((cards[i-1] -1) / 4) +1 ) return 0; } return 1; } /* 是否是双顺 CARD_TYPE_SEQUENCE_DOUBLE */ static int cardsIsDoubleSequence(const unsigned char *cards,int card_num) { int i; debug(82, 2) ("%s(%s,%d)\n",__FUNCTION__,__FILE__,__LINE__); if(card_num <6 || card_num % 2 != 0) return 0; if((cards[0] - 1) /4 != (cards[1] - 1) /4 ) return 0; for(i=1;i<card_num/2;i++) { if((cards[i*2] - 1) / 4 != (cards[i*2+1] - 1) / 4) return 0; if( ((cards[i*2] -1) / 4 ) != ((cards[i*2-1] -1) / 4 )+1) return 0; } return i; } /* 是否是三顺 CARD_TYPE_SEQUENCE_THREE */ static int cardsIsThreeSequence(const unsigned char *cards,int card_num) { int i; if(card_num <6 || card_num % 3 != 0) return 0; if( !(cards[0]-1)/4 == (cards[1]-1)/4 && (cards[1]-1)/4 == (cards[2]-1)/4 ) return 0; for(i=1;i<card_num/3;i++) { if(!( (cards[i*3] - 1 )/4 == (cards[i*3+1] - 1) / 4 && (cards[i*3+1] -1) /4 == (cards[i*3+2] - 1) / 4) ) return 0; if( ((cards[i*3] -1) / 4 ) != ((cards[i*3-1] -1) / 4 )+1) return 0; } return i; } /* 是否是指定的num顺 */ int cardsIsNumSequence(const unsigned char *cards,int card_num,int num) { int i,j; if(card_num < 5 || card_num % num != 0 || card_num < num*2) return 0; for(j = 0;j<num-1;j++) { if((cards[j] - 1) / 4 != (cards[j+1] - 1) / 4) return 0; } for(i=1;i<card_num/num;i++) { for(j = 0;j<num-1;j++) { if((cards[i*num+j] - 1) / 4 != (cards[i*num+j+1] - 1) / 4) return 0; } if( ((cards[i*num] -1) / 4 ) != ((cards[i*num-1] -1) / 4 )+1) return 0; } return i; } /* 分析牌型 */ card_type oppose_get_card_type(const unsigned char *playercards,int card_num) { unsigned char cards[card_num]; memcpy(cards,playercards,card_num); sort_card(cards,card_num); if(card_num == 1) return CARD_TYPE_SIGNAL; if(card_num == 2) { if(isSmallemperor(cards[0]) && isBigemperor(cards[1])) return CARD_TYPE_ROCKET; if((cards[0] - 1) / 4 == (cards[1] - 1) / 4 ) return CARD_TYPE_DOUBLE; return CARD_TYPE_ERROR; } if(card_num == 3) { if( ((cards[0] - 1) / 4 == (cards[1] - 1) / 4) && ((cards[1] - 1) / 4 == (cards[2] - 1) / 4)) return CARD_TYPE_THREE; return CARD_TYPE_ERROR; } if(card_num == 4) { if( ((cards[0] - 1) / 4 == (cards[1] - 1) / 4) && ((cards[1] - 1) / 4 == (cards[2] - 1) / 4) && ((cards[2] - 1) / 4 == (cards[3] - 1) / 4)) return CARD_TYPE_FOUR_BOMB; sort_card_by_type(cards,card_num); if( ((cards[0] - 1) / 4 == (cards[1] - 1) / 4) && ((cards[1] - 1) / 4 == (cards[2] - 1) / 4)) return CARD_TYPE_THREE_SIGNAL; /* if( ((cards[1] - 1) / 4 == (cards[2] - 1) / 4) && ((cards[2] - 1) / 4 == (cards[3] - 1) / 4)) return CARD_TYPE_THREE_SIGNAL; */ return CARD_TYPE_ERROR; } if(cardsIsSignalSequence(cards,card_num)) return CARD_TYPE_SEQUENCE_SIGNAL; int num = 1; int *tmpnum = getSameValueNum(cards,card_num,num); int isc4 = tmpnum[4-num],isc3 = tmpnum[3-num],isc2=tmpnum[2-num],isc1=tmpnum[1-num]; xfree(tmpnum); if(card_num == 5) { if(isc3 && isc2) return CARD_TYPE_THREE_DOUBLE; } if(card_num == 6) { if(isc4 && !isc2) return CARD_TYPE_FOUR_DOUBLE_SIGNAL; } if(card_num == 8) { if(isc4 && isc2 == 2) return CARD_TYPE_FOUR_DOUBLE_DOUBLE; } //sort_card_by_type(cards,card_num); if(isc2 > 2 && cardsIsDoubleSequence(cards,card_num)) return CARD_TYPE_SEQUENCE_DOUBLE; if(isc3 > 1 && cardsIsThreeSequence(cards,card_num)) return CARD_TYPE_SEQUENCE_THREE; sort_card_by_type(cards,card_num); if(isc3 && !isc4) { int i,isMatch = 1; for(i = 0;i<isc3-1;i++) { if((cards[i*3] - 1) / 4 +1 != (cards[i*3+3] - 1) / 4) { isMatch = 0; break; } } if(isMatch && !isc2 && isc3 == isc1) return CARD_TYPE_SEQUENCE_THREE_WINGS_SIGNAL; if(isMatch && !isc1 && isc3 == isc2) return CARD_TYPE_SEQUENCE_THREE_WINGS_DOUBLE; } return CARD_TYPE_ERROR; } /* 斗地主游戏出牌 */ #ifdef SINOCDN_H_MAIN int main(int argc, char *argv[]) { return 0; } #endif