/**
* 牌型
火箭:即双王(大王和小王),最大的牌。
炸弹:四张点数相同的牌,如:7777。
单牌:任意一张单牌。
对牌:任意两张点数相同的牌。
三张:任意三张点数相同的牌,如888。
三带一:点数相同的三张牌+一张单牌或一对牌。如:333+6 或 444+99。
单顺:任意五张或五张以上点数相连的牌,如:45678或78910JQK。不包括 2和双王。
双顺:三对或更多的连续对牌,如:334455、7788991010JJ。不包括 2 点和双王。
三顺:二个或更多的连续三张牌,如:333444 、555666777888。不包括 2 点和双王。
飞机带翅膀:三顺+同数量的单牌或同数量的对牌。如:444555+79 或333444555+7799JJ
四带二:四张牌+两手牌。(注意:四带二不是炸弹)。如:5555+3+8 或 4444+55+77 。
*/
var PokerObj = require("Poker");
var CardType = cc.Enum({
c1: 0, //单牌。
c2: -1, //对子。
c20: -1, //王炸。
c3: -1, //3不带。
c4: -1, //炸弹。
c31: -1, //3带1。
c32: -1, //3带2。
c411: -1, //4带2个单,或者一对
c422: -1, //4带2对
c123: -1, //顺子。
c1122: -1, //连队。
c111222: -1, //飞机。
c11122234: -1, //飞机带单排.
c1112223344: -1, //飞机带对子.
c0: -1 //不能出牌
});
//获取牌的等级
function getGrade(card) {
return card.getComponent('Poker')._grade;
};
//牌生成一个反应数量的数组
function getCarAnalyseInfo(cards) {
var oneArray = [];
var twoArray = [];
var threeArray = [];
var fourArray = [];
//循环跳过的数量=相同牌的数量
var jumpCount = 1;
for (let i = 0; i < cards.length; i += jumpCount) {
var sameCount = 1;
var grade = getGrade(cards[i]);
for (let j = i + 1; j < cards.length; j++) {
var grade1 = getGrade(cards[j]);
if (grade != grade1) {
break;
}
sameCount++;
}
jumpCount = sameCount;
switch (sameCount) {
case 1:
oneArray.push(grade);
break;
case 2:
twoArray.push(grade);
break;
case 3:
threeArray.push(grade);
break;
case 4:
fourArray.push(grade);
break;
default:
break;
}
};
var allInfo = [oneArray, twoArray, threeArray, fourArray];
console.log(allInfo)
return allInfo;
}
//根据长度筛选先
function sortByLength(cards) {
let length = cards.length;
var cardsInfo = getCarAnalyseInfo(cards);
switch (length) {
case 0:
return CardType.c0;
break;
case 1:
//单
return CardType.c1;
break;
case 2:
//进行对子的判断和王炸判断
if (checkIsWangzha(cards)) {
return CardType.c20;
} else if (cardsInfo[1].length == 1) {
return CardType.c2;
}
break;
case 3:
//3不带的判断
if (cardsInfo[2].length == 1) {
return CardType.c3;
}
break;
case 4:
//炸弹、3带1。
if (cardsInfo[2].length == 1) {
return CardType.c31;
} else if (cardsInfo[3].length == 1) {
return CardType.c4;
}
break;
case 5:
//三带二、顺子
//炸弹
if (cardsInfo[2].length == 1 && cardsInfo[1].length == 1){
return CardType.c32;
} else if (cardsInfo[3].length == 1) {
return CardType.c4;
} else if (checkIsShunzi(cardsInfo, length)) {
return CardType.c123;
}
break;
case 6:
//顺子、四带二、飞机不带、连对
if (cardsInfo[3].length == 1) {
return CardType.c411;
} else if (cardsInfo[2].length == 2) {
return CardType.c111222;
} else if (checkIsShunzi(cardsInfo, length)) {
return CardType.c123;
} else if (checkIsLianDuizi(cardsInfo, length)) {
return CardType.c1122;
}
break;
case 8:
//顺子、四带二对、连对、飞机带单
if (cardsInfo[3].length == 1 && cardsInfo[1].length == 2) {
return CardType.c422;
} else if (cardsInfo[2].length == 2) {
return CardType.c11122234;
} else if (checkIsShunzi(cardsInfo, length)) {
return CardType.c123;
} else if (checkIsLianDuizi(cardsInfo, length)) {
return CardType.c1122;
}
break;
default:
//顺子、连对、飞机(不带、单、双)
/**
* 顺子:每个值差1,5-11张,不含王、2
* 连对:偶数,每两个差1,6-18张,不含王、2
* 飞机不带:%3为0,每三张差1,6-18张
* 飞机带单:%4为0,从前到后或者后到前,每三张差1,8-16张
* 飞机带双:%5为0,从前到后或者后到前,每三张差1,10-15张
*/
if (checkIsShunzi(cardsInfo, length)) {
return CardType.c123;
} else if (checkIsLianDuizi(cardsInfo, length)) {
return CardType.c1122;
} else if (checkIsFeiJi(cardsInfo, length, 3)) {
//飞机不带
return CardType.c111222;
} else if (checkIsFeiJi(cardsInfo, length, 4)) {
//飞机带单
return CardType.c11122234;
} else if (checkIsFeiJi(cardsInfo, length, 5)) {
//飞机带对子
return CardType.c1112223344;
}
break;
}
return CardType.c0;
}
//进行对子的判断和王炸判断
function checkIsWangzha(cards) {
var grade1 = getGrade(cards[0]);
var grade2 = getGrade(cards[1]);
//王炸
if (grade1 == 17 && grade2 == 16) {
return true;
}
return false;
}
//顺子的判断
function checkIsShunzi(cardsInfo, length) {
var flag = false;
if (cardsInfo[0].length != length) {
//单排数组长度为所有扑克牌
} else if (checkElementIsContain(17, cardsInfo[0]) || checkElementIsContain(16, cardsInfo[0]) || checkElementIsContain(15, cardsInfo[0])) {
//不可以包含王、2
} else if (cardsInfo[0][0] - cardsInfo[0][cardsInfo[0].length - 1] == length - 1) {
//(第一张牌值 - 最后一张牌值)== (length-1)
flag = true;
}
return flag;
}
//连对子判断
function checkIsLianDuizi(cardsInfo, length) {
var flag = false;
if ((cardsInfo[1].length != length / 2) || (0 != length % 2)) {
//对子数组长度为所有扑克牌/2 length为2的整除
} else if (checkElementIsContain(17, cardsInfo[1]) || checkElementIsContain(16, cardsInfo[1]) || checkElementIsContain(15, cardsInfo[1])) {
//不可以包含王、2
} else if ( cardsInfo[1][0] - cardsInfo[1][cardsInfo[1].length - 1] == length / 2 - 1) {
//(第一张牌值 - 最后一张牌值)== (length/2-1)
flag = true;
}
return flag;
}
function checkIsFeiJi(cardsInfo, length, count) {
var flag = false;
if ((cardsInfo[2].length != length / count) || (0 != length % count)) {
//对子数组长度为所有扑克牌/2 length为2的整除
} else if (checkElementIsContain(15, cardsInfo[2])) {
//不可以包含、2
} else if (cardsInfo[2][0] - cardsInfo[2][cardsInfo[2].length - 1] == length / count - 1) {
//(第一张牌值 - 最后一张牌值)== (length/3-1)
flag = true;
}
return flag;
}
//二次排序(针对四带和三代)
function secondSortWithCards(cards){
let type = sortByLength(cards);
var cardsInfo = getCarAnalyseInfo(cards);
if (type == CardType.c31 ||type == CardType.c32 ||type == CardType.c11122234 ||type == CardType.c1112223344) {
//将cardsInfo[2]中有的全部提前
//反向遍历
for (let i = cardsInfo[2].length -1 ; i >=0 ; i--) {
let grade = cardsInfo[2][i];
for (let j = 0 ; j <cards.length ; j++) {
const pokerSpriteOne = cards[j];
let pokerGrade = pokerSpriteOne.getComponent('Poker')._grade;
//找到相等等级的提前
if (grade == pokerGrade) {
let tempArray = [cards[j+2],cards[j+1],cards[j]];
//合并两个数组
cards = tempArray.concat(cards);
//删除原始的三个数据
cards.splice(j+3,3);
break;
}
}
}
}else if (type == CardType.c411 ||type == CardType.c422) {
//将cardsInfo[3]中有的全部提前
//反向遍历
let grade = cardsInfo[3][0];
for (let j = 0 ; j <cards.length; j++) {
const pokerSpriteOne = cards[j];
let pokerGrade = pokerSpriteOne.getComponent('Poker')._grade;
//找到相等等级的提前
if (grade == pokerGrade) {
let tempArray = [cards[j],cards[j+1],cards[j+2],cards[j+3]];
//合并两个数组
cards = tempArray.concat(cards);
//删除原始的三个数据
cards.splice(j+4,4);
break;
}
}
}else{
return cards;
}
return cards;
}
/**
* 比较两次打的牌,后一次要大于前一次
* @param {上一手牌} lastPoker
* @param {本次} thisPoker
*/
function comparePokers(lastPoker, thisPoker) {
//首先判断是否为炸弹和王炸
if (lastPoker == CardType.c20) {//上一手为王炸
return false;
} else if (thisPoker == CardType.c20) {//当前为王炸
return true;
} else if (thisPoker == CardType.c4 && lastPoker != CardType.c4) {//当前为炸弹,上一手不为炸弹
return true;
}
//长度不同则直接返回错误
if (Global.lastPokers.length != Global.selectPokers.length) {
return false;
}
//大小判断
if (lastPoker == thisPoker) {
//通用方法,从大到小(先排序一次)
bubbleSortCards(Global.lastPokers);
bubbleSortCards(Global.selectPokers);
let lastCardsInfo = getCarAnalyseInfo(Global.lastPokers);
let thisCardsInfo = getCarAnalyseInfo(Global.selectPokers);
let index = 0;
if (lastPoker == CardType.c1 || lastPoker == CardType.c123) {
index = 0;
} else if (lastPoker == CardType.c2) {
index = 1;
} else if (lastPoker == CardType.c3 || lastPoker == CardType.c31 || lastPoker == CardType.c32 || lastPoker == CardType.c11122234 || lastPoker == CardType.c1112223344) {
index = 2;
} else if (lastPoker == CardType.c4 || lastPoker == CardType.c411 || lastPoker == CardType.c422) {
index = 3
}
for (let i = 0; i < lastCardsInfo[index].length; i++) {
if (lastCardsInfo[index][i] >= thisCardsInfo[index][i]) {
//出现一个小于则失败
return false;
}
}
return true;
}
return false;
}
//检查数组是否包含元素
function checkElementIsContain(element, array) {
for (const grade of array) {
if (grade == element) {
return true;
}
}
return false;
};
/**
* 对牌进行排序,从小到大,使用冒泡排序,此种方法不是很好
*
* @param cards
* 牌
*/
function bubbleSortCards(cards) {
if (cards == null) {
return cards;
}
let size = cards.length;
// 冒泡排序,从左到右,从小到大
for (var i = 0; i < size; i++) {
for (var j = 0; j < size - 1 - i; j++) {
let pokerSpriteOne = cards[j];
let PokerOne = pokerSpriteOne.getComponent('Poker');
let pokerSpriteTwo = cards[j + 1];
let PokerTwo = pokerSpriteTwo.getComponent('Poker');
var gradeOne = PokerOne._grade;
var gradeTwo = PokerTwo._grade;
var isExchange = false;
if (gradeOne < gradeTwo) {
isExchange = true;
} else if (gradeOne == gradeTwo) {
// 2张牌的grade相同
var type1 = PokerOne._bigType;
var type2 = PokerTwo._bigType;
// 从左到右,方块、梅花、红桃、黑桃
if (type1 == PokerObj.CardBigType.HEI_TAO) {
isExchange = true;
} else if (type1 == PokerObj.CardBigType.HONG_TAO) {
if (type2 == PokerObj.CardBigType.MEI_HUA ||
type2 == PokerObj.CardBigType.FANG_KUAI) {
isExchange = true;
}
} else if (type1 == PokerObj.CardBigType.MEI_HUA) {
if (type2 == PokerObj.CardBigType.FANG_KUAI) {
isExchange = true;
}
}
}
if (isExchange) {
cards[j + 1] = pokerSpriteOne;
cards[j] = pokerSpriteTwo;
}
}
}
// console.log("我的牌"+ cards);
// return cards;
};
module.exports = {
CardType: CardType,
sortByLength: sortByLength,
bubbleSortCards: bubbleSortCards,
secondSortWithCards: secondSortWithCards,
comparePokers:comparePokers
}