牛牛牌型判断算法

export class CowCard{
	/**
	 * NiuNiuCard constructor.
	 * @param type  牌型 //type : 1 : 黑桃 2:红桃 3:梅花 4:方块
	 * @param num   牌号
	 * @param count 牌点数 >10都作为10
	 */
	constructor(type, num, count) {
		this.type = type;
		this.num = num;
		this.count = count;
	}
}
//判断牛几
export class Cow{
	/**
	 * 辅助函数,用于排序
	 * @param cards 卡牌的引用
	 */
	sortCards(cards) {
		cards.sort((a, b) => {
			if (a.num > b.num || (a.num == b.num && a.type < b.type)) {
				return 1;
			}
			else {
				return -1;
			}
		});
	}
	/**
	 * @param cards 玩家的手牌
	 * @param typeSelected  允许的可选牌型的数组,用于是否开启该牌型,包含数据为
	 *          canShunDou: 能否顺斗; canKanDou: 能否坎斗
	 *          canSameColorLineCow: 能否同花顺
	 *          canBoomCow: 能否×××牛
	 *          canSmallCow: 能否五小牛
	 *          canFlowerCow:  能否五花牛
	 *          canSiHuaNiu:  能否四花牛
	 *          canGourdCow:   能否葫芦牛
	 *          canSameColorCow: 能否同花牛
	 *          canLineCow:  能否顺子牛
	 * @return resultArray 某一个玩家的结果数组,存放结果
	 *          'level': 牌的级别,按照同花顺 > 五小牛 > 五花牛 > 四花牛 > ×××牛 > 葫芦牛 > 同花
	 *                                     > 顺子 > 牛牛 > 牛9-牛5 > 牛4-牛1 > 无牛进行排列
	 *                         注意:坎斗、顺斗以及普通牛是同一级别,都看点数
	 *          'levelResult': 牌的级别对应的最大牌,用于同级别的判断
	 *
	 */
	getCowResult(cards, typeSelected){

		let result = {level:-1,levelResult:'',douPai:[]};

		//保存一个临时牌组,并按从小到大排序
		this.sortCards(cards);

		//获取普通牛数据
		let r = this.getCowCount(cards);
		this.processResult(result, r);

		if(typeSelected.canShunDou){
			//获取顺斗的数据
			r = this.getShunDouPoint(cards);
			this.processResult(result, r);
		}

		/*if(typeSelected.canCanDou){
			//获取豹子牛数据
			r = this.isLeopardCow(cards);
			if(r.level==Cow.COW_LEOPARD){
				this.processResult(result, r);

			}
		}*/

		//可能出错
		if(typeSelected.canFlowerCow){
			//获取五花牛
			r = this.isFlowerCow(cards);
			if(r.level==Cow.COW_FLOWER){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canLineCow){
			//获取顺子牛数据
			r = this.isLineCow(cards);
			if(r.level==Cow.COW_LINE){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canSameColorCow){
			//获取同花牛
			r = this.isSameColorCow(cards);
			if(r.level==Cow.COW_SAME_COLOR){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canGourdCow){
			//获取葫芦牛
			r = this.isGourdCow(cards);
			if(r.level==Cow.COW_GOURD){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canBoomCow){
			//获取炸弹牛
			r = this.isBoomCow(cards);
			if(r.level==Cow.COW_BOOM){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canSmallCow){
			//获取五小牛
			r = this.isSmallCow(cards);
			if(r.level==Cow.COW_SMALL){
				this.processResult(result, r);
			}
		}

		if(typeSelected.canSameColorLineCow){
			//获取同花顺
			r = this.isSameColorLineCow(cards);
			if(r.level==Cow.COW_SAME_COLOR_LINE){
				this.processResult(result, r);
			}
		}


		return result;
	}

	processResult(playerResult, newResult){
		if(playerResult.level < newResult.level){
			playerResult.level = newResult.level;
			playerResult.levelResult = newResult.maxCard;
			playerResult.douPai = newResult.douPai;
		}
	}

	/**
	 * 判断牛牛点数
	 * @param cards 玩家的手牌
	 * @return array:[level:牌力,maxCard: 最大牌]
	 */
	getCowCount(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		//总点数
		let cardsTotalPoint = 0;
		//计算总点数
		cards.forEach(card => {
			cardsTotalPoint += card.count;
		});
		//计算余数
		let lave = cardsTotalPoint % 10;
		for(let i = 0; i < cards.length - 1; i++){
			for(let j = i + 1; j < cards.length; j++){
				if((cards[i].count + cards[j].count) % 10 == lave){
					//此处是有牛,则取出斗的牌
					if(i != 0 && j != 0){
						result.douPai.push(cards[0]);
					}
					if(i != 1 && j != 1){
						result.douPai.push(cards[1]);
					}
					if(i != 2 && j != 2) {
						result.douPai.push(cards[2]);
					}
					if(i != 3 && j != 3){
						result.douPai.push(cards[3]);
					}
					if(i != 4 && j != 4){
						result.douPai.push(cards[4]);
					}

					result.level = this._getCount(lave);
					result.maxCard = cards[4];
					return result;
				}
			}
		}
		result.level = Cow.NONE;
		result.maxCard = cards[4];
		return result;

	}

	/*
	 * 辅助函数,用于处理牛1-牛9的细分结果处理
	 * @param lave: getNiuniuCount的余数结果
	 */
	_getCount(lave) {
		switch (lave) {
			case 0:
				return Cow.COW_COW;
			case 1:
				return Cow.COW_1;
			case 2:
				return Cow.COW_2;
			case 3:
				return Cow.COW_3;
			case 4:
				return Cow.COW_4;
			case 5:
				return Cow.COW_5;
			case 6:
				return Cow.COW_6;
			case 7:
				return Cow.COW_7;
			case 8:
				return Cow.COW_8;
			case 9:
				return Cow.COW_9;
			default:
				return -1;
		}
	}

	/**
	 * 判断是否为五花牛的函数
	 * @param cards 某一个玩家的手牌
	 * @return level: 牌力,maxCard: 最大牌
	 */
	isFlowerCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let flag = false;
		cards.some(card => {
			if(card.num <= 10){
				flag = true;
				return true;
			}
		});
		if(flag){
			return result;
		}
		result.level = Cow.COW_FLOWER;
		result.maxCard = cards[4];
		result.douPai = cards;
		return result;
	}

	/**
	 * 判断是否为同花牛的函数
	 * @param cards 某一个玩家的手牌
	 * @return result:{level:牌力,maxCard: 最大牌}
	 */
	isSameColorCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let type = cards[0].type;
		let flag = true;
		cards.some(card => {
			if(card.type != type){
				flag = false;
				return false;
			}
		});

		if(flag){
			result.level = Cow.COW_SAME_COLOR;
			result.maxCard = cards[4];
			result.douPai = cards;
		}

		return result;
	}

	/**
	 * 判断是否为同花顺牛的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 同花顺的最大牌}
	 */
	isSameColorLineCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let r1 = this.isSameColorCow(cards);
		let r2 = this.isLineCow(cards);
		if(r1.level == Cow.COW_SAME_COLOR && r2.level == Cow.COW_LINE){
			result.level = Cow.COW_SAME_COLOR_LINE;
			result.maxCard = cards[4];
			result.douPai = cards;
		}

		return result;
	}

	/**
	 * 判断是否为炸弹牛的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 同花顺的最大牌}
	 */
	isBoomCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		//假设牌已经按照从小到大排序
		//aaaa*
		if(cards[0].num == cards[3].num){
			result.level = Cow.COW_BOOM;
			result.maxCard = cards[0];
			result.douPai = cards.slice(0,5);
		}
		//*aaaa
		else if(cards[1].num ==cards[4].num){
			result.level = Cow.COW_BOOM;
			result.maxCard = cards[1];
			result.douPai = cards.slice(1);
		}
		return result;
	}

	/**
	 * 判断是否为五小牛的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 同花顺的最大牌}
	 */
	isSmallCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let totalCount = 0;
		cards.some(card => {
			if(card.num > 5){
				return false;
			}
			else{
				totalCount += card.num;
			}
		});
		if(totalCount <= 10 && totalCount > 0){
			result.level= Cow.COW_SMALL;
			result.maxCard = cards[4];
			result.douPai=cards;
		}

		return result;
	}

	/**
	 * 判断是否为葫芦牌型的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 葫芦的最大牌}
	 */
	isGourdCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		//aaabb
		if(cards[0].num == cards[2].num){
			if(cards[3].num == cards[4].num){
				result.level = Cow.COW_GOURD;
				result.maxCard = cards[0];
				result.douPai = cards.slice(0,3);
			}
		}
		//aabbb
		if(cards[2].num == cards[4].num){
			if(cards[0].num == cards[1].num){
				result.level = Cow.COW_GOURD;
				result.maxCard = cards[2];
				result.douPai = cards.slice(2);
			}
		}
		return result;
	}

	/**
	 * 判断是否为四花型的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 四花的最大牌}
	 */
	isFourCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let flag = true;
		cards.some(card => {
			if(card.num < 10){
				flag = false;
				return false;
			}
		});
		if(cards[0].num == 10 && flag){
			result.level = Cow.COW_FOUR;
			result.maxCard = cards[4];
		}

		return result;
	}

	/**
	 * 判断是否为顺子牛的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 顺子牛的最大牌}
	 */
	isLineCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		//abcde
		let temp = cards[0].num;
		let num = 0;
		if(temp == 1){
			//第一张为A
			//a 2 3 4 5
			if(cards[1].num == 2){
				num++;
				for(let i=2;i<5;i++){
					if(cards[i].num-i == temp){
						num++;
					}else{
						return result;
					}
				}
			}else if(cards[1].num == 10){
				num++;
				for(let i=2;i<5;i++){
					if(cards[i].num-i+1 == 10){
						num++;
					}else{
						return result;
					}
				}
			}

			//10 J Q K A
		}else{
			for(let i=1;i<5;i++){
				if(cards[i].num-i == temp){
					num++;
				}else{
					return result;
				}
			}
		}

		if(num==4){
			result.level = Cow.COW_LINE;
			result.maxCard = cards[4];
			result.douPai = cards;
		}
		return result;
	}

	/**
	 * 判断是否为豹子牛的函数
	 * @param cards
	 * @return result:{level:牌力, maxCard: 豹子牛的最大牌}
	 */
	isLeopardCow(cards){
		let result = {level:-1,maxCard:'',douPai:[]};

		//aaa**
		if(cards[0].num == cards[2].num){
			result.level = Cow.COW_LEOPARD;
			result.maxCard = cards[4];
			result.douPai = cards.slice(0,3);
		}
		//*aaa*
		else if(cards[1].num == cards[3].num){
			//count = cards[0].point + cards[4].point;
			result.level = Cow.COW_LEOPARD;
			result.maxCard = cards[4];
			result.douPai = cards.slice(1,4);
		}
		//**aaa
		else if(cards[2].num == cards[4].num){
			result.level = Cow.COW_LEOPARD;
			result.maxCard = cards[1];
			result.douPai = cards.slice(2);
		}
		return result;
	}

	/**
	 * 获取是否为坎斗的函数
	 * @param cards 某一个玩家的手牌
	 * @return result:{level:牌力, maxCard: 坎斗的最大牌}
	 */
	getKanDouPoint(cards){
		let result = {level:-1,maxCard:'',douPai:[]};
		let count = -1;
		//aaa**
		if(cards[0].num == cards[2].num){
			count = cards[3].count + cards[4].count;
			result.maxCard = cards[4];
		}
		//*aaa*
		else if(cards[1].num == cards[3].num){
			count = cards[0].count + cards[4].count;
			result.maxCard = cards[4];
		}
		//**aaa
		else if(cards[2].num == cards[4].num){
			count = cards[0].count + cards[1].count;
			result.maxCard = cards[1];
		}
		else{
			count = -1;
		}
		count = count % 10;

		result.level = this._getCount(count);
		return result;
	}

	/**
	 * 获取是否为顺斗的函数
	 * @param cards 某一个玩家的手牌
	 * @return result:{level:牌力, maxCard: 顺斗的最大牌}
	 */
	getShunDouPoint(cards){
		let result = {level:-1,maxCard:'',douPai:[]};

		//枚举所有情况产生点数的数组
		let tempResults = {level:-1,maxCard:'',douPai:[]};
		//第一种情况abc**
		if( (cards[0].num+1 == cards[1].num) && (cards[1].num == cards[2].num - 1)){
			tempResults.push({level:(cards[3].count + cards[4].count)%10,maxCard:cards[4],douPai:cards.slice(0,3)});
		}
		//第二种情况*abc*
		if ((cards[1].num+1 == cards[2].num) && (cards[2].num == cards[3].num - 1)){
			tempResults.push({level:(cards[0].count + cards[4].count)%10,maxCard:cards[4],douPai:cards.slice(1,4)});
		}

		//第三种情况**abc
		if ((cards[2].num+1 == cards[3].num) && (cards[3].num == cards[4].num - 1)){
			tempResults.push({level:(cards[0].count + cards[1].count)%10,maxCard:cards[4],douPai:cards.slice(2)});
		}
		//第四种情况abbc*
		if (cards[0].num+2 == cards[3].num && cards[0].num + 1 == cards[1].num){
			tempResults.push({level:(cards[4].count + cards[1].count)%10,maxCard:cards[4],douPai:[cards[0],cards[1],cards[3]]});
		}

		//第五种情况*bccd;
		if(cards[1].num+2 == cards[4].num && cards[3].num + 1 == cards[4].num) {
			tempResults.push({level:(cards[0].count + cards[2].count)%10,maxCard:cards[4],douPai:[cards[1],cards[2],cards[4]]});
		}

		//第六种情况aabbc;
		if((cards[0].num+1 == cards[2].num) && (cards[2].num+1 == cards[4].num)){
			tempResults.push({level:(cards[0].count + cards[2].count)%10,maxCard:cards[4],douPai:[cards[0],cards[2],cards[4]]});
		}

		//第七种情况abbcc
		if((cards[0].num+1 == cards[2].num) && (cards[2].num+1 == cards[4].num)){
			tempResults.push({level:(cards[1].count + cards[3].count)%10,maxCard:cards[4],douPai:[cards[0],cards[1],cards[3]]});
		}

		//第8种情况abbbc
		if(cards[0].num+2 == cards[4].num && cards[0].num + 1 == cards[1].num) {
			tempResults.push({level:(cards[1].count * 2)%10,maxCard:cards[4],douPai:[cards[0],cards[1],cards[4]]});
		}

		//有可能没有结果,直接返回
		if(tempResults.length == 0){
			return result;
		}

		//获取最大的可能性结果返回
		let level = tempResults[0].level;
		let maxIndex = 0;
		tempResults.forEach((tempResult,index) => {
			if(tempResult.level > level){
				level = tempResult;
				maxIndex = index;
			}
		});
		//echo tempResult[index].level;
		result.level = this._getCount(tempResults[maxIndex].level % 10 );
		result.maxCard = tempResults[maxIndex].maxCard;
		result.douPai = tempResults[maxIndex].douPai;

		return result;
	}

}

Cow.NONE = -1; //无牛

Cow.COW_1 = 1; //牛1
Cow.COW_2 = 2; //牛2
Cow.COW_3 = 3; //牛3
Cow.COW_4 = 4; //牛4
Cow.COW_5 = 5; //牛5
Cow.COW_6 = 6; //牛6
Cow.COW_7 = 7; //牛7
Cow.COW_8 = 8; //牛8
Cow.COW_9 = 9; //牛9
Cow.COW_COW = 10; //牛牛
Cow.COW_LINE = 11; //顺子牛
Cow.COW_SAME_COLOR = 12; //同花牛
Cow.COW_GOURD = 13; //葫芦牛
Cow.COW_BOOM = 14; //炸弹牛
Cow.COW_FOUR = 15; //四花牛
Cow.COW_FLOWER = 16; //5花牛
Cow.COW_SMALL = 17; //五小牛

Cow.COW_SAME_COLOR_LINE = 18; //同花顺牛


// Cow.COW_LEOPARD = 18;//豹子牛

你可能感兴趣的:(算法)