斗地主游戏实现6:代码之一(主程序)

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

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值