'use strict'; //// 为什么选择 Lodash ? //// Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。 //// Lodash 的模块化方法 非常适用于: //// 遍历 array、object 和 string //// 对值进行操作和检测 //// 创建符合功能的函数 var _ = require('lodash'); var quick = require('quick-pomelo'); var logger = quick.logger.getLogger('fhmj', __filename); // 所有牌 const CARDS = [ 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条 // 51, // 中 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条 // 51, // 中 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条 // 51, // 中 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条 // 51, // 中 ]; // 块类型 const STYLE = { NULL: 0, // 无效 CHI: 1, // 吃牌 SUN: 2, // 顺序 PENG: 3, // 碰子 KE: 4, // 刻子 GANG: 5, // 杠子 ANGANG: 6, // 暗杠 ZMGANG: 7, // 自摸明杠 BUDA:8, // TL++不搭 // LIANGBD:9, // TL++两张百搭和一张普通牌组成一个块 // SANBD:10, // TL++三张百搭和一张普通牌组成一个块 }; // 椅子数 const CHAIR_COUNT = 4; const CARDS_COUNT = 13; // 构造方法 var Logic = function (type,gameKindTL,playerAllCount,other) { // 类型 this.type = type; this.other = other;//////TL++2人3人的游戏规则 this.jiangmaType = -1;////奖码类型:-1:不奖码,1:159奖码,2:摸几奖几,3:一码全中 this.jiangmaCount = -1;////奖码张数 if(this.other & 1){ this.jiangmaType = 1; if(this.other & 8) this.jiangmaCount = 2; else if(this.other & 16) this.jiangmaCount = 4; else if(this.other & 32) this.jiangmaCount = 6; } else if(this.other & 2){ this.jiangmaType = 2; this.jiangmaCount = 0; } else if(this.other & 4){ this.jiangmaType = 3; this.jiangmaCount = 1; } this.hzCount = 0;/////红中个数 if(this.other & 64) this.hzCount = 4; else if(this.other & 1024) this.hzCount = 6; else if(this.other & 2048) this.hzCount = 8; this.isQGHJM = false;/////是否抢杠胡奖码 if(this.other & 128) this.isQGHJM = true; this.isHZHG = false;/////是否荒庄荒杠 if(this.other & 256) this.isHZHG = true; this.isWGHZJYM = false;/////无红中胡加一码 if(this.other & 512) this.isWGHZJYM = true; this.isZNZM = this.type == 2;/////是否只能自摸,拉杠情况可以胡 // console.warn("logic 奖码类型:-1:不奖码,1:159奖码,2:摸几奖几,3:一码全中 "+this.jiangmaType) // console.warn("logic 奖码张数 "+this.jiangmaCount) // console.warn("logic 是否红中赖子 "+this.isHZLZ) // console.warn("logic 是否抢杠胡奖码 "+this.isQGHJM) // console.warn("logic 是否荒庄荒杠 "+this.isHZHG) // console.warn("logic 无红中胡加一码 "+this.isWGHZJYM) // console.warn("logic 是否只能自摸 "+this.isZNZM) // 七对 // this.has7d = true;/////TL++因为奉化麻将当中本身就可以胡7对 // 全牌 var cards = _.clone(CARDS); // 添加红中红中 if (this.hzCount > 0){ for (let i = 0; i < this.hzCount; ++i) { cards[cards.length] = 51; } } this.castCount = 0; this.disCount = 0; this.lastCount = cards.length;//////设置剩余牌数为了测试海底捞月 this.cardsPool = cards; this.cardsyl = _.clone(cards); //////以下变量全是TL++ this.gameKindTL = gameKindTL || 1;////平搓还是冲刺 = 1代表平搓 = 2代表冲刺 this.playerAllCount = playerAllCount || 4;////游戏人数 = 2表示2人局 = 3表示3人局 = 4表示4人局 this.setCardFilerIndex = 0 this.baiDaCard = 51;/////TL++,拿到百搭牌 this.baiDaList = [0,0,0];/////TL++,拿到百搭牌数组 this.sbyBDList = []//////得到某人手中的百搭牌数组 this.chuPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡 this.moPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡 this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id this.addThisIsHu = 0//////TL++,胡牌判断时加上这张能不能胡 this.isSeleCatcedCard = false//////判断能否胡牌的那张牌是自己抓的还是别人打出来的 this.currChairIDTL = 0/////当前判断胡的chairID,用于得到当前玩家的胡牌情况 this.isLaGang = false;//////TL++,是否刚刚被拉杠用于判断是否被拉杠胡 this.isGuoHuList = [[false,0],[false,0],[false,0],[false,0],]/////TL++,各个玩家在本轮是否点击了过胡和点击过牌时的台数 this.setCardFileName = '';/////设置手牌的文件名 this.cardGroupIndex = 0;////要设置的牌型种类 this.isZHYZ = false;/////是不是最后1张 this.isMZWF = [0,1,2,3];/////是不是满足位风 // console.warn("ppppppppppp 长度 "+cards.length+" cards "+cards); }; Logic.setHCfileNameList =[/////全部设置牌型的文件名 "setHandCard_tianhu", ] // 导出常量 Logic.CARDS = CARDS; Logic.STYLE = STYLE; Logic.CHAIR_COUNT = CHAIR_COUNT; Logic.CARDS_COUNT = CARDS_COUNT; // 导出类 module.exports = Logic; // 原型对象 var proto = Logic.prototype; /////TL++为了得到百搭牌数组用于判断是否需要补花和手牌中百搭牌个数 proto.setBDList = function () { this.baiDaList = [this.baiDaCard,this.baiDaCard,this.baiDaCard]/////TL++,拿到百搭牌 }; ///////TL++在table类中出牌函数中调用,为了判断天胡和地胡 proto.chuPaiTL = function () { // console.warn("111c天胡判断不正确",this.chuPaiCountTL); this.chuPaiCountTL += 1//////这个其实并不是真实的出牌个数,因为这个方法的调用在判断吃碰杠胡之前调用的 } ///////TL++在table类中出牌函数中调用,为了判断天胡和地胡 proto.moPaiTL = function () { // console.warn("111c天胡判断不正确",this.chuPaiCountTL); this.moPaiCountTL += 1//////TL++,记录出牌的个数,为了判断天胡和地胡 += 1 } ///////TL++重置默认数据,在每局游戏开始的洗牌函数中调用 proto.resetDataOnGameStart = function () { this.chuPaiCountTL = 0//////TL++出牌个数 this.moPaiCountTL = 0//////TL++,记录摸牌的个数,为了判断天胡和地胡 this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id this.addThisIsHu = 0//////TL++,胡牌判断时加上这张能不能胡 this.isSeleCatcedCard = false//////判断能否胡牌的那张牌是自己抓的还是别人打出来的 this.isLaGang = false;//////TL++,是否刚刚被拉杠用于判断是否被拉杠胡 this.isGuoHuList = [[false,0],[false,0],[false,0],[false,0],]/////TL++,各个玩家在本轮是否点击了过胡和点击过牌时的台数 this.isZHYZ = false;/////是不是最后1张 } // 重新洗牌 proto.shuffle = function () { this.castCount = 0; this.disCount = 0; this.cardsPool = _.clone(this.cardsyl); this.lastCount = this.cardsPool.length; this.cardsPool = _.shuffle(this.cardsPool);////随机打乱一个数组 this.cardsPool = _.shuffle(this.cardsPool);////洗第二次牌 // this.cardsPool = _.shuffle(this.cardsPool);////洗第三次牌 }; // 填充数组 proto.fillDeep = function (array, o, isMore) { for (let i = 0; i < array.length; ++i) { if (!isMore) { array[i] = _.clone(o); } else { array[i] = _.cloneDeep(o);/////深度拷贝,就是重新分配内存空间,浅拷贝则是两个变量共用一个内存对象 } } return array; }; //////TL++ 深复制一个object类型的数据 proto.deepCloneTL = function (obj){ let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(let key in obj){ if(obj.hasOwnProperty(key)){ //判断ojb子元素是否为对象,如果是,递归复制 if(obj[key]&& typeof obj[key] ==="object"){ objClone[key] = this.deepCloneTL(obj[key]); }else{ //如果不是,简单复制 objClone[key] = obj[key]; } } } } return objClone; }; // 获取类型 proto.getType = function (card) { return Math.floor(card / 10); }; // 获取牌值 proto.getValue = function (card) { return card % 10; }; // 手牌排序 proto.sort = function (handCards) { return _.sortBy(handCards);///降序排序 }; // 删除手牌 /////TL++参数isBuHua表示是否因为补花而造成的删除牌 proto.remove = function (handCards, cards) { if (typeof (cards) == 'number') { if (cards == handCards[handCards.length - 1]) { return (handCards.pop(), true); } else { let pos = handCards.indexOf(cards); if (pos == -1) return false; return (handCards.splice(pos, 1), true); } } var length = cards.length; if (length > 1 && cards[0] == cards[length - 1]) { if (cards[0] == handCards[handCards.length - 1]) { handCards.pop(); length -= 1; } let pos = handCards.indexOf(cards[0]); if (pos == -1) return false; handCards.splice(pos, length); } else { for (let i = 0; i < length; ++i) { let pos = handCards.indexOf(cards[i]); if (pos == -1) return false; handCards.splice(pos, 1); } } return true; }; // 调整手牌 proto.adjust = function (handCards) { var length = handCards.length; if (length < 2) return false; if (handCards[length - 1] < handCards[length - 2]) { let moCard = handCards.pop(); let pos = _.findIndex(handCards, (i) => (i >= moCard)); if (pos == -1) handCards.push(moCard); else handCards.splice(pos, 0, moCard); } return true; }; // 投骰子 proto.dice = function () { return _.random(1, 6); }; // 剩余牌数 proto.leaveCount = function () { return this.lastCount; }; //////TL++,人工设置测试牌型 proto.setTestSendCardsTL = function () { this.setCardFileName = ''; let fileName = "setHandCard_tianhu" if(!fileName) return;/////文件名字不存在 // console.warn("设置手牌的文件名",fileName); this.setCardFileName = fileName var SetHandCardTL = require('./setcard/' + fileName); if(!SetHandCardTL) return; //////TL++,设置手牌的文件 this.setHandCardTL = new SetHandCardTL(); ////console.error("洗牌之后的牌",this.cardsPool); let ccc = this.setHandCardTL.getSCFP(this.cardGroupIndex) if(ccc){//////已经设置的手牌发完了就随机发牌 this.cardsPool = ccc/////设置手牌的地方 设置牌 this.cardGroupIndex += 1; ////此句是否存在代表是否只发某一种牌型 // SetHandCardTL.cardGroupIndex += 1; ////此句是否存在代表是否只发某一种牌型 // if(SetHandCardTL.cardGroupIndex == 1) SetHandCardTL.cardGroupIndex = 0 } else{ this.setCardFilerIndex += 1; this.cardGroupIndex = 0; // SetHandCardTL.cardGroupIndex = 0; if(Logic.setCardFilerIndex < Logic.setHCfileNameList.length) this.setTestSendCardsTL() } } // 初始手牌 proto.handCards = function (chBanker,_PJHF,_over,recordid,_ctime) { this.resetDataOnGameStart()//////TL++ this.shuffle(); // if(this.hzCount == 8) { // this.cardsPool = [37,31,28,19,26,33,12,24,29,15,34,32,21,21,33,12,17,39,23,11,32,21,16,29,16,19,22,11,22,12,32,23,15,34,13,24,13,28,35,27,23,38,16,35,18,12,24,22,34,17,33,32,26,39,35,14,23,36,16,27,25,31,26,36,19,13,17,36,17,31,29,37,21,38,25,15,18,37,14,39,33,11,13,19,38,15,11,27,51,18,37,28,28,22,51,31,51,14,14,51,18,29,25,26,34,38,24,35,25,39,36,27] // this.setTestSendCardsTL()///////设置手牌的地方,设置发牌 不需要设置的时候注释掉这个方法就可以了 // this.lastCount = this.cardsPool.length;//////设置剩余牌数设置剩余牌数,测试完这句要删掉 // } let dqjs = _over + 1; _PJHF.writexpJson(this.deepCloneTL(this.cardsPool),dqjs,recordid,_ctime); //// 下面这个是随机发牌但是起手发lzgs张癞子的逻辑 // let lzgs = 4//癞子个数 // let djg = 0; // let djg2 = 31; // for (let i = 0; i < this.cardsPool.length; i++) { // if(this.cardsPool[i] == 51){ // if(djg < 2){ // let xx = this.cardsPool[djg] // this.cardsPool[djg] = 51; // this.cardsPool[i] = xx; // } // else{ // let xx = this.cardsPool[djg2] // this.cardsPool[djg2] = 51; // this.cardsPool[i] = xx; // djg2++; // } // djg++ // if(djg >= lzgs){ // break // } // } // } /////TL++设置百搭牌数组 this.setBDList() var result = []; var castCount = 0; for (let i = 0; i < this.playerAllCount; ++i) { let cardCount = CARDS_COUNT; if (i == chBanker) cardCount += 1; let cards = this.cardsPool.slice(castCount, castCount + cardCount); castCount += cardCount; result.push({ cards: this.sort(cards) }); } this.castCount += castCount this.lastCount -= castCount; // this.lastCount -= this.disCountTL;////因为翻出来的百搭牌不能被摸走 // console.error("发的手牌",result); return result; }; // 是否无牌 proto.isNoCards = function () { return this.lastCount <= 0; }; // 摸牌函数 proto.moCard = function (isgang) { // console.error("摸排摸排---------",isgang,this.disCountTL,this.lastCount); var card = 0; if (this.lastCount > 0) { card = this.cardsPool[this.castCount++]; this.lastCount -= 1; } return { card: card }; }; // 是否将牌 proto.isJang = function (lcard, rcard) { return lcard == rcard; }; ////判断吃碰补之后是否只剩下百搭牌了,因为如果吃碰补之后只剩下百搭牌,而百搭牌又不允许打出会造成玩家无牌可出的局面 proto.isCanCPB = function (handCards,opeate,type) { // console.warn("判断吃碰补之后是否只剩下百搭牌了 length "+handCards.length +" handCards "+JSON.stringify(handCards)+" opeate "+opeate+" type "+type); let length = handCards.length; let baiDaCount22 = this.getBDCount(handCards) let needCost = 0;//进行操作需要消耗的张数 if(opeate == STYLE.CHI || opeate == STYLE.PENG) needCost = 2; else if(opeate == STYLE.GANG){ //补牌,1-普通补, 2-暗补, 3-自摸补 //1-普通杠, 2-暗杠, 3-自摸明杠 if(type == 1) needCost = 3; else if(type == 2) needCost = 4; else if(type == 3) needCost = 1; } // console.warn("判断吃碰补之后是否只剩下百搭牌了 length "+length +" baiDaCount22 "+baiDaCount22+" needCost "+needCost); return (length - needCost - baiDaCount22 > 0); } // 可否碰牌 proto.isPeng = function (handCards, card) { if(card == 51) return false; for (let i = 0; i < handCards.length - 1; ++i) { if (handCards[i] == card && handCards[i + 1] == card) { return true; } } return false; }; // 碰牌 TL++参数chirID为了判断圈风和位风 proto.peng = function (chirID,handCards, card) { if (this.isPeng(handCards, card)) { return { style: STYLE.PENG, cards: [card, card, card], disc: [card] }; } }; // 吃牌,1-@**左吃, 2-*@*中吃, 3-@**右吃 proto.chi = function (handCards, card, type) { var chis = this.chiAnalyze(handCards, card, type); if (chis[0]) { let res = { style: STYLE.CHI, type: type, disc: [card] }; if (type == 1) { res.cards = [card, card + 1, card + 2]; if (this.getValue(card) < 7) { res.disc.push(card + 3); } } else if (type == 2) { res.cards = [card - 1, card, card + 1]; } else { res.cards = [card - 2, card - 1, card]; if (this.getValue(card) > 3) { res.disc.push(card - 3); } } return res; } }; // 杠牌,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风 proto.gang = function (chirID,handCards, card, type) { // 结果 var res = null; // 明杠 if (type == 1) { let gang = this.gangAnalyze(handCards, card); if (gang) { res = { style: STYLE.GANG, cards: [card, card, card] }; } } // 暗杠 else if (type == 2) { let anGang = this.anGangAnalyze(handCards, card); if (anGang[0]) { res = { style: STYLE.ANGANG, cards: [card, card, card] }; } } return res; }; // 自摸明杠,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风 proto.zmGang = function (chirID,handCards, huCards, card) { var zmGang = this.zmGangAnalyze(handCards, huCards, card); if (zmGang[0]) { return { style: STYLE.ZMGANG, cards: [card, card, card] }; } }; // 吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传 proto.chiAnalyze = function (handCards, card, type) { // 结果集合 var result = []; if(card == 51) return result; // 排除风字 if (handCards.length < 2 || card > 40) return result; // 查找句子 var length = handCards.length; for (let i = 0; i < length; ++i) { // 牌面值 let value = this.getValue(card); // @**左吃,吃类型(可以不指定) if (!type || type == 1) { if (value < 8 && i < length - 1) { if (handCards[i] == card + 1 && handCards[i + 1] == card + 2) { result.push({ type: 1, card: card }); } } } // *@*中吃,吃类型(可以不指定) if (!type || type == 2) { if (value > 1 && value < 9 && i < length - 1) { if (handCards[i] == card - 1 && handCards[i + 1] != card - 1) { for (let j = i + 1; j < i + 5 && j < length; ++j) { if (handCards[j] == card + 1) { result.push({ type: 2, card: card }); break; } } } } } // **@右吃,吃类型(可以不指定) if (!type || type == 3) { if (value > 2 && i < length - 1) { if (handCards[i] == card - 2 && handCards[i + 1] == card - 1) { result.push({ type: 3, card: card }); } } } } return result; }; // 普通杠分析,1-普通杠, 2-暗杠, 3-自摸明杠 proto.gangAnalyze = function (handCards, card) { // 结果对象 var result = null; if(card == 51 || this.lastCount <= 0) return result;//红中不能碰杠 var length = handCards.length; if (length < 3) return result; // 查找同牌 for (let i = 0; i < length - 2; ++i) { if (handCards[i] == card && handCards[i + 1] == card && handCards[i + 2] == card) { result = { type: 1, card: card }; break; } } return result; }; // 暗杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传 proto.anGangAnalyze = function (handCards, card) { // 结果对象 var result = []; if(this.lastCount <= 0) return result;//红中不能碰杠 var length = handCards.length; if (length < 4) return result; // 查找同牌 var moCard = handCards[length - 1]; for (let i = 0; i < length - 3; ++i) { // 指定杠牌,可以不指定 if (card && handCards[i] != card) continue; // 判定是否刻子 if (handCards[i] == handCards[i + 1] && handCards[i] == handCards[i + 2]) { // 手上有杠牌 if (handCards[i] == handCards[i + 3]) { if(handCards[i] != 51){ result.push({ type: 2, card: handCards[i] }); } } // 刚摸到杠牌 else if (handCards[i] == moCard) { if(handCards[i] != 51){ result.push({ type: 2, card: moCard }); } } } } return result; }; // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传 proto.zmGangAnalyze = function (handCards, huCards, card) { // 返回结果 var result = []; if(card == 51 || this.lastCount <= 0) return result;//红中不能碰杠 // 遍历句子 for (let i = 0; i < huCards.length; ++i) { if (huCards[i].style != STYLE.PENG) { continue; } let _card = huCards[i].cards[0]; if (card && _card != card) continue; let pos = handCards.indexOf(_card); if (pos != -1) { result.push({ type: 3, card: _card }); if (card) break; } } return result; }; // 分析牌型 proto.parseBlock = function (card1, card2, card3) { // 刻子 if (card1 && card1 == card2 && card1 == card3) { return { style: STYLE.KE, cards: [card1, card2, card3] }; } // 顺子(排除风字) var cards = this.sort([card1, card2, card3]); if (cards[2] < 40) { if (cards[2] == cards[1] + 1 && cards[1] == cards[0] + 1) { return { style: STYLE.SUN, cards: cards }; } } }; // TL++,得到手牌中百搭牌的个数 proto.getBDCount = function (cards) { ////TL++,整个for循环判断手牌中的百搭牌个数 let baiDaCount = 0 for (let i = 0; i < cards.length; ++i) { if(cards[i] == this.baiDaCard) baiDaCount = baiDaCount + 1 } return baiDaCount } // TL++,得到手牌中百搭牌的shuzu数组 proto.getBDListZZ = function (cards) { this.sbyBDList = []//////重置某人手牌中的百搭牌数组 ////TL++,整个for循环判断手牌中的百搭牌个数 let baiDaCount = 0 let baiDali = [] for (let i = 0; i < cards.length; ++i) { if(cards[i] == this.baiDaCard){ baiDali[baiDaCount] = cards[i] baiDaCount = baiDaCount + 1 } } return baiDali } // TL++,得到手牌中百搭牌的index数组 proto.getBDIndexList = function (cards) { ////TL++,整个for循环判断手牌中的百搭牌个数 let baiDali = [] for (let i = 0; i < cards.length; ++i) { let cardTL = cards[i]; if(this.baiDaList[0] && cardTL == this.baiDaList[0]) baiDali[baiDali.length] = i; else if(this.baiDaList[1] && cardTL == this.baiDaList[1]) baiDali[baiDali.length] = i; else if(this.baiDaList[2] && cardTL == this.baiDaList[2]) baiDali[baiDali.length] = i; } return baiDali } // TL++,得到手牌中百搭牌的index,用于删除手牌中的百搭牌 proto.getBDIndex = function (cards) { ////TL++,整个for循环判断手牌中的百搭牌个数 let baiDali = [] for (let i = 0; i < cards.length; ++i) { let cardTL = cards[i]; if(this.sbyBDList[0] && cardTL == this.sbyBDList[0]) baiDali[baiDali.length] = i; if(this.sbyBDList[1] && cardTL == this.sbyBDList[1]) baiDali[baiDali.length] = i; if(this.sbyBDList[2] && cardTL == this.sbyBDList[2]) baiDali[baiDali.length] = i; } return baiDali } // TL++,得到默认手牌中百搭牌当的数组 cards: 手牌去除百搭之后的牌 proto.getBDMakeList = function (cards,isNeedAllZi) { if(cards.length == 0){ ////手上就剩百搭牌的时候 需要把所有牌都当一遍 let reslist = [ 11, 12, 13, 14, 15, 16, 17, 18, 19, // 筒 21, 22, 23, 24, 25, 26, 27, 28, 29, // 万 31, 32, 33, 34, 35, 36, 37, 38, 39, // 条 ] return reslist; } ////TL++,整个for循环按照手牌情况确定百搭牌当的范围 let makeList = this.deepCloneTL(cards) for (let i = 0; i < cards.length; ++i) { let cardTL = cards[i]; let type = this.getType(cardTL); let vale = this.getValue(cardTL); if(type < 4){ if(vale == 1){ let makeValue = cardTL + 1; if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue; let makeValue2 = cardTL + 2; if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2; } else if(vale == 9){ let makeValue = cardTL - 1; if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue; let makeValue2 = cardTL - 2; if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2; } else if(vale == 2){ let makeValue = cardTL - 1; if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue; let makeValue2 = cardTL + 1; if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2; let makeValue3 = cardTL + 2; if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3; } else if(vale == 8){ let makeValue = cardTL - 1; if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue; let makeValue2 = cardTL - 2; if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2; let makeValue3 = cardTL + 1; if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3; } else if(vale > 2 && vale < 8){ let makeValue = cardTL - 1; if(makeList.indexOf(makeValue) == -1) makeList[makeList.length] = makeValue; let makeValue2 = cardTL + 1; if(makeList.indexOf(makeValue2) == -1) makeList[makeList.length] = makeValue2; let makeValue3 = cardTL - 2; if(makeList.indexOf(makeValue3) == -1) makeList[makeList.length] = makeValue3; let makeValue4 = cardTL + 2; if(makeList.indexOf(makeValue4) == -1) makeList[makeList.length] = makeValue4; } } } // let makeList2 = makeList.concat([41,42,43,44,51,52,53])/////给当的数组拼接字牌 // var xx = [1,1,2,3,4,1,2] // var xx22 = _.uniq(xx) // console.warn("数组去重",xx,xx22);///[ 1, 1, 2, 3, 4, 1, 2 ] [ 1, 2, 3, 4 ] // xx[1] = 6 // console.warn("22数组去重",xx,xx22);////[ 1, 6, 2, 3, 4, 1, 2 ] [ 1, 2, 3, 4 ] return _.uniq(makeList); } // 提取成句 card:手上的所有牌删除2张用来做将的牌之后剩下的牌 整理是否为刻子或者顺子 proto._dumpFixed = function (cards, huCards) { // if(this.currChairIDTL == 0){ // console.error("sscc提取成句没有百搭cards",cards); // console.error("sscc提取成ju没有百搭huCards",huCards); // } for (let i = 0; i < cards.length - 2; ++i) { let card = cards[i]; if (card <= 0) continue; if (card == cards[i + 1] && card == cards[i + 2]) { huCards.push({ style: STYLE.KE, cards: [card, card, card] }); cards[i] = 0; cards[i + 1] = 0; cards[i + 2] = 0; i += 2; continue; } if (card > 40 || this.getValue(card) > 7) continue; let second = -1, third = -1; for (let j = i + 1; j < cards.length; ++j) { if (cards[j] == card + 1) second = j; if (cards[j] == card + 2) third = j; if (cards[j] > card + 2) break; if (second != -1 && third != -1) break; } if (second != -1 && third != -1) { huCards.push({ style: STYLE.SUN, cards: [card, cards[second], cards[third]] }); cards[i] = 0; cards[second] = 0; cards[third] = 0; } } }; proto._dumpFixedc = function (cards,huCards,baidaCount) { let spkzgs = 4 - huCards.length;//手牌可组个数 let spkzzh = [];//手牌可组组合(1为刻2为顺) if(spkzgs == 1) spkzzh = [[1],[2]]; else if(spkzgs == 2) spkzzh = [[1,1],[1,2],[2,2],[2,1]]; else if(spkzgs == 3) spkzzh = [[1,1,1],[1,2,1],[1,1,2],[1,2,2],[2,2,2],[2,1,2],[2,2,1],[2,1,1]]; else if(spkzgs == 4){ spkzzh = [[1,1,1,1],[1,2,1,1],[1,1,2,1],[1,1,1,2], [1,2,2,1],[1,1,2,2],[1,2,1,2],[1,2,2,2], [2,2,2,2],[2,1,2,2],[2,2,1,2],[2,2,2,1], [2,1,1,2],[2,2,1,1],[2,1,2,1],[2,1,1,1] ] } //找到目标牌 var getMBCard = (cscards) => { for (let i = 0; i < cscards.length; ++i) { let card = cscards[i]; if (card <= 0) continue; else return card; } return -100; }; // let mbpailist = [12,15,15,15,16,17,18,25,26,27] // let islog = true; // if(mbpailist.length == cards.length){ // for (let i = 0; i < cards.length; ++i) { // if(mbpailist[i] != cards[i]) islog = false; // } // } // else{ // islog = false; // } // let mbpailist2 = [15,15,16,17,18,25,26,27,28,28,28] // if(islog) console.warn("_dumpFixedc 提取成句 baidaCount "+baidaCount+" cards "+cards+ " indexof "+mbpailist2.indexOf(15)); // console.warn("所有的判断组合 长度 "+spkzzh.length+" spkzzh "+JSON.stringify(spkzzh) ) let dqdpd = [0,0]//当前的判断 for (let x = 0; x < spkzzh.length; ++x) { let copyCards = this.deepCloneTL(cards) let bdCount = baidaCount; let huCards22 = []; // console.warn("当前的判断组合 "+dqdpd+" spkzzh[x] "+spkzzh[x]+" x "+x); // if(islog && x == 5) console.warn("当前的判断组合 "+dqdpd+" spkzzh[x] "+spkzzh[x]+" x "+x); for (let y = 0; y < spkzzh[x].length; ++y) { let ckORcs = spkzzh[x][y]//成刻或成顺(1为刻2为顺) // if(islog && x == 5) console.warn("当前的判断 "+dqdpd+" ckORcs "+ckORcs); if(ckORcs == 1){ let mbCard = getMBCard(copyCards);//目标card(mbCard这次应该成刻) if(mbCard > 0){ let index1 = copyCards.indexOf(mbCard); if(index1 != -1) copyCards[index1] = 0; // else console.error("这里不正常,都没有目标牌"); let cj = [mbCard];//成句 let index2 = copyCards.indexOf(mbCard); if(index2 != -1){ cj[cj.length] = mbCard; copyCards[index2] = 0; } else { if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } let index3 = copyCards.indexOf(mbCard); if(index3 != -1){ cj[cj.length] = mbCard; copyCards[index3] = 0; } else { if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } if(cj.length == 3){ huCards22.push({ style: STYLE.KE, cards: cj }); } else{ //mbCard不能成刻,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了 // console.warn("mbCard不能成刻,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了"); break; } } else{ //手牌全部都判断过了 if(bdCount >= 3){ huCards22.push({ style: STYLE.KE, cards: [51, 51, 51] }); bdCount -= 3; } //因为手里最多8张百搭,最多可以有6张百搭做成2个百搭刻,所以需要两次if if(bdCount >= 3){ huCards22.push({ style: STYLE.KE, cards: [51, 51, 51] }); bdCount -= 3; } break; } } else if(ckORcs == 2){ let mbCard = getMBCard(copyCards);//目标card(mbCard这次应该成刻) // if(islog && x == 5) console.warn("mbCard "+mbCard+" copyCards "+copyCards); if (mbCard < 40){ if(mbCard > 0){ let index1 = copyCards.indexOf(mbCard); if(index1 != -1) copyCards[index1] = 0; // else console.error("这里不正常,都没有目标牌"); let cj = [mbCard];//成句 if(this.getValue(mbCard) <= 7){ let index2 = copyCards.indexOf(mbCard+1); if(index2 != -1){ cj[cj.length] = copyCards[index2]; copyCards[index2] = 0; } else { if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } let index3 = copyCards.indexOf(mbCard+2); if(index3 != -1){ cj[cj.length] = copyCards[index3]; copyCards[index3] = 0; } else { if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } } else if(this.getValue(mbCard) == 8){ let index2 = copyCards.indexOf(mbCard+1); if(index2 != -1){ cj[cj.length] = copyCards[index2]; copyCards[index2] = 0; } else { if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } if(bdCount > 0){ cj[cj.length] = 51; bdCount -= 1; } } else if(this.getValue(mbCard) == 9){ if(bdCount > 1){ cj[cj.length] = 51; cj[cj.length] = 51; bdCount -= 2; } } if(cj.length == 3){ huCards22.push({ style: STYLE.SUN, cards: cj }); } else{ //mbCard不能成顺,说明spkzzh[x]这种组合是不行的,剩下的就不用判断了 break; } } else{ //手牌全部都判断过了 if(bdCount >= 3){ huCards22.push({ style: STYLE.SUN, cards: [51, 51, 51] }); bdCount -= 3; } //因为手里最多8张百搭,最多可以有6张百搭做成2个百搭刻,所以需要两次if if(bdCount >= 3){ huCards22.push({ style: STYLE.SUN, cards: [51, 51, 51] }); bdCount -= 3; } break; } } } // if(y < spkzzh[x].length-1) dqdpd=[x,y+1]; // else dqdpd=[x+1,0]; } // if(islog && x == 5) console.warn("提取成句 组合 "+" spkzzh[x] "+spkzzh[x]+" huCards22 "+JSON.stringify(huCards22) ); if(huCards22.length + huCards.length == 4){ //已经可以胡牌了,其他的组合就不需要判断了 for (var i = 0; i < huCards22.length; i++) { huCards.push(huCards22[i]); } break; } } }; //////TL++,判断一手张牌是否为百搭牌 proto.judgeACardISBD = function (card) { return card == this.baiDaCard; } // 胡牌分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的 proto.huAnalyze = function (chairID,handCards, card, huCards, isTouch) { // console.error("sscc777胡牌分析card",card); // console.error("sscc777胡牌分析handCards",handCards); // console.error("sscc777胡牌分析huCards",huCards); // console.error("sscc777胡牌分析isTouch",isTouch); // this.isHanDa = false;//////TL++,是否还搭(百搭牌用作原牌型,不累计) this.isPaoDa = false/////TL++,当前是不是抛搭,因为是抛搭的话不能打倒胡(吃胡) this.isQiDui = false;//////TL++,是否7对 let tempAllTai = 0/////临时总台数 let tempres = {}///本函数的返回值 this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡 this.isSeleCatcedCard = isTouch//////判断能否胡牌的那张牌是自己抓的还是别人打出来的 this.currChairIDTL = chairID/////当前判断胡的chairID,用于得到当前玩家的花牌情况 this.dangAfterBDListTL = [];/////7月18日+的 // console.warn("胡牌分析 isGuoHuList ",this.isGuoHuList," chairID ",chairID," isTouch ",isTouch); if(this.isGuoHuList[chairID][0]){ // console.warn("此人点过胡了 ",chairID," isTouch ",(!isTouch)); if(!isTouch){ // console.warn("不是此人摸牌 ",chairID,isTouch); return false; } } let baiDaCount22 = 0 let bdIndexlist = [] if (!isTouch){ baiDaCount22 = this.getBDCount(handCards) this.sbyBDList = this.getBDListZZ(handCards) handCards = handCards.concat(card);/////不是自己抓的就把这张牌拼接进手牌中 handCards = this.sort(handCards); bdIndexlist = this.getBDIndexList(handCards) } else{ handCards = this.sort(handCards); baiDaCount22 = this.getBDCount(handCards) this.sbyBDList = this.getBDListZZ(handCards) bdIndexlist = this.getBDIndexList(handCards) } // console.warn("判断13不搭手上百搭牌个数出错了?????",baiDaCount22,this.sbyBDList,bdIndexlist) handCards = this.sort(handCards); var huRes = { card: card, jiang: 0, huCards: [] }; // 重设将牌 var resetHuRes = (jiang) => { huRes.jiang = jiang; huRes.huCards = []; for (let huCard of huCards) huRes.huCards.push(huCard); }; // 手牌不全 var length = handCards.length; if (length % 3 != 2) return; let hucardTL = huCards//////TL++,保存碰杠牌的初始值,因为这个参数会在下面的代码中被修改掉 if(baiDaCount22 == 4 && this.hzCount == 4){ //选择4红中规则的时候,手里有4张红中的话可以直接胡,6红中8红中不可直接胡 // tempres = huCards return huRes; } if(baiDaCount22 == 0){/////没有百搭的时候 // 确定将牌 for (let i = 0; i < length - 1; ++i) { if (!this.isJang(handCards[i], handCards[i + 1])) continue; resetHuRes(handCards[i]);////设置将牌 let cards = handCards.slice(0, i);////手牌数组的前i个元素 cards = cards.concat(handCards.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 this._dumpFixed(cards, huRes.huCards); i += 1;/////TL++,为了减少运算 if(huRes.huCards.length >= 4){ return huRes; } } } else{/////有百搭的时候 let card2 = []//////用于存放手牌中将所有百搭牌去掉之后的手牌 for (let xx = 0; xx < this.sbyBDList.length; ++xx){ card2 = handCards.slice(0,bdIndexlist[xx] - xx)////得到数组中的前bdIndexlist[xx] 个元素 card2 = card2.concat(handCards.slice(bdIndexlist[xx]+1 - xx))////得到数组中的最后bdIndexlist[xx] +1 个元素 handCards = card2 // console.error("有百搭删除掉百搭牌",handCards,card2); } // console.warn("删除百搭之后的手牌222",handCards); let bdzs = this.sbyBDList.length;/////百搭张数 let copyhandCards = this.deepCloneTL(handCards) var huResTL = []; for (let huCard of huCards) huResTL.push(huCard); // console.warn("去掉百搭之后的手牌 copyhandCards "+copyhandCards); if(copyhandCards.length == 0) return huRes; //下面的for循环是用手牌的两张牌做将牌看能不能胡牌 for (let i = 0; i < copyhandCards.length - 1; ++i) { let cards22 = this.deepCloneTL(copyhandCards) if (!this.isJang(cards22[i], cards22[i + 1])) continue; let huRes3 = { card: card, jiang: 0, huCards: [] }; // 重设将牌 huRes3.jiang = cards22[i]; huRes3.huCards = []; for (let huCard of huCards) huRes3.huCards.push(huCard); let cards2 = cards22.slice(0, i);////手牌数组的前i个元素 cards2 = cards2.concat(cards22.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 this._dumpFixedc(cards2, huRes3.huCards,bdzs); // console.warn("判胡 2张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards)); if (huRes3.huCards.length >= 4){ return huRes3; } i += 1;/////TL++,为了减少运算 } //下面的for循环是用一张手牌和一张百搭牌做将牌看能不能胡牌 let bcjp = 0;///////本次的将牌 for (let i = 0; i < copyhandCards.length; ++i) { let cards22 = this.deepCloneTL(copyhandCards); if(cards22[i] == bcjp) continue; let huRes3 = { card: card, jiang: 0, huCards: [] }; // 重设将牌 huRes3.jiang = cards22[i]; huRes3.huCards = []; for (let huCard of huCards) huRes3.huCards.push(huCard); bcjp = cards22[i]; ///////本次的将牌 let cards2 = cards22.slice(0, i);////手牌数组的前i个元素 cards2 = cards2.concat(cards22.slice(i + 1));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 // console.warn("判胡 1张手牌做将length "+huRes3.huCards.length+" jiang "+huRes3.jiang+" huRes3.huCards "+JSON.stringify(huRes3.huCards)); this._dumpFixedc(cards2, huRes3.huCards,bdzs-1); if (huRes3.huCards.length >= 4){ return huRes3; } } } }; // // TL++胡牌提示 chairID(TL++这个参数) 手牌 手上的吃碰杠牌 这个是胡牌提示里不统计台数 proto.hutip = function (chairID,_handCards, _huCards,_allhuCards,outCards) { // return { // renyi:0,//////是否可胡任意牌,0表示不满足1表示满足 // kehuData:[]/////对象数组,分别表示打哪张可胡哪几张数据 // };////服务端运算量太大放到前端去计算了 this.yscs = 0 // console.warn("hutip777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs); // console.error("sscc777胡牌提示huCards",_huCards); let hutipRes = []; let handCards1 = _.clone(_handCards); // if(chairID == 1) console.warn("sscc777胡牌提示handCards1 ",chairID,_handCards); let huCards = _.clone(_huCards); let allhuCards = _.clone(_allhuCards);////用统计胡牌提示的剩余牌 let baiDaCount22 = this.getBDCount(_handCards); let dangPaiList = this.getBDMakeList(handCards1); if(baiDaCount22 == 4 && this.hzCount == 4){ //选择4红中规则的时候,手里有4张红中的话可以直接胡,6红中8红中不可直接胡 let kehuData2 = { renyi:1,//////是否可胡任意牌,0表示不满足1表示满足 kehuData:[]/////对象数组,分别表示打哪张可胡哪几张数据 }; return kehuData2; } if(baiDaCount22 < this.hzCount && this.hzCount > 0 && _handCards.indexOf(this.baiDaCard) == -1 && this.baiDaCard < 60){ dangPaiList[dangPaiList.length] = this.baiDaCard; } // if(chairID == 1) console.warn("hutip777胡牌提示 dangPaiList ",dangPaiList.length,dangPaiList); let kdcdp = 0;////可打出的牌 就是打出这个牌之后可以胡 let dczhkhdp = [];////打出kdcdp之后可以胡的牌 let yjpdgdsp = 0;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了 // let yjpdgdzh = [];////已经判断过的组合 把28换成26 和 把26换成28 的结果是一样的所以可以剔除以减少运算 for (var i = 0; i < handCards1.length; i++) { if(this.judgeACardISBD(handCards1[i])) continue; kdcdp = handCards1[i];////可打出的牌 dczhkhdp = []; if(handCards1[i] == yjpdgdsp) continue;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了 yjpdgdsp = handCards1[i];////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了 var huResTL = []; for (let huCard of huCards) huResTL.push(huCard); let copyhandCards = this.deepCloneTL(_handCards) for (let x = 0; x < copyhandCards.length; ++x) { if(this.judgeACardISBD(copyhandCards[x])){ copyhandCards[x] = 0;////剔除手里的百搭去判断抛搭 } } copyhandCards[i] = 0;///剔除手里的百搭和打出那张之后剩下的手牌去判断抛搭 let copyhandCardsqbd = _.compact(_.clone(copyhandCards)); copyhandCardsqbd = this.sort(copyhandCardsqbd); // let ispd = this.hutipJudgePAODA(baiDaCount22,copyhandCardsqbd,dangPaiList,huResTL.length,kdcdp);////打出kdcdp之后是否抛搭 //上面是旧的算法,下面是新的算法 let ispd = false; if(copyhandCardsqbd.length == 0){ ispd = true;//手上全是百搭肯定抛搭了 } else{ if(baiDaCount22 > 0){ ispd = this.hutipJudgePAODA2(baiDaCount22-1,copyhandCardsqbd,huResTL,kdcdp);////打出kdcdp之后是否抛搭 } } // console.warn("打出kdcdp之后是否抛搭 ",kdcdp,ispd,this.yscs); if(ispd){ ////打出kdcdp之后可以抛搭了 let data = { "canTing": kdcdp,////表示打出这张牌之后可以听牌 "youjin": 1,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用 "tpxq": dczhkhdp } hutipRes[hutipRes.length] = data; } else{ ////打出kdcdp之后不能抛搭 for (var k = 0; k < dangPaiList.length; k++) { this.yscs++; let handCards = _.clone(handCards1); // console.error("222sscc777胡牌提示huCards",i,handCards[i] , dangPaiList[k],handCards); handCards[i] = dangPaiList[k]; handCards = this.sort(handCards); // 手牌不全 var length = handCards.length; if (length % 3 != 2) return; // console.warn("pandau 0ceccewcde -------开始调用 hutip33"); let huRes22 = this.hutip33(chairID,handCards, dangPaiList[k], huCards,false); if (huRes22) { // console.warn("胡牌提示 打出 "+kdcdp+" 如果摸到 "+dangPaiList[k]+" 可以胡"); ////打出kdcdp如果摸到dangPaiList[k]可以胡 let syzs = this.getACardSYZS(dangPaiList[k],_handCards,allhuCards,outCards); // console.warn("111????????????????????????????????",dangPaiList[k],syzs); dczhkhdp[dczhkhdp.length] = [dangPaiList[k],-1,syzs];////[可胡的牌,剩余张数] } } // console.warn("222????????????????????????????????",dczhkhdp.length); if(dczhkhdp.length > 0){ ////至此表示打出handCards[i]之后可以听牌 let data = { "canTing": kdcdp,////表示打出这张牌之后可以听牌 "youjin": 0,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用 "tpxq": dczhkhdp } hutipRes[hutipRes.length] = data; } } } // console.warn("333????????????????????????????????",hutipRes); // console.warn("222sscc777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs); let kehuData3 = { renyi:0,//////是否可胡任意牌,0表示不满足1表示满足 kehuData:hutipRes/////对象数组,分别表示打哪张可胡哪几张数据 }; return kehuData3; // return hutipRes; }; ////TL++得到一张牌的剩余张数 用于胡牌提示提示该张的剩余张数 proto.getACardSYZS = function (card,_handCards,allhuCards,outCards) { ////下面这段是适合胡牌提示里用的剩余牌数统计 let yjcxdzs = 0;////该牌已经出现的张数 for (var i = 0; i < _handCards.length; i++) { if(card == _handCards[i]) yjcxdzs++;////该牌已经出现在自己手牌里的张数 } // console.warn("111得到一张牌的剩余张数 手牌张数",yjcxdzs,_handCards); for (var i = 0; i < allhuCards.length; i++) { if(allhuCards[i].length == 0) continue;////该玩家没有碰杠牌 // console.warn("222得到一张牌的剩余张数 碰杠杠牌",card,yjcxdzs,i,JSON.stringify(_.clone(allhuCards[i]))); for (var k = 0; k < allhuCards[i].length; k++) { let pgp = allhuCards[i][k].cards; if(!pgp) continue; for (var j = 0; j < pgp.length; j++) { if(card == pgp[j]) yjcxdzs++;////该牌已经出现在自己手牌里的张数 } } } for (var i = 0; i < outCards.length; i++) { if(outCards[i].length == 0) continue;////该玩家没有碰杠牌 // console.warn("2得到一张牌的剩余张数 打出去的牌",card,yjcxdzs,i,JSON.stringify(_.clone(outCards[i]))); for (var k = 0; k < outCards[i].length; k++) { if(card == outCards[i][k]) yjcxdzs++;////该牌已经出现在所有打出去牌里的张数; } } let zs = 4 if(card == 51) zs = this.hzCount; // if(this.judgeACardISBD(card)) zs = 3; let syzs = zs - yjcxdzs;////剩余张数 = 总张数 - 已经出现的张数 // console.warn("333得到一张牌的剩余张数",card,syzs); return syzs; }; //////TL++,胡牌提示判断抛搭 proto.hutipJudgePAODA2 = function (_baidacount,_hd,_huCards,_addThisIsHu) { // console.warn("胡牌提示判断抛搭 _baidacount "+_baidacount+" _hd.length "+_hd.length +" _hd "+_hd); let cards2 = this.deepCloneTL(_hd); let huRes3 = { card: 0, jiang: 0, huCards: [] }; huRes3.huCards = []; for (let huCard of _huCards) huRes3.huCards.push(huCard); this._dumpFixedc(cards2, huRes3.huCards,_baidacount); // console.warn("胡牌提示 判断判断抛搭 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards)); if (huRes3.huCards.length >= 4){ // console.warn("胡牌提示 判断判断抛搭 可以抛搭222 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards)); return true; } // console.warn("不能抛搭"); return false; } // 胡牌分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的 proto.hutip33 = function (chairID,handCards, card, huCards, isTouch) { // console.error("sscc777胡牌分析card",card); // console.error("sscc777胡牌分析handCards",handCards); // console.error("sscc777胡牌分析huCards",huCards); // console.error("sscc777胡牌分析isTouch",isTouch); let tempres = {}///本函数的返回值 // this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡 // console.error("sscc777胡牌分析333this.addThisIsHu ",this.addThisIsHu); // this.isSeleCatcedCard = isTouch//////判断能否胡牌的那张牌是自己抓的还是别人打出来的 // this.currChairIDTL = chairID/////当前判断胡的chairID,用于得到当前玩家的花牌情况 this.dangAfterBDListTL = [];/////7月18日+的 let baiDaCount22 = 0 let bdIndexlist = [] handCards = this.sort(handCards); baiDaCount22 = this.getBDCount(handCards) this.sbyBDList = this.getBDListZZ(handCards) bdIndexlist = this.getBDIndexList(handCards) // console.warn("判断13不搭手上百搭牌个数出错了?????",baiDaCount22,this.sbyBDList,bdIndexlist) // 手牌不全 var length = handCards.length; // console.warn("胡牌提示 length "+length+" baiDaCount22 "+baiDaCount22); if (length % 3 != 2) return; if(baiDaCount22 == 0){/////没有百搭的时候 var huRes = { card: card, jiang: 0, huCards: [] }; // 重设将牌 var resetHuRes = (jiang) => { huRes.jiang = jiang; huRes.huCards = []; for (let huCard of huCards) huRes.huCards.push(huCard); }; // let hucardTL = huCards//////TL++,保存碰杠牌的初始值,因为这个参数会在下面的代码中被修改掉 // 确定将牌 for (let i = 0; i < length - 1; ++i) { if (!this.isJang(handCards[i], handCards[i + 1])) continue; resetHuRes(handCards[i]);////设置将牌 let cards = handCards.slice(0, i);////手牌数组的前i个元素 cards = cards.concat(handCards.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 this._dumpFixed(cards, huRes.huCards); i += 1;/////TL++,为了减少运算 // let tempres22 = this.outHures(huRes,handCards,hucardTL); if(huRes.huCards.length >= 4){ return true; } } } else{/////有百搭的时候 let card2 = []//////用于存放手牌中将所有百搭牌去掉之后的手牌 for (let xx = 0; xx < this.sbyBDList.length; ++xx){ card2 = handCards.slice(0,bdIndexlist[xx] - xx)////得到数组中的前bdIndexlist[xx] 个元素 card2 = card2.concat(handCards.slice(bdIndexlist[xx]+1 - xx))////得到数组中的最后bdIndexlist[xx] +1 个元素 handCards = card2 // console.error("有百搭删除掉百搭牌",handCards,card2); } // console.warn("胡牌提示 删除百搭之后的手牌222",handCards); let bdzs = this.sbyBDList.length;/////百搭张数 let copyhandCards = this.deepCloneTL(handCards) // console.warn("去掉百搭之后的手牌 copyhandCards "+copyhandCards); if(copyhandCards.length == 0) return true; //下面的for循环是用手牌的两张牌做将牌看能不能胡牌 for (let i = 0; i < copyhandCards.length - 1; ++i) { let cards22 = this.deepCloneTL(copyhandCards) if (!this.isJang(cards22[i], cards22[i + 1])) continue; let huRes3 = { card: card, jiang: 0, huCards: [] }; // 重设将牌 huRes3.jiang = cards22[i]; huRes3.huCards = []; for (let huCard of huCards) huRes3.huCards.push(huCard); let cards2 = cards22.slice(0, i);////手牌数组的前i个元素 cards2 = cards2.concat(cards22.slice(i + 2));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 this._dumpFixedc(cards2, huRes3.huCards,bdzs); if (huRes3.huCards.length >= 4){ // console.warn("胡牌提示 判断结果222 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards)); return true; } i += 1;/////TL++,为了减少运算 } //下面的for循环是用一张手牌和一张百搭牌做将牌看能不能胡牌 let bcjp = 0;///////本次的将牌 for (let i = 0; i < copyhandCards.length; ++i) { let cards22 = this.deepCloneTL(copyhandCards); if(cards22[i] == bcjp) continue; let huRes3 = { card: card, jiang: 0, huCards: [] }; // 重设将牌 huRes3.jiang = cards22[i]; huRes3.huCards = []; for (let huCard of huCards) huRes3.huCards.push(huCard); bcjp = cards22[i]; ///////本次的将牌 let cards2 = cards22.slice(0, i);////手牌数组的前i个元素 cards2 = cards2.concat(cards22.slice(i + 1));////给数组cards拼接上手牌的第 i+2 个以后的全部数组元素 这句是将手牌删除2张将牌之后得到的牌 this._dumpFixedc(cards2, huRes3.huCards,bdzs-1); // console.warn("胡牌提示 判断结果233 length "+huRes3.huCards.length+" huRes3.huCards "+ JSON.stringify(huRes3.huCards)); if (huRes3.huCards.length >= 4){ return true; } } } return false; }; // 获得奖码列表和计算奖码分数函数 proto.getJiangmaInfo = function (isMZJYM) { // console.warn("获得奖码列表函数 奖码类型:-1:不奖码,1:159奖码,2:摸几奖几,3:一码全中 "+this.jiangmaType) let jiangmaList = [] let jmzs = 0;//奖码张数 if(this.jiangmaType == 2){ //摸几奖几 jmzs = this.getValue(this.addThisIsHu);//胡的那张牌的牌值 if(this.addThisIsHu == 51) jmzs = 10; // console.warn("摸几奖几 奖码樟树 addThisIsHu "+this.addThisIsHu+" jmzs "+jmzs); } else{ //159奖码 一码全中 jmzs = this.jiangmaCount; if(isMZJYM ){ //满足无红中加1码 jmzs++; } } if(this.isLaGang){ // console.warn("现在 是 拉杠胡了"); if(!this.isQGHJM){ //没有选择抢杠胡奖码 jmzs = 0; // console.warn("现在 是 拉杠胡了 选则了抢杠胡不奖码 现在不奖码"); } } else{ // console.warn("现在 不是 拉杠胡了"); } let castC1 = this.castCount;//已经消耗的 let lastC1 = this.lastCount; for (var i = 0; i < jmzs; i++) { let card = 0; if (lastC1 > 0) { card = this.cardsPool[castC1++]; lastC1 -= 1; } if(card > 0) jiangmaList[i] = card; else break; } // console.warn("获得奖码列表函数 奖码列表 ",jiangmaList," 长度 ",jiangmaList.length," addThisIsHu ",this.addThisIsHu) //下面是计算奖码分数 let mafen = 0; if(this.jiangmaType == 1 || this.jiangmaType == 2){ //159奖码 摸几奖几 let count = 0 for (var i = 0; i < jiangmaList.length; i++) { let pz = this.getValue(jiangmaList[i]);//牌值 if (pz == 1 || pz == 5 || pz == 9 || jiangmaList[i] == 51 ){ count++ } } mafen = 2 * count; } else if(this.jiangmaType == 3){ //一码全中 // console.warn("一码全中 jiangmaList ",jiangmaList) if(jiangmaList.length == 1){ let count = this.getValue(jiangmaList[0]); if(jiangmaList[0] == 51) count = 10; mafen = count; } } // console.warn("获得奖码分数 mafen ",mafen) return { jiangmaList:jiangmaList,mafen:mafen} };