| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625 |
- 'use strict';
- //// 为什么选择 Lodash ?
- //// Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。
- //// Lodash 的模块化方法 非常适用于:
- //// 遍历 array、object 和 string
- //// 对值进行操作和检测
- //// 创建符合功能的函数
- var _ = require('lodash');
- var bigInt = require('big-integer');
- var quick = require('quick-pomelo');
- var logger = quick.logger.getLogger('fhmj', __filename);
- // 所有牌
- const CARDS = [
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, //一到十
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, //壹到拾
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- ];
- // 块类型
- const STYLE = {
- NULL: 0, // 无效
- CHI: 1, // 吃牌
- SUN: 2, // 顺序
- PENG: 3, // 碰子
- KE: 4, // 刻子(起手3张一样的,不能把牌拖上去)
- GANG: 5, // 跑(杠子)能跑必须跑
- ANGANG: 6, // 提(暗杠)能提必须提
- ZMGANG: 7, // 跑(自摸明杠)能跑必须跑
- JIAO:8, // 绞牌
- BIPAI:9, // 比牌,吃牌能比时若要吃必须比
- WEI: 10, // 偎牌(手上2张摸牌过程中又摸到一张)能偎必须偎
- };
- // 有胡息类型
- const HUXITYPE = {
- NULL: 0, // 无效
- XIAOSHUN: 1, // 小顺
- DASHUN: 2, // 大顺
- XIAOKE: 3, // 小刻
- DAKE: 4, // 大刻
- XIAOPENG: 5, // 小碰
- DAPENG: 6, // 大碰
- XIAOWEI: 7, // 小偎
- DAWEI: 8, // 大偎
- XIAOPAO: 9, // 小跑
- DAPAO: 10, // 大跑
- XIAOTI: 11, // 小提
- DATI: 12, // 大提
- };
- // 哥有胡息类型对应的息数
- const HUXIVALUE = [
- 0, // 无效
- 3, // 小顺
- 6, // 大顺
- 3, // 小刻
- 6, // 大刻
- 1, // 小碰
- 3, // 大碰
- 3, // 小偎
- 6, // 大偎
- 6, // 小跑
- 9, // 大跑
- 9, // 小提
- 12 // 大提
- ];
- // 椅子数
- const CHAIR_COUNT = 3;
- const CARDS_COUNT = 20;
- // 天胡可以过胡
- // 庄家必须出牌,就算是起手连提两个(8块)也必须打牌
- // 3提五坎只发生在庄家打出第一张牌之前
- // A玩家摸的牌A要偎提B玩家要胡,应该偎提(如果是起手庄家的那张则应该胡的优先级高于庄家的偎提)
- // 提牌情况1:起手就有4张
- // 提牌情况2:当自己从墩上摸得牌,是“三”形成了4个“三”
- // 提牌情况3:当自己从墩上摸得牌,是自己已经“偎牌”的牌
- // 有跑必须跑,但是没有胡的优先级高(比如自己可胡可跑显示胡过点胡就胡点过就自动跑)
- // 跑牌情况1:当别人从墩上摸得牌,自己手上有一坎
- // 跑牌情况2:当自己从墩上摸得牌,是自己已经碰的牌
- // 跑牌情况3:当别人从墩上摸得牌,是自己已经碰的牌
- // 跑牌情况4:当别人从墩上摸得牌,是自己已经偎的牌
- // 跑牌情况5:当别人滑动手牌打出的牌,是自己已经偎的牌
- // 跑牌情况6:当别人滑动手牌打出的牌,自己手上有一坎
- // 偎牌情况1:当自己从墩上摸得牌,是自己手上已经有一对的牌(只发生在摸牌阶段)
- // 碰牌情况1:当别人从墩上摸得牌,是自己手上已经有一对的牌
- // 碰牌情况2:当别人滑动手牌打出的牌,自己手上有一对
- // 吃牌情况1:当自己或别人从墩上摸得牌,可以和自己手牌组成顺子或绞牌且可以成功比牌
- // 吃牌情况2:当别人滑动手牌打出的牌,可以和自己手牌组成顺子或绞牌且可以成功比牌
- // 构造方法
- var Logic = function (type,gameKindTL,playerAllCount,other) {
- // 类型
- this.type = type;
- this.other = other;//////TL++2人3人的游戏规则
- this.gameKindTL = gameKindTL || 1;//游戏类型 = 1代表全名堂 = 2代表大小子 = 3表示土跑胡
- let otherstr = ""+other;
- this.fengDingValue = parseInt(otherstr[6])*100;////封顶值:0:不封顶,1:封顶100,2:封顶200,3:封顶300
- this.tunshuValue = parseInt(otherstr[5]);////充囤值:0:不充囤,1:充1囤,2:充2囤,3:充3囤,4:充4囤,5:充5囤
- // 点灯规则:流局后黄+1,不切换庄家,闲家胡牌后黄-1,若庄家胡牌则黄不减1,有黄则满足“黄番”牌型
- // 不勾选点灯规则的话则黄的个数不会累加(要么是0要么是1)
- this.dengshuValue = -1;//-1:未勾选点灯规则,>-1:已勾选点灯规则下剩余的灯数,
- if(gameKindTL == 1 || gameKindTL == 2) this.dengshuValue = 0;
- let kexuanstr = " 可选规则: ";//
- if(this.gameKindTL == 1){
- if(parseInt(otherstr[1]) == 1) kexuanstr += " 点灯 ";
- if(parseInt(otherstr[3]) == 1) kexuanstr += " 有丁 ";
- if(parseInt(otherstr[4]) == 1) kexuanstr += " 有捉小三 ";
- }
- this.chouPaiShu = 0;
- if(playerAllCount == 2) {
- if(parseInt(otherstr[2]) == 1) this.chouPaiShu = 20;////抽牌张数:0:不抽牌,1:抽20张牌
- }
- console.warn("logic 游戏人数 抽牌张数 ",playerAllCount,this.chouPaiShu)
- console.warn("logic 游戏类型 = 1代表全名堂 = 2代表大小子 = 3表示土跑胡 "+this.gameKindTL+kexuanstr)
- console.warn("logic 封顶值 "+this.fengDingValue)
- console.warn("logic 充囤值 "+this.tunshuValue)
- this.xiaoType = 1;//小牌花色值(一到十)
- this.daType = 2;//大牌花色值(壹到拾)
- this.khMinHX = 15;//可胡需满足的最低胡息
- // 全牌
- var cards = _.clone(CARDS);
-
- this.castCount = 0;
- this.disCount = 0;
- this.lastCount = cards.length;//////设置剩余牌数为了测试海底捞月
- this.cardsPool = cards;
- this.cardsyl = _.clone(cards);
- //////以下变量全是TL++
- this.playerAllCount = playerAllCount || 3;////游戏人数 = 2表示2人局 = 3表示3人局
- this.setCardFilerIndex = 0
-
- this.chuPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡
- this.moPaiCountTL = 0//////TL++,记录出牌的个数,为了判断天胡和地胡
- this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id
- this.everyCPGS = [0,0,0]//////TL++,记录每个玩家的出牌的个数,为了判断听胡
- this.chBanker = -1;
- this.addThisIsHu = 0//////TL++,胡牌判断时加上这张能不能胡
- this.isGuoHuList = [[false,0],[false,0],[false,0],[false,0],]/////TL++,各个玩家在本轮是否点击了过胡和点击过牌时的台数
- this.setCardFileName = '';/////设置手牌的文件名
- this.cardGroupIndex = 0;////要设置的牌型种类
- // let bigNumber = BigInt(12345678901234567890);
- this.isZHYZ = false;/////是不是最后1张
- ////////下面是判胡算法新加的变量
- this.paiArr = [];//2位数牌数组,索引是牌id,值是牌数量
- this.lastNum = 0;//拆分的剩余牌的数量,只有全部拆完才算胡
- this.fromPaiId = 0;//进牌id
- this.SHUNZI = 1;//普通顺子
- this.HUNDUN = 2;//绞牌
- this.KAN = 3; //坎(刻子)
- this.TI = 4; //提
- this.DUIZI = 5; //对子
- this.S2710 = 6; //二七十和贰柒拾顺子
- this.bitType = 3;//占的二进制位数
- this.bitPai = 5;//占的二进制位数
- this.byteType = 7;//0x7;//占的二进制字节16进制代表7
- this.bytePai = 31;//0x1F;//占的二进制字节16进制代表31
- this.duiList = [];//保存所有可以胡的牌型,数组元素是long类型,有几个元素代表有几种不同的可组合成胡的方式
- this.laiZiList = [];//所有可以胡牌型用到的癞子保存在这里,元素代表本次可胡方式中百搭当的牌
- this.MAX_PAI_CNT = 22;
- this.WANG = 21;//表示百搭牌
- this.DA_SHI = 20;//表示拾(11~20分别代表壹~拾)
- this.XIAO_YI = 1;//表示一(1~10分别代表一~十)
- ////////判胡算法新加的变量结束
- this.huTypeTL = [/////分别表示牌型和台数
- ['天胡',6],//庄家刚刚起手21张牌的时候胡牌(庄家天胡也肯定自摸),或者庄家的三提五坎
- ['地胡',6],//庄家起手亮张的子(牌)闲家胡了。(庄家没有地胡闲家没有天胡)
- ['海胡',6],//胡的是墩上(剩余牌牌堆)最后一张牌。
- ['听胡',6],//没有进子(手牌没有改变)的情况下胡牌,满足天胡或者地胡的话一定是满足“听胡”的。
- ['红胡',3],//(3+N)胡牌时,手上的牌和操作(吃碰偎提跑)过的牌有超过10张红牌(二七十,贰柒拾)即满足“红胡”牌型,红牌张数在10张基础之上每多1张的话番数在基础3番多加1番。如11张红牌(3+1=4)番,12张红牌(3+2=5)番
- ['黑胡',8],//胡牌时没有一张红牌
- ['点胡',6],//胡牌时只有一张红牌
- ['大胡',8],//(8+N)胡牌时大子(大写的牌,如叁)张数>=18张,18张基础之上每多1张在起始8番上加1番
- ['小胡',10],//(10+N)胡牌时小子(小写的牌,如八)张数>=16张,16张基础之上每多1张在起始10番上加 1番,如17张小子=11番,20张小子=10+(20-16)=14番。
- ['耍猴',6],//胡牌时只剩一张牌(子)单吊。
- ['黄番',2],//结算本局算分完得到最后总得分之后,如果还有黄(灯数,参照点灯规则,则这局的最终总得分=本局总得分*2
- ['对子胡',8],//7个成句中每个成句都是同一个牌面数值(大小写不可交替),即7个成句 都是由偎碰刻或(提跑偎碰刻+1对,因为有提手上有个1对)构成的。(手上只能有一个对子)
- ['大团圆',10],//(10*N)跑或提了2个相同的牌,如跑或提“九”且跑或提“玖”,每个大团圆都要+10番
- ['真行息',10],//7个成句都是由有息的成句组成的(成句有息无息见胡息计算规则)(有 提不可能是真行,因为有个对子,这个对子没有息)
- ['假行息',6],//7个成句中有6个成句都是由有息的成句组成的,且没息的那列为对子(是对子意味着肯定有跑或提)
- ['四七红',2],//胡牌的时候手上有4张或7张红色牌(二七 十,贰柒拾)。
- ['真背靠背',10],//手中听牌是一对大小字,胡了其中一张。如手上有一对“一”和一对“壹”, 听牌“一”和“壹”,胡了“一”或“壹”,形成了“一”和“壹”一个刻子一个对子 则形成背靠背。只剩4张的时候是真背靠背
- ['假背靠背',6],//假背靠背:6番。手中听牌是一对大小字,胡了其中一张。如手上有一对“一”和一对“壹”, 听牌“一”和“壹”,胡了“一”或“壹”,形成了“一”和“壹”一个刻子一个对子 则形成背靠背。手牌大于4张的时候是假背靠背
- ['三提五坎',6],//有3个提或着5个坎,直接胡,仅限在发牌期间,在全名堂和大小子中不算牌型,土跑胡中算1番
- ['金屋藏娇',6],//提了小三
- ['丁',2],//可选,胡的那张牌是用来做对子的(肯定有提或者跑,满足耍猴肯定是满足“丁”的) 如“三三四五”别人明示的“三”,自己摸到的“三”不算,因为必须先偎掉
- ['捉小三',6]//可选,胡的那张牌是“三”,并且是自己摸到的。别人抓到的不算。
- ]
- this.xypddpxlb = [];//需要判断的牌型列表
- if(this.gameKindTL == 1){
- for (var i = 0; i < 19; i++) {//前20个牌型
- this.xypddpxlb.push(i);
- }
- if(parseInt(otherstr[3]) == 1) this.xypddpxlb.push(20);//丁
- if(parseInt(otherstr[4]) == 1) {
- this.xypddpxlb.push(19);//金屋藏娇
- this.xypddpxlb.push(21);//捉小三
- }
- }
- else if(this.gameKindTL == 2){
- for (var i = 0; i < 12; i++) {//前12个牌型
- this.xypddpxlb.push(i);
- }
- this.xypddpxlb.push(18);//三提五坎
- }
- else if(this.gameKindTL == 3){
- this.xypddpxlb.push(4);
- this.xypddpxlb.push(5);
- this.xypddpxlb.push(6);
- this.xypddpxlb.push(11);
- this.xypddpxlb.push(18);//三提五坎
- this.huTypeTL[18][1] = 1;
- }
- // console.warn("ppppppppppp 长度 "+cards.length+" cards "+cards);
- };
- Logic.setHCfileNameList =[/////全部设置牌型的文件名
- "setHandCard_tianhu",
- ]
- // 导出常量
- Logic.CARDS = CARDS;
- Logic.STYLE = STYLE;
- Logic.HUXITYPE = HUXITYPE;
- Logic.HUXIVALUE = HUXIVALUE;
- Logic.CHAIR_COUNT = CHAIR_COUNT;
- Logic.CARDS_COUNT = CARDS_COUNT;
- // 导出类
- module.exports = Logic;
- // 原型对象
- var proto = Logic.prototype;
- ///////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.everyCPGS = [0,0,0]//////TL++,记录每个玩家的出牌的个数,为了判断听胡
- this.chBanker = -1;
- this.chuPaiCountTL = 0//////TL++出牌个数
- this.moPaiCountTL = 0//////TL++,记录摸牌的个数,为了判断天胡和地胡
- this.lastMoPaiChairID = 0//////TL++,最后一个摸牌玩家的id
- this.addThisIsHu = 0//////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 / 100);
- };
- // 获取牌值
- proto.getValue = function (card) {
- return card % 100;
- };
- // 手牌排序
- proto.sort = function (handCards) {
- return _.sortBy(handCards);///降序排序
- };
- // 删除手牌
- 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);
- }
- }
- // console.warn("删除手牌");
- var length = cards.length;
- for (let i = 0; i < length; ++i) {
- let pos = handCards.indexOf(cards[i]);
- if (pos == -1) return false;
- }
- 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.removes = function (_handCards, cards) {
- // console.warn("删除手牌",_handCards, cards);
- let handCards = this.arr2ToArr1(_handCards,false);
- 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;
- for (let i = 0; i < length; ++i) {
- let pos = handCards.indexOf(cards[i]);
- if (pos == -1) return false;
- }
- for (let i = 0; i < length; ++i) {
- let pos = handCards.indexOf(cards[i]);
- if (pos == -1) return false;
- handCards.splice(pos, 1);
- }
- return this.changeRes2(handCards);
- };
- // 删除手牌,适合吃碰偎中使用,为了实现
- proto.removes2 = function (_handCards, cards) {
- // console.warn("删除吃碰偎手牌111 ",JSON.stringify(_handCards), cards);
- // let handCards = _.cloneDeep(_handCards);
- //不能按照上面那个写法,否则会在吃方法里调用的时候使用如下参数会出现两个207都被删除(handCards[x][y] = 0;这句里把2个207改为0)
- //如果使用上面那种写法就需要在调用的时候使用this.deepCloneTL()方法对参数进行深复制
- //[[202,207,210],[202,207,210],[102,107,110],[102,107,110],[206,205,204],[104],[105,105],[106,103]] [206,207,205,105,105]
- let handCards = this.deepCloneTL(_handCards);
- let clgs = 0;//处理个数
- for (var i = 0; i < cards.length; i++) {
- let c = cards[i];
- for (var x = handCards.length-1; x >= 0; x--) {
- let sfzd = false;
- for (var y = 0; y < handCards[x].length; y++) {
- if(handCards[x][y] == c){
- handCards[x][y] = 0;
- sfzd = true;
- clgs++;
- break;
- }
- }
- if(sfzd) break;
- }
- }
- if(clgs != cards.length) return false;
- for (var i = 0; i < handCards.length; i++) {
- handCards[i] = handCards[i].filter(item => item !== 0);
- }
- handCards = handCards.filter(subArray => subArray.length > 0);
- let res = {
- changeRes: 0,
- };
- res.handCards = _.cloneDeep(handCards);
- // console.warn("删除吃碰偎手牌222 ",JSON.stringify(res.handCards));
- let styles = this.getCardStyle(res.handCards);
- let hxTypes = this.getCardHXType(res.handCards,styles);
- let hxValues = this.getCardHXValue(hxTypes);
- res.handHXInfos = {
- styles: styles,//玩家i的手牌块列表,为了计算这列手牌的胡息类型
- hxTypes: hxTypes,//玩家i的手牌胡息类型列表,为了计算这列手牌的胡息息数
- hxValues: hxValues,//玩家i的手牌胡息类型的息数列表,为了前端显示
- }
- // console.warn("删除手牌之后的结果333 ",JSON.stringify(handCards),res);
- return res;
- };
- // 删除指定位置的一张手牌,适合出牌时使用
- proto.removeACardByPos = function (handCards, handHXInfos, card, oldIndex) {
- // console.warn("删除指定位置的一张手牌,适合出牌时使用",handCards, card, oldIndex);
- let res = {
- changeRes: 0,
- };
- if(!handCards[oldIndex[0]] || !handCards[oldIndex[0]][oldIndex[1]] || handCards[oldIndex[0]][oldIndex[1]] != card){
- res.changeRes = 2;//传上来的牌值和所在位置对不上
- return res;
- }
- let oldStyle = handHXInfos.styles[oldIndex[0]];//手牌中老坐标所在列的块类型
- if(oldStyle == STYLE.ANGANG || oldStyle == STYLE.KE){
- res.changeRes = 4;//手牌的提和刻子所在的列的牌不允许挪动
- return res;
- }
- // let pos = _.findIndex(handCards[oldIndex[0]],card);//这么写不行
- let pos = handCards[oldIndex[0]].indexOf(card);
- if(pos == -1){
- res.changeRes = 5;//系统错误了,能走到这里肯定是有问题的
- return res;
- }
- handCards[oldIndex[0]].splice(pos, 1);
- if(handCards[oldIndex[0]].length > 0){
- let styles = this.getCardStyle([handCards[oldIndex[0]]]);
- let hxTypes = this.getCardHXType([handCards[oldIndex[0]]],[styles[0]]);
- let hxValues = this.getCardHXValue([hxTypes[0]]);
- handHXInfos.styles[oldIndex[0]] = styles[0];
- handHXInfos.hxTypes[oldIndex[0]] = hxTypes[0];
- handHXInfos.hxValues[oldIndex[0]] = hxValues[0];
- }
- else {
- let filteredArray = handCards.filter(subArray => subArray.length > 0);
- handCards = filteredArray;
- handHXInfos.styles.splice(oldIndex[0],1);
- handHXInfos.hxTypes.splice(oldIndex[0],1);
- handHXInfos.hxValues.splice(oldIndex[0],1);
- }
- res.handCards = handCards;
- res.handHXInfos = handHXInfos;
- // console.warn("调删除指定位置的一张手牌,适合出牌时使用 之后的结果 ",handCards,handHXInfos,res);
- return res;
- };
- // 调整手牌
- 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.changeRes = function (_handCards,handHXInfos,card,oldIndex,newIndex) {
- let res = {
- changeRes: 0,
- };
- let handCards = this.deepCloneTL(_handCards);
- // console.warn("调整之前的手牌 ",handCards," card ",card," ",handCards[oldIndex[0]]);
- if(newIndex[0] >= handCards.length) {
- newIndex[0] = handCards.length;
- handCards[handCards.length] = [];
- }
- if(handCards[newIndex[0]].length > 3){
- res.changeRes = 1;//每列最多只能放4张牌
- return res;
- }
- if(!handCards[oldIndex[0]] || !handCards[oldIndex[0]][oldIndex[1]] || handCards[oldIndex[0]][oldIndex[1]] != card){
- // console.warn("调整之前的手牌 ",handCards," card ",card," ",handCards[oldIndex[0]]);
- res.changeRes = 2;//传上来的牌值和所在位置对不上
- return res;
- }
- let newStyle = handHXInfos.styles[newIndex[0]];//手牌中新坐标所在列的块类型
- if(newStyle == STYLE.ANGANG || newStyle == STYLE.KE){
- res.changeRes = 3;//手牌的提和刻子所在的列不能放入其他牌
- return res;
- }
- let oldStyle = handHXInfos.styles[oldIndex[0]];//手牌中老坐标所在列的块类型
- if(oldStyle == STYLE.ANGANG || oldStyle == STYLE.KE){
- res.changeRes = 4;//手牌的提和刻子所在的列的牌不允许挪动
- return res;
- }
- // let pos = _.findIndex(handCards[oldIndex[0]],card);//这么写不行
- let pos = handCards[oldIndex[0]].indexOf(card);
- if(pos == -1){
- res.changeRes = 5;//系统错误了,能走到这里肯定是有问题的
- return res;
- }
- let ylspcount = this.getSPZS(handCards);//调整前原来手牌数量
- // console.warn("添加前 ",handCards[oldIndex[0]],handCards[newIndex[0]]," handCards ",handCards);
- if(newIndex[0] == oldIndex[0]){
- let xwzyldp = handCards[newIndex[0]][newIndex[1]];//新位置原来的牌
- handCards[newIndex[0]][newIndex[1]] = handCards[oldIndex[0]][oldIndex[1]];
- handCards[oldIndex[0]][oldIndex[1]] = xwzyldp;
- if(!xwzyldp){//新位置没有牌
- handCards[oldIndex[0]] = _.compact(handCards[oldIndex[0]]);
- }
- }
- else{
- if(handCards[newIndex[0]].length >= newIndex[1]){
- handCards[newIndex[0]].splice(newIndex[1], 0, card); //在下标为newIndex[1]的位置添加元素card
- }
- else{
- handCards[newIndex[0]].push(card)
- }
- // handCards[oldIndex[0]].splice(pos, 1);因为是操作参数这么写不行
- // 上面这写法操作方法参数时会多删除(如果操作的是局局部变量就没有问题),所以改成了下面这样
- // 例如最左侧的两列都是1,2,3,把2挪到最右侧新建一列时会把前2列里的2都删除
- let oldIndexCards = _.cloneDeep(handCards[oldIndex[0]]);
- oldIndexCards.splice(pos, 1);
- handCards[oldIndex[0]] = _.cloneDeep(oldIndexCards);
- }
- // console.warn("添加后 ",handCards[oldIndex[0]],handCards[newIndex[0]]," handCards ",handCards);
- let xzspcount = this.getSPZS(handCards);//调整后现在手牌数量
- if(ylspcount != xzspcount){
- //调整过程中出问题了
- res.changeRes = 6;//调整前后牌的张数不一样了
- return res;
- }
- if(handCards[newIndex[0]].length > 0){
- let styles = this.getCardStyle([handCards[newIndex[0]]]);
- let hxTypes = this.getCardHXType([handCards[newIndex[0]]],[styles[0]]);
- let hxValues = this.getCardHXValue([hxTypes[0]]);
- handHXInfos.styles[newIndex[0]] = styles[0];
- handHXInfos.hxTypes[newIndex[0]] = hxTypes[0];
- handHXInfos.hxValues[newIndex[0]] = hxValues[0];
- }
- if(handCards[oldIndex[0]].length > 0){
- let styles = this.getCardStyle([handCards[oldIndex[0]]]);
- let hxTypes = this.getCardHXType([handCards[oldIndex[0]]],[styles[0]]);
- let hxValues = this.getCardHXValue([hxTypes[0]]);
- handHXInfos.styles[oldIndex[0]] = styles[0];
- handHXInfos.hxTypes[oldIndex[0]] = hxTypes[0];
- handHXInfos.hxValues[oldIndex[0]] = hxValues[0];
- }
- else {
- let filteredArray = handCards.filter(subArray => subArray.length > 0);
- // console.warn("去掉长度为0的数组元素",filteredArray,handCards);
- handCards = filteredArray;
- // console.warn("去掉长度为0的数组元素2222 ",handCards);
- handHXInfos.styles.splice(oldIndex[0],1);
- handHXInfos.hxTypes.splice(oldIndex[0],1);
- handHXInfos.hxValues.splice(oldIndex[0],1);
- }
- res.handCards = handCards;
- res.handHXInfos = handHXInfos;
- // console.warn("调整牌之后的结果 ",handCards,handHXInfos,res);
- return res;
- };
- // 调整手牌(理牌按钮理牌)
- proto.changeRes2 = function (_handCards) {
- let res = {
- changeRes: 0,
- };
- let handCards = this.arr2ToArr1(_handCards,true);
- res.handCards = this.groupCards(handCards);
- let styles = this.getCardStyle(res.handCards);
- let hxTypes = this.getCardHXType(res.handCards,styles);
- let hxValues = this.getCardHXValue(hxTypes);
- res.handHXInfos = {
- styles: styles,//玩家i的手牌块列表,为了计算这列手牌的胡息类型
- hxTypes: hxTypes,//玩家i的手牌胡息类型列表,为了计算这列手牌的胡息息数
- hxValues: hxValues,//玩家i的手牌胡息类型的息数列表,为了前端显示
- }
- // console.warn("调整牌之后的结果222 ",JSON.stringify(handCards),res);
- return res;
- };
- // 剩余牌数
- 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();
-
- // this.cardsPool = [102,107,208,202,108,209,101,101,109,110,201,104,202,210,206,202,105,207,207,204,205,210,102,109,206,207,204,209,205,109,108,106,208,204,102,204,201,206,107,107,105,203,207,110,103,106,103,203,203,208,203,201,110,101,201,209,205,208,103,210,108,105,101,205,104,106,210,107,104,106,109,104,102,202,206,103,209,110,105,108]
- // this.cardsPool = [101,207,203,106,208,102,201,206,102,104,107,206,204,108,104,209,109,101,201,207,108,205,204,102,106,208,205,110,208,105,105,210,103,110,206,106,209,108,105,207,107,209,201,208,104,203,109,105,107,101,210,102,109,205,107,109,203,104,202,106,103,110,204,202,201,103,210,209,202,103,101,203,108,206,110,205,210,204,202,207]
- // this.cardsPool = [203,105,101,107,108,201,105,109,101,108,107,105,202,210,108,110,107,101,203,102,208,204,210,206,201,205,202,105,208,208,103,109,201,209,202,209,106,106,103,109,207,110,203,204,101,210,102,205,104,206,106,208,204,209,108,102,109,201,209,107,110,207,103,110,205,207,207,206,206,204,104,104,104,106,203,103,102,202,210,205]
- // this.cardsPool = [105,104,107,102,107,204,209,207,203,205,206,210,101,201,106,108,104,101,105,206,103,209,210,203,110,210,108,103,209,207,206,105,210,110,203,201,101,110,109,202,104,204,205,102,208,202,109,108,208,204,206,110,102,108,207,205,201,105,103,106,109,104,202,202,201,209,208,102,106,207,101,204,106,203,208,109,103,107,205,107]
- // this.cardsPool = [202,103,206,206,108,208,102,201,209,107,202,105,208,101,205,102,106,110,207,205,207,103,103,104,101,106,104,109,205,202,102,204,210,203,210,109,209,208,106,209,209,210,207,107,206,101,201,101,203,208,102,108,110,105,108,103,107,104,204,105,109,110,203,201,203,201,106,210,109,207,105,108,104,204,204,206,110,202,107,205]
- // this.cardsPool = [202,208,106,103,205,107,203,210,201,206,210,209,209,204,108,201,104,110,102,108,107,108,209,203,104,205,202,203,207,109,203,206,101,107,110,109,103,105,210,101,102,205,204,209,108,101,105,105,109,104,207,106,206,105,202,102,204,102,201,204,208,210,104,208,202,109,201,205,206,101,107,106,106,103,110,103,208,207,110,207]
- // this.cardsPool = [102,109,207,106,206,102,210,208,207,107,201,101,206,208,201,205,105,210,206,110,204,201,205,209,110,103,107,104,109,202,104,208,101,107,201,204,108,206,210,107,209,109,202,205,108,203,109,202,103,202,105,208,207,108,108,104,110,207,101,210,106,102,110,203,209,101,204,205,103,104,203,105,103,102,209,105,106,203,106,204]
- // this.setTestSendCardsTL()///////设置手牌的地方,设置发牌 不需要设置的时候注释掉这个方法就可以了
- // this.lastCount = this.cardsPool.length;//////设置剩余牌数设置剩余牌数,测试完这句要删掉
- this.lastCount -= this.chouPaiShu;//处理抽牌张数可选项
- let dqjs = _over + 1;
- _PJHF.writexpJson(this.deepCloneTL(this.cardsPool),dqjs,recordid,_ctime);
- this.chBanker = chBanker;
- var result = [];
- var castCount = 0;
- for (let i = 0; i < this.playerAllCount; ++i) {
- let cardCount = CARDS_COUNT;
- let cards = this.cardsPool.slice(castCount, castCount + cardCount);
- castCount += cardCount;
- result.push({ cards: this.sort(cards) });
- }
- this.castCount += castCount
- this.lastCount -= castCount;
- // console.warn("发的手牌111",JSON.stringify(result));
- for (let i = 0; i < this.playerAllCount; ++i) {
- result[i].cards = this.groupCards(result[i].cards);
- // console.warn("发牌函数里面获取手牌的块getCardStyle ");
- let styles = this.getCardStyle(result[i].cards);
- let hxTypes = this.getCardHXType(result[i].cards,styles);
- let hxValues = this.getCardHXValue(hxTypes);
- result[i].hxinfo = {
- styles: styles,//玩家i的手牌块列表,为了计算这列手牌的胡息类型
- hxTypes: hxTypes,//玩家i的手牌胡息类型列表,为了计算这列手牌的胡息息数
- hxValues: hxValues,//玩家i的手牌胡息类型的息数列表,为了前端显示
- }
- }
- // console.warn("发的手牌222",JSON.stringify(result));
- return result;
- };
- //整理手牌(新的,逻辑是逻辑是先去掉坎和刻,再去掉所有对子,然后将剩下单牌组成有息的顺子(一二三,二七十)并去掉,之后去掉能和对子组成绞牌的单牌,剩余单牌去掉普通顺子,最后剩余的单牌称为杂牌,杂牌每3张一列进行放置)
- proto.groupCards = function (_Cards) {
- // console.error("整理手牌 ",JSON.stringify(_Cards));
- let Cards = _.cloneDeep(_Cards);
- let CardsCopy = _.cloneDeep(_Cards);
- // console.error("判断桌子是否存在 ");
- // let Cards = [101,102,102,102,103,106,106,106,107,108,201,202,202,203,203,205,205,206,206,207,208]
- // let CardsCopy = [101,102,102,102,103,106,106,106,107,108,201,202,202,203,203,205,205,206,206,207,208]
- // // // let group1 = _.groupBy(Cards, function (n) { return n % 100 })
- // // //// group1 = {"1":[101,201],"2":[102,102,102,202,202],"3":[103,203,203],"5":[205,205],"6":[106,106,106,206,206],"7":[107,207],"8":[108,208]}
- // // // let map1 = _.map(Object.keys(group1), function (n) { return Number(n) });
- // // //// map1 = [1,2,3,5,6,7,8]
- // let group2 = _.groupBy(Cards, function (n) { return n})
- // console.error("group2 = ",group2);
- // // // // group2 = {"101":[101],"102":[102,102,102],"103":[103],"106":[106,106,106],"107":[107],"108":[108],
- // // // // "201":[201],"202":[202,202],"203":[203,203],"205":[205,205],"206":[206,206],"207":[207],"208":[208]}
- // // let map2 = _.map(Object.keys(group2), function (n) { return Number(n) });
- // // // map2 [101,102,103,106,107,108,201,202,203,205,206,207,208]
- // // console.error("group2 = ",JSON.stringify(group2)," map2 ",JSON.stringify(map2));
- // // let order2 = _.sortBy((group2, function (n) { return n.length})
- // // console.error("group2 = ",group2," order2 ",order2);
- // var values2 = _.values(group2);
- // // values2 = [[101],[102,102,102],[103],[106,106,106],[107],[108],[201],[202,202],[203,203],[205,205],[206,206],[207],[208]]
- // console.error(" values2 ",values2,JSON.stringify(values2));
- // var sortVal = _.sortBy(values2, function (n) { return n.length }).reverse();
- // //sortVal = [[106,106,106],[102,102,102],[206,206],[205,205],[203,203],[202,202],[208],[207],[201],[108],[107],[103],[101]]
- // console.error(" sortVal ",sortVal,JSON.stringify(sortVal));
- let dspzs = [[201,202,203],[202,207,210]];//大顺的牌值列表
- let xspzs = [[101,102,103],[102,107,110]];//小顺的牌值列表
- let res = [];
- let gc = _.groupBy(Cards, function (n) { return n})
- let vc = _.values(gc);
- var sortVal = _.sortBy(vc, function (n) { return n.length }).reverse();
- // console.error(" sortVal ",sortVal);
- // console.error(" Cards111 ",JSON.stringify(Cards));
- let tikeList = [];//手牌中的提刻列表
- let dashunList = [];//手牌中的大顺列表
- let xiaoshunList = [];//手牌中的小顺列表
- let chengshuangList = [];//手牌中的成双列表
- let jiaoList = [];//手牌中的绞牌列表
- let duiziList = [];//手牌中的对子列表
- let danpaiList = [];//手牌中的单牌列表
- for (var i = 0; i < sortVal.length; i++) {
- if(sortVal[i].length >= 3){
- tikeList.push(sortVal[i]);
- let issccg = this.remove(Cards,sortVal[i]);//从手牌中剔除可组成刻提的牌
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("牌出错了111 ",JSON.stringify(Cards));
- return [];
- }
- }
- }
- let gc2 = _.groupBy(Cards, function (n) { return n})
- let vc2 = _.values(gc2);
- for (var i = 0; i < vc2.length; i++) {
- if(vc2[i].length == 1) danpaiList = danpaiList.concat(vc2[i]);
- else if(vc2[i].length == 2) chengshuangList.push(vc2[i]);
- else {
- console.error("牌出错了222 ",JSON.stringify(CardsCopy));
- return [];
- }
- }
- // console.warn("整理手牌 最开始的单牌 danpaiList ",JSON.stringify(danpaiList));
- for (var j = 0; j < dspzs.length; j++) {
- for (var i = 0; i < 2; i++) {//手牌中剔除刻子之后最多2个大顺
- let issccg = this.remove(danpaiList,dspzs[j]);//从手牌中剔除可组成大顺的牌
- // if(issccg) console.warn(" 成了大顺之后Cards222 ",JSON.stringify(danpaiList));
- if(issccg) dashunList.push(dspzs[j])
- else break;
- }
- }
- for (var j = 0; j < xspzs.length; j++) {
- for (var i = 0; i < 2; i++) {//手牌中剔除刻子之后最多2个小顺
- let issccg = this.remove(danpaiList,xspzs[j]);//从手牌中剔除可组成小顺的牌
- // if(issccg) console.warn(" 成了小顺之后Cards333 ",JSON.stringify(danpaiList));
- if(issccg) xiaoshunList.push(xspzs[j])
- else break;
- }
- }
- // console.warn("整理手牌 去掉大小顺之后的单牌 danpaiList ",JSON.stringify(danpaiList));
- //下面是在单牌中提取普通顺子和能和对子组成绞牌的牌
- let dpszList = [];//手牌中的单牌可组成的顺子列表
- let dphdzkzjpList = [];//手牌中的单牌和对子可组成的绞牌列表
-
- for (var j = 0; j < chengshuangList.length; j++) {
- let sfcj = false;//是否可以成绞
- for (var i = 0; i < danpaiList.length; i++) {
- if(this.getValue(danpaiList[i]) == this.getValue(chengshuangList[j][0])){
- dphdzkzjpList.push(danpaiList[i])
- jiaoList.push([danpaiList[i],chengshuangList[j][0],chengshuangList[j][1]]);
- sfcj = true;
- break;
- }
- }
- if(!sfcj) duiziList.push(chengshuangList[j])
- }
- if(dphdzkzjpList.length > 0){
- let issccg = this.remove(danpaiList, dphdzkzjpList);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了555 ",JSON.stringify(danpaiList),dphdzkzjpList);
- return [];
- }
- }
- // console.warn("整理手牌 dphdzkzjpList ",JSON.stringify(dphdzkzjpList));
- for (var i = 0; i < danpaiList.length-2; i++) {
- if(danpaiList[i]+1 == danpaiList[i+1] && danpaiList[i]+2 == danpaiList[i+2]){
- dpszList.push([danpaiList[i],danpaiList[i+1],danpaiList[i+2]])
- i+=2;
- }
- }
- // console.warn("整理手牌 单牌可组顺子 dpszList ",JSON.stringify(dpszList));
- for (var i = 0; i < dpszList.length; i++) {
- let needRemoves = dpszList[i];
- let issccg = this.remove(danpaiList, needRemoves);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了444 ",JSON.stringify(danpaiList),needRemoves);
- return [];
- }
- }
- // console.warn("整理手牌 剔除可组顺子的单牌 danpaiList ",JSON.stringify(danpaiList));
- // console.warn("整理手牌 最hou的单牌 danpaiList ",JSON.stringify(danpaiList));
-
- danpaiList = _.chunk(danpaiList, 3);
- // console.warn("手牌中的提刻列表 ",tikeList);//
- // console.warn("手牌中的大顺列表 ",dashunList);//
- // console.warn("手牌中的小顺列表 ",xiaoshunList);//
- // console.warn("手牌中的普通顺子列表 ",dpszList);//
- // console.warn("手牌中的绞牌列表 ",jiaoList);//
- // console.warn("手牌中的对子列表 ",duiziList);//
- // console.warn("手牌中的单牌列表 ",danpaiList);//
- res = res.concat(tikeList);//
- res = res.concat(dashunList);//
- res = res.concat(xiaoshunList);//
- res = res.concat(dpszList);//
- res = res.concat(jiaoList);//
- res = res.concat(duiziList);//
- res = res.concat(danpaiList);//
- // console.warn("整理之后的牌 res ",res);
- //下面是检验整理之后的牌和原来的牌有没有发生变化
- let zlzh = [];//整理之后的牌
- for (var i = 0; i < res.length; i++) {
- zlzh = zlzh.concat(res[i].reverse());
- }
- zlzh = _.sortBy(zlzh);///降序排序
- let lygdys = _.difference(zlzh,CardsCopy);////另一个队员的人数
- let lygdys2 = _.difference(CardsCopy,zlzh);////另一个队员的人数
- if(lygdys.length > 0 || lygdys2.length > 0 || zlzh.length != CardsCopy.length){
- console.error("111==============================这把派出错了 =======",JSON.stringify(zlzh));
- console.error("222==============================这把派出错了 =======",JSON.stringify(CardsCopy));
- return [];
- }
- return res;
- };
- //整理手牌(旧的,先去掉坎和刻,再去掉大顺(壹贰叁,贰柒拾)和小顺(一二三,二七十),然后将剩下的手牌分成单牌和成对的牌,然后在单牌里面去掉顺子,剩余的单牌在和成对牌组成绞牌并去掉,然后去掉不能成绞牌的对子,最终剩余的单牌称为杂牌并3张一组放在最后。)
- proto.groupCardsOld = function (_Cards) {
- // console.warn("整理手牌 ",JSON.stringify(_Cards));
- let Cards = _.cloneDeep(_Cards);
- let CardsCopy = _.cloneDeep(_Cards);
- // console.error("判断桌子是否存在 ");
- // let Cards = [101,102,102,102,103,106,106,106,107,108,201,202,202,203,203,205,205,206,206,207,208]
- // let CardsCopy = [101,102,102,102,103,106,106,106,107,108,201,202,202,203,203,205,205,206,206,207,208]
- // // // let group1 = _.groupBy(Cards, function (n) { return n % 100 })
- // // //// group1 = {"1":[101,201],"2":[102,102,102,202,202],"3":[103,203,203],"5":[205,205],"6":[106,106,106,206,206],"7":[107,207],"8":[108,208]}
- // // // let map1 = _.map(Object.keys(group1), function (n) { return Number(n) });
- // // //// map1 = [1,2,3,5,6,7,8]
- // let group2 = _.groupBy(Cards, function (n) { return n})
- // console.error("group2 = ",group2);
- // // // // group2 = {"101":[101],"102":[102,102,102],"103":[103],"106":[106,106,106],"107":[107],"108":[108],
- // // // // "201":[201],"202":[202,202],"203":[203,203],"205":[205,205],"206":[206,206],"207":[207],"208":[208]}
- // // let map2 = _.map(Object.keys(group2), function (n) { return Number(n) });
- // // // map2 [101,102,103,106,107,108,201,202,203,205,206,207,208]
- // // console.error("group2 = ",JSON.stringify(group2)," map2 ",JSON.stringify(map2));
- // // let order2 = _.sortBy((group2, function (n) { return n.length})
- // // console.error("group2 = ",group2," order2 ",order2);
- // var values2 = _.values(group2);
- // // values2 = [[101],[102,102,102],[103],[106,106,106],[107],[108],[201],[202,202],[203,203],[205,205],[206,206],[207],[208]]
- // console.error(" values2 ",values2,JSON.stringify(values2));
- // var sortVal = _.sortBy(values2, function (n) { return n.length }).reverse();
- // //sortVal = [[106,106,106],[102,102,102],[206,206],[205,205],[203,203],[202,202],[208],[207],[201],[108],[107],[103],[101]]
- // console.error(" sortVal ",sortVal,JSON.stringify(sortVal));
- let dspzs = [[201,202,203],[202,207,210]];//大顺的牌值列表
- let xspzs = [[101,102,103],[102,107,110]];//小顺的牌值列表
- let res = [];
- let gc = _.groupBy(Cards, function (n) { return n})
- let vc = _.values(gc);
- var sortVal = _.sortBy(vc, function (n) { return n.length }).reverse();
- // console.error(" sortVal ",sortVal);
- // console.error(" Cards111 ",JSON.stringify(Cards));
- let tikeList = [];//手牌中的提刻列表
- let dashunList = [];//手牌中的大顺列表
- let xiaoshunList = [];//手牌中的小顺列表
- let chengshuangList = [];//手牌中的成双列表
- let jiaoList = [];//手牌中的绞牌列表
- let duiziList = [];//手牌中的对子列表
- let danpaiList = [];//手牌中的单牌列表
- for (var i = 0; i < sortVal.length; i++) {
- if(sortVal[i].length >= 3){
- tikeList.push(sortVal[i]);
- let issccg = this.remove(Cards,sortVal[i]);//从手牌中剔除可组成刻提的牌
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("牌出错了111 ",JSON.stringify(Cards));
- return [];
- }
- // console.error(" Cards222 ",JSON.stringify(Cards));
- }
- }
- for (var j = 0; j < dspzs.length; j++) {
- for (var i = 0; i < 2; i++) {//手牌中剔除刻子之后最多2个大顺
- let issccg = this.remove(Cards,dspzs[j]);//从手牌中剔除可组成大顺的牌
- // if(issccg) console.error(" Cards222 ",JSON.stringify(Cards));
- if(issccg) dashunList.push(dspzs[j])
- else break;
- }
- }
- for (var j = 0; j < xspzs.length; j++) {
- for (var i = 0; i < 2; i++) {//手牌中剔除刻子之后最多2个小顺
- let issccg = this.remove(Cards,xspzs[j]);//从手牌中剔除可组成小顺的牌
- // if(issccg) console.error(" Cards333 ",JSON.stringify(Cards));
- if(issccg) xiaoshunList.push(xspzs[j])
- else break;
- }
- }
- let gc2 = _.groupBy(Cards, function (n) { return n})
- let vc2 = _.values(gc2);
- for (var i = 0; i < vc2.length; i++) {
- if(vc2[i].length == 1) danpaiList = danpaiList.concat(vc2[i]);
- else if(vc2[i].length == 2) chengshuangList.push(vc2[i]);
- else {
- console.error("牌出错了222 ",JSON.stringify(CardsCopy));
- return [];
- }
- }
- //下面是在单牌中提取普通顺子和能和对子组成绞牌的牌
- let dpszList = [];//手牌中的单牌可组成的顺子列表
- let dphdzkzjpList = [];//手牌中的单牌和对子可组成的绞牌列表
- // console.warn("整理手牌 最开始的单牌 danpaiList ",JSON.stringify(danpaiList));
- for (var i = 0; i < danpaiList.length-2; i++) {
- if(danpaiList[i]+1 == danpaiList[i+1] && danpaiList[i]+2 == danpaiList[i+2]){
- dpszList.push([danpaiList[i],danpaiList[i+1],danpaiList[i+2]])
- i+=2;
- }
- }
- // console.warn("整理手牌 单牌可组顺子 dpszList ",JSON.stringify(dpszList));
- for (var i = 0; i < dpszList.length; i++) {
- let needRemoves = dpszList[i];
- let issccg = this.remove(danpaiList, needRemoves);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了444 ",JSON.stringify(danpaiList),needRemoves);
- return [];
- }
- }
- // console.warn("整理手牌 剔除可组顺子的单牌 danpaiList ",JSON.stringify(danpaiList));
- for (var j = 0; j < chengshuangList.length; j++) {
- let sfcj = false;//是否可以成绞
- for (var i = 0; i < danpaiList.length; i++) {
- if(this.getValue(danpaiList[i]) == this.getValue(chengshuangList[j][0])){
- dphdzkzjpList.push(danpaiList[i])
- jiaoList.push([danpaiList[i],chengshuangList[j][0],chengshuangList[j][1]]);
- sfcj = true;
- break;
- }
- }
- if(!sfcj) duiziList.push(chengshuangList[j])
- }
- // console.warn("整理手牌 dphdzkzjpList ",JSON.stringify(dphdzkzjpList));
- if(dphdzkzjpList.length > 0){
- let issccg = this.remove(danpaiList, dphdzkzjpList);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了555 ",JSON.stringify(danpaiList),dphdzkzjpList);
- return [];
- }
- }
- // console.warn("整理手牌 最hou的单牌 danpaiList ",JSON.stringify(danpaiList));
-
- danpaiList = _.chunk(danpaiList, 3);
- // console.warn("手牌中的提刻列表 ",tikeList);//
- // console.warn("手牌中的大顺列表 ",dashunList);//
- // console.warn("手牌中的小顺列表 ",xiaoshunList);//
- // console.warn("手牌中的普通顺子列表 ",dpszList);//
- // console.warn("手牌中的绞牌列表 ",jiaoList);//
- // console.warn("手牌中的对子列表 ",duiziList);//
- // console.warn("手牌中的单牌列表 ",danpaiList);//
- res = res.concat(tikeList);//
- res = res.concat(dashunList);//
- res = res.concat(xiaoshunList);//
- res = res.concat(dpszList);//
- res = res.concat(jiaoList);//
- res = res.concat(duiziList);//
- res = res.concat(danpaiList);//
- // console.warn("整理之后的牌 res ",res);
- //下面是检验整理之后的牌和原来的牌有没有发生变化
- let zlzh = [];//整理之后的牌
- for (var i = 0; i < res.length; i++) {
- zlzh = zlzh.concat(res[i].reverse());
- }
- zlzh = _.sortBy(zlzh);///降序排序
- let lygdys = _.difference(zlzh,CardsCopy);////另一个队员的人数
- let lygdys2 = _.difference(CardsCopy,zlzh);////另一个队员的人数
- if(lygdys.length > 0 || lygdys2.length > 0 || zlzh.length != CardsCopy.length){
- console.error("111==============================这把派出错了 =======",JSON.stringify(zlzh));
- console.error("222==============================这把派出错了 =======",JSON.stringify(CardsCopy));
- return [];
- }
- return res;
- };
- //得到一组手牌的块类型 (_cards是数组,元素也是数组)
- proto.getCardStyle = function (_cards) {
- // console.warn("得到一组手牌的块类型 ",JSON.stringify(_cards));
- let res = [];
- for (var i = 0; i < _cards.length; i++) {
- let lie = _.cloneDeep(_cards[i]);//第i列的牌
- lie = this.sort(lie);
- // console.warn("这列牌 ",lie);
- let style = -1;
- let zlpzs = lie.length;//这列牌张数
- let zlqczh = _.uniq(lie);//这列牌去重之后
- let zlqchzs = zlqczh.length;//这列牌去重之后的张数
- // console.warn("得到一组手牌的块类型2222 ","zlpzs",zlpzs,"zlqchzs",zlqchzs);
- if(zlpzs == 4){
- // console.warn("得到一组手牌的块类型 getCardStyle 调用anGangAnalyze ");
- let res = this.anGangAnalyze(lie);
- if(res.length > 0) style = STYLE.ANGANG;
- else style = STYLE.NULL;
- }
- else if(zlpzs == 3){
- if(zlqchzs == 1) style = STYLE.KE;
- else if(zlqchzs == 2) {
- if(this.getValue(lie[0]) == this.getValue(lie[1]) && this.getValue(lie[0]) == this.getValue(lie[2])) style = STYLE.JIAO;
- else style = STYLE.NULL;
- }
- else if(zlqchzs == 3) {
- let ress = this.shunAnalyze(lie, lie[0]);
- if(ress.length > 0) {
- if(ress[0].type <= 4) style = STYLE.SUN;
- else if(ress[0].type >= 5 && ress[0].type <= 6) style = STYLE.JIAO;
- else style = STYLE.NULL;
- }
- else style = STYLE.NULL;
- }
- }
- else if(zlpzs < 3){
- style = STYLE.NULL;
- }
- if(style < 0) console.error("这里判断手牌的块出错了");
- res[i] = style;
- }
- return res;
- };
- //得到一组手牌的胡息类型(_cards是数组,元素也是数组)
- proto.getCardHXType = function (_cards,_styles) {
- let res = [];
- if(_cards.length != _styles.length){
- console.error("这里判断手牌的块出错了");
- return res;
- }
- for (var i = 0; i < _cards.length; i++) {
- let lie = _.cloneDeep(_cards[i]);//第i列的牌
- lie = this.sort(lie);
- let dyzhs = this.getType(lie[0]);//第一张花色
- let dyzpz = this.getValue(lie[0]);//第一张牌值
- let hxlx = -1;//胡息类型
- if(_styles[i] < 0) hxlx = HUXITYPE.NULL;
- else if(_styles[i] == STYLE.SUN) {
- let dezpz = this.getValue(lie[1]);//第二张牌值
- // console.warn("得到一组手牌的胡息类型,",lie,_styles[i]);
- if(dyzhs == this.xiaoType && (dyzpz == 1 || (dyzpz == 2 && dezpz == 7))) hxlx = HUXITYPE.XIAOSHUN;
- else if(dyzhs == this.daType && (dyzpz == 1 || (dyzpz == 2 && dezpz == 7))) hxlx = HUXITYPE.DASHUN;
- else hxlx = HUXITYPE.NULL;
- }
- else if(_styles[i] == STYLE.KE) {
- if(dyzhs == this.xiaoType) hxlx = HUXITYPE.XIAOKE;
- else if(dyzhs == this.daType) hxlx = HUXITYPE.DAKE;
- else hxlx = HUXITYPE.NULL;
- }
- else if(_styles[i] == STYLE.PENG) {
- if(dyzhs == this.xiaoType) hxlx = HUXITYPE.XIAOPENG;
- else if(dyzhs == this.daType) hxlx = HUXITYPE.DAPENG;
- else hxlx = HUXITYPE.NULL;
- }
- else if(_styles[i] == STYLE.WEI) {
- if(dyzhs == this.xiaoType) hxlx = HUXITYPE.XIAOWEI;
- else if(dyzhs == this.daType) hxlx = HUXITYPE.DAWEI;
- else hxlx = HUXITYPE.NULL;
- }
- else if(_styles[i] == STYLE.GANG || _styles[i] == STYLE.ZMGANG) {
- if(dyzhs == this.xiaoType) hxlx = HUXITYPE.XIAOPAO;
- else if(dyzhs == this.daType) hxlx = HUXITYPE.DAPAO;
- else hxlx = HUXITYPE.NULL;
- }
- else if(_styles[i] == STYLE.ANGANG) {
- if(dyzhs == this.xiaoType) hxlx = HUXITYPE.XIAOTI;
- else if(dyzhs == this.daType) hxlx = HUXITYPE.DATI;
- else hxlx = HUXITYPE.NULL;
- }
- else hxlx = HUXITYPE.NULL;
- res[i] = hxlx;
- }
- return res;
- };
- //得到一组手牌的胡息息数(参数是手牌的胡息类型数组)
- proto.getCardHXValue = function (_hxtypes) {
- let res = [];
- for (var i = 0; i < _hxtypes.length; i++) {
- res[i] = HUXIVALUE[_hxtypes[i]];
- }
- return res;
- };
- // 是否无牌
- proto.isNoCards = function () {
- return this.lastCount <= 0;
- };
- // 摸牌函数
- proto.moCard = function () {
- 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.isPeng = function (_handCards, card) {
- let handCards = this.arr2ToArr1(_handCards,true);
- if(this.getACardCount(handCards,card) >= 3) 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], card: card };
- }
- };
- // 得到吃牌需要删除的所有牌
- proto.getChiAllNeedRemoves = function (card, type, cdpsszs, bi1Type, bi2Type) {
- let res = [];
- res = this.getChiOtherCards(card, type);
- if (cdpsszs == 1) {
- res = res.concat(this.getChiResCards(card, bi1Type));
- }
- if (cdpsszs == 2) {
- res = res.concat(this.getChiResCards(card, bi1Type));
- res = res.concat(this.getChiResCards(card, bi2Type));
- }
- // console.warn("得到吃牌需要删除的所有牌",res);
- return res;
- };
- //通过吃的牌和吃的类型得到需要删除的牌
- proto.getChiOtherCards = function (card, type) {
- let res = [];
- let ctype = this.getType(card);
- let value = this.getValue(card);
- if (type == 1) {
- res = [card + 1, card + 2];
- } else if (type == 2) {
- res = [card - 1, card + 1];
- } else if (type == 3){
- res = [card - 2, card - 1];
- } else if (type == 4) {//二七十顺
- if(ctype == 1) {
- if(value == 2) res = [107,110];
- else if(value == 7) res = [102,110];
- else if(value == 10) res = [102,107];
- }
- else if(ctype == 2) {
- if(value == 2) res = [207,210];
- else if(value == 7) res = [202,210];
- else if(value == 10) res = [202,207];
- }
- } else if (type == 5) {//绞情况1
- if(ctype == 1) res = [card+100,card+100];
- else if(ctype == 2) res = [card-100,card-100];
- } else if (type == 6) {//绞情况2
- if(ctype == 1) res = [card,card+100];
- else if(ctype == 2) res = [card,card-100];
- }
- return res;
- }
- // 吃牌,1-@**左吃, 2-*@*中吃, 3-@**右吃
- proto.getChiResCards = function (card, type) {
- let res = [];
- let ctype = this.getType(card);
- let value = this.getValue(card);
- if (type == 1) {
- res = [card, card + 1, card + 2];
- } else if (type == 2) {
- res = [card - 1, card, card + 1];
- } else if (type == 3){
- res = [card - 2, card - 1, card];
- } else if (type == 4) {//二七十顺
- if(ctype == 1) res = [102,107,110];
- else if(ctype == 2) res = [202,207,210];
- } else if (type == 5) {//绞情况1
- if(ctype == 1) res = [card,card+100,card+100];
- else if(ctype == 2) res = [card,card-100,card-100];
- } else if (type == 6) {//绞情况2
- if(ctype == 1) res = [card,card,card+100];
- else if(ctype == 2) res = [card,card,card-100];
- }
- return res;
- };
- // 吃牌,1-@**左吃, 2-*@*中吃, 3-@**右吃
- proto.chi = function (_handCards, card, type, cdpsszs, bi1Type, bi2Type, outerId, chairId) {
- // console.warn("roto.chi = funct card, type, cdpsszs, bi1Type, bi2Type, outerId, chairId ",card, type, cdpsszs, bi1Type, bi2Type, outerId, chairId);
- let res = [];
- let needRemoves = this.getChiAllNeedRemoves(card,type, cdpsszs, bi1Type, bi2Type);
- let handCards = this.arr2ToArr1(_handCards,false);
- var length = needRemoves.length;
- // console.warn("roto.chi = funct 1111 ",handCards,needRemoves)
- for (let i = 0; i < length; ++i) {
- let pos = handCards.indexOf(needRemoves[i]);
- // console.warn("roto.chi = funct 2222 ",pos,needRemoves[i])
- if (pos == -1) return res;
- }
- for (let i = 0; i < length; ++i) {
- let pos = handCards.indexOf(needRemoves[i]);
- // console.warn("roto.chi = funct 3333 ",pos,needRemoves[i])
- if (pos == -1) return res;
- handCards.splice(pos, 1);
- }
- let resItem = { style: STYLE.CHI, type: type, card: card, origin:outerId};
- resItem.cards = this.getChiResCards(card, type);
- res[res.length] = resItem;
- if (cdpsszs == 1 && type != 6) {
- let bi1Item = { style: STYLE.CHI, type: bi1Type, card: card, origin:chairId};
- bi1Item.cards = this.getChiResCards(card, bi1Type);
- res[res.length] = bi1Item;
- }
- if (cdpsszs == 2) {
- let bi1Item = { style: STYLE.CHI, type: bi1Type, card: card, origin:chairId};
- bi1Item.cards = this.getChiResCards(card, bi1Type);
- // console.warn("roto.chi = funct ????? ",bi1Item)
- res[res.length] = bi1Item;
- if(bi2Type > 0){
- let resItem2 = { style: STYLE.CHI, type: bi2Type, card: card, origin:chairId};
- resItem2.cards = this.getChiResCards(card, bi2Type);
- res[res.length] = resItem2;
- }
- }
- // console.warn("roto.chi = funct res ",res,resItem)
- return res;
- };
- // 杠牌,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风
- proto.gang = function (chirID,_handCards, huCards, card, type) {
- let handCards = this.arr2ToArr1(_handCards,true);
- // 结果
- var res = null;
- // 明杠
- if (type == 1) {
- let gang = this.gangAnalyze(handCards, card);
- if (gang) {
- res = { style: STYLE.GANG, card: card, cards: [card, card, card, card] };
- }
- }
- // 暗杠
- else if (type == 2) {
- handCards.push(card);
- let anGang = this.anGangAnalyze(handCards, card);
- if (anGang[0]) {
- res = { style: STYLE.ANGANG, card: card, cards: [card, card, card, card] };
- }
- }
- else if ((type == 4 || type == 5) && card) {
- let angang = this.zmGangAnalyze2(handCards, huCards, card);
- if (angang[0]) {
- res = { style: STYLE.ANGANG, card: card, cards: [card, card, card, card] };
- }
- }
- return res;
- };
- // 杠牌2仅在发牌时候调用,因为发牌时可能有多个提,应该返回个数组,1-普通杠, 2-暗杠, 3-自摸明杠
- proto.gang2 = function (chirID,_handCards, huCards, card, type) {
- let handCards = this.arr2ToArr1(_handCards,true);
- // 结果
- var res = [];
- // 明杠
- if (type == 1) {
- let gang = this.gangAnalyze(handCards, card);
- if (gang) {
- res.push({ style: STYLE.GANG, card: card, cards: [card, card, card, card] });
- }
- }
- // 暗杠
- else if (type == 2) {
- let anGang = this.anGangAnalyze(handCards);
- if (anGang[0]) {
- for (var i = 0; i < anGang.length; i++) {
- res.push({style: STYLE.ANGANG, card: anGang[i].card, cards: [anGang[i].card, anGang[i].card, anGang[i].card, anGang[i].card] });
- }
- }
- }
- else if ((type == 4 || type == 5) && card) {
- let angang2 = this.zmGangAnalyze2(handCards, huCards, card);
- if (angang2[0]) {
- res.push({ style: STYLE.ANGANG, card: card, cards: [card, card, card, card] });
- }
- }
- return res;
- };
- // 自摸明杠,1-普通杠, 2-暗杠, 3-自摸明杠 TL++参数chirID为了判断圈风和位风
- proto.zmGang = function (chirID,_handCards, huCards, card) {
- let handCards = this.arr2ToArr1(_handCards,true);
- var zmGang = this.zmGangAnalyze(handCards, huCards, card);
- if (zmGang[0]) {
- return { style: STYLE.ZMGANG, cards: [card, card, card, card] };
- }
- else{
- zmGang = this.zmGangAnalyze2(handCards, huCards, card);
- if (zmGang[0]) {
- return { style: STYLE.ZMGANG, cards: [card, card, card, card] };
- }
- }
- };
- //检查吃牌的数据是否合法
- proto.checkChiData = function (type,cdpsszs,bi1Type,bi2Type) {
- if(cdpsszs == 0) {
- return true;
- }
- else if(cdpsszs == 1 ){
- if(type == 6){
- return true;
- }
- else{
- if(bi1Type >= 1 && bi1Type <= 6) return true;
- }
- }
- else if(cdpsszs == 2){
- if(type == 6){
- if(bi1Type >= 1 && bi1Type <= 6) return true;
- }
- else{
- if(bi1Type == 6){
- return true;
- }
- else{
- if(bi1Type >= 1 && bi1Type <= 6 && bi2Type >= 1 && bi2Type <= 6) return true;
- }
- }
- }
- return false;
- }
- //删除数组中重复出现3次以上的元素
- proto.sccx3cysdys = function (_Cards) {
- let Cards = _.cloneDeep(_Cards);
- let gc = _.groupBy(Cards, function (n) { return n})
- let vc = _.values(gc);
- var sortVal = _.sortBy(vc, function (n) { return n.length }).reverse();
- for (var i = 0; i < sortVal.length; i++) {
- if(sortVal[i].length >= 3){
- let issccg = this.remove(Cards,sortVal[i]);//从手牌中剔除可组成刻提的牌
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了 ",JSON.stringify(Cards));
- return [];
- }
- // console.error(" Cards222 ",JSON.stringify(Cards));
- }
- }
- return Cards;
- }
- proto.getACardCount = function (array, element) {
- let cout = array.filter(e => e === element).length;
- // console.warn("得到出现的次数 ",cout, element,JSON.stringify(array));
- return cout;
- }
- // 吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传
- proto.chiAnalyze = function (_handCards, card, type) {
- // console.warn("吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传111 ",_handCards, card, type);
- let handCards = this.arr2ToArr1(_handCards,true);
- handCards = this.sccx3cysdys(handCards);
- // console.warn("吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传222 ",JSON.stringify(handCards), card, type);
- // 结果集合
- var result = [];
- // 排除手牌不够情况
- if (handCards.length <= 2) return result;
- if(this.getACardCount(handCards,card) >= 3) return result;
- // 牌面值
- let value = this.getValue(card);
- // 查找句子
- var length = handCards.length;
- for (let i = 0; i < length; ++i) {
- // @**左吃,吃类型(可以不指定)
- if (!type || type == 1) {
- if (value < 9 && 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 < 10 && 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 });
- }
- }
- }
- }
- let ctype = this.getType(card);
- //上面是吃普通顺子,下面是吃2,7,10顺子
- if (!type || type == 4) {
- let pos = [2,7,10].indexOf(value);
- if (pos != -1) {
- // let eqsszpzs = [,];//二七十顺的牌值列表
- let needList = [];//想吃手牌需要存在的牌
- if(ctype == 1) needList = [102,107,110];
- else if(ctype == 2) needList = [202,207,210];
- needList.splice(pos, 1);
- if (handCards.indexOf(needList[0]) != -1 && handCards.indexOf(needList[1]) != -1) {
- result.push({ type: 4, card: card });
- }
- }
- }
- //下面是吃绞牌
- let pzhsxtzs = 0;//自己手牌中与要吃的那张牌的牌值相同花色相同的张数
- let pzxthsbtzs = 0;//自己手牌中与要吃的那张牌的牌值相同花色不同的张数
- for (let i = 0; i < length; ++i) {
- if(this.getValue(handCards[i]) == value){
- if(this.getType(handCards[i]) == ctype) pzhsxtzs++;
- else pzxthsbtzs++;
- }
- }
- // console.warn("下面是吃绞牌 "," pzhsxtzs ",pzhsxtzs," pzxthsbtzs ",pzxthsbtzs);
- if (!type || type == 5) {//自己两牌花色和吃的那张牌的花色相同数量为0
- if(pzxthsbtzs == 2){
- result.push({ type: 5, card: card });
- }
- }
- if (!type || type == 6) {//自己两牌花色和吃的那张牌的花色相同数量为1
- if(pzhsxtzs >= 1 && pzxthsbtzs >= 1 && pzhsxtzs <= 2 && pzxthsbtzs <= 2){
- result.push({ type: 6, card: card });
- }
- }
- // console.warn("chiAnalyze result ",result);
- return result;
- };
- //得到吃牌时吃比数据
- proto.getChiBiArr = function (_handCards, card) {
- let chiBiArr = {cdpsszs:-1,chi:[],bi1:[],bi2:[]}; //吃牌时吃比数据
- //chi是{}类型的数组,bi1是[{},{}...]类型的数组,bi2是[[{},{}...],[{},{}...]...]要吃的牌手上只有一张时彼bi2为空数组
- let handCards = this.arr2ToArr1(_handCards,true);
- handCards = this.sccx3cysdys(handCards);
- // 排除手牌不够情况
- if (handCards.length <= 2) return chiBiArr;
- // console.warn("得到吃牌时吃比数据 ks",JSON.stringify(_handCards), card,JSON.stringify(handCards));
- let cdpsszs = this.getACardCount(handCards,card);//要吃的牌手上张数
- chiBiArr.cdpsszs = cdpsszs;
- if(cdpsszs >= 3) return chiBiArr;
- let chiArr = this.chiAnalyze(_handCards, card);
- // console.warn("得到吃牌时吃比数据 chiArr ",cdpsszs,chiArr);
- if(cdpsszs == 0) {
- for (var i = 0; i < chiArr.length; i++) {
- let chiItem = chiArr[i];
- chiBiArr.chi.push(chiItem);
- }
- return chiBiArr;
- }
- else if(cdpsszs == 1){
- for (var i = 0; i < chiArr.length; i++) {
- let chiItem = chiArr[i];
- let copyCards = _.cloneDeep(handCards);
- // console.warn("得到吃牌时吃比数据 删除之前的 copyCards ",JSON.stringify(copyCards));
- let needRemoves = this.getChiOtherCards(chiItem.card,chiItem.type);
- let issccg = this.remove(copyCards, needRemoves);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了111 ",JSON.stringify(copyCards));
- return chiBiArr;
- }
- // console.warn("得到吃牌时吃比数据 删除之后的 copyCards ",JSON.stringify(copyCards)," needRemoves ",needRemoves);
- if(chiItem.type == 6){
- //这种绞牌的吃牌会消耗掉手上那张要吃的牌,所以这种类型的就不用比了
- chiBiArr.chi.push(chiItem);
- chiBiArr.bi1.push([]);
- }
- else{
- let bi1 = [];
- if(copyCards.indexOf(card) != -1){
- this.remove(copyCards, [card]);//删除手牌结果//把下面判断bi1需要消耗的手牌card先删掉,这样才能正确的判断出bi1
- bi1 = this.chiAnalyze(copyCards, card);
- }
- let bi1Item = [];
- for (var j = 0; j < bi1.length; j++) {
- bi1Item.push(bi1[j])
- }
- // console.warn("得到吃牌时吃比数据 bi1 ",bi1Item,bi1);
- if(bi1Item.length > 0){
- chiBiArr.chi.push(chiItem);
- chiBiArr.bi1.push(bi1Item);
- }
- }
- }
- }
- else if(cdpsszs == 2){
- for (var i = 0; i < chiArr.length; i++) {
- // if(i == 2) break;
- let zzcfsfky = false;//这种吃法是否可以
- let chiItem = chiArr[i];
- let copyCards = _.cloneDeep(handCards);
- // console.warn("得到吃牌时吃比数据 删除之前的222 copyCards ",i,JSON.stringify(copyCards));
- let needRemoves = this.getChiOtherCards(chiItem.card,chiItem.type);
- //getChiOtherCards返回值是2个,适合得到吃牌需要删除的牌,getChiResCards适合得到比牌需要删除的牌,这里是删除上面吃牌消耗掉的2张手牌
- //采用getChiResCards的目的是替下面的比牌判断先删掉一张card(相当于正常吃时候别人打下来的那张牌)
- // let needRemoves = this.getChiResCards(chiItem.card,chiItem.type);
- let issccg = this.remove(copyCards, needRemoves);//删除手牌结果
- if(!issccg){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了222 ",JSON.stringify(copyCards));
- return chiBiArr;
- }
- if(copyCards.indexOf(card) != -1){
- this.remove(copyCards, [card]);//删除手牌结果//把下面判断bi1需要消耗的手牌card先删掉,这样才能正确的判断出bi1
- }
- // console.warn("得到吃牌时吃比数据 删除之后的222 copyCards ",i,JSON.stringify(copyCards)," needRemoves ",needRemoves);
- let bi1 = this.chiAnalyze(copyCards, card);
- // console.warn("得到吃牌时吃比数据 222 bi1 ",JSON.stringify(bi1));
- // let bi1Item = [];
- for (var j = 0; j < bi1.length; j++) {
- if(chiItem.type == 6 && bi1[j].type == 6) continue;
- let ccd = chiBiArr.chi.length;//吃数组长度
- // console.warn("?????????????????????? ",ccd,bi1.length);
- let b1cd = chiBiArr.bi1.length;//比1数组长度
- let b2cd = chiBiArr.bi2.length;//比2数组长度
- // console.warn("各长度111=== ",i,j,ccd,b1cd,b2cd,JSON.stringify(chiBiArr));
- if(chiItem.type == 6){
- zzcfsfky = true;
- // chiBiArr.bi1[ccd]=bi1;
- if(!chiBiArr.bi1[ccd]) chiBiArr.bi1[ccd]=[];
- chiBiArr.bi1[ccd].push(bi1[j]);
- if(!chiBiArr.bi2[ccd]) chiBiArr.bi2[ccd]=[];
- chiBiArr.bi2[ccd].push([]);
- }
- else{
- let zzbfsfky = false;//这种比法是否可以
- let needRemoves2 = this.getChiOtherCards(bi1[j].card,bi1[j].type);
- let copyCards2 = _.cloneDeep(copyCards);
- // console.warn("得到吃牌时吃比数据 删除之前的333 copyCards2 ",JSON.stringify(copyCards2));
- let issccg2 = this.remove(copyCards2, needRemoves2);//删除手牌结果
- if(!issccg2){//是否删除成功,不成功说明手牌中没有,据此可知代码出错了
- console.error("删除出错了333 ",JSON.stringify(copyCards)," needRemoves ",needRemoves2);
- return chiBiArr;
- }
- // console.warn("得到吃牌时吃比数据 删除之后的333 copyCards2 ",JSON.stringify(copyCards2)," needRemoves ",needRemoves2);
- // let bi2 = this.chiAnalyze(copyCards2, card);
- let bi2 = [];
- let bi2sfbxy = false;//bi2是否必须有
- if(copyCards2.indexOf(card) != -1){
- bi2sfbxy = true;
- this.remove(copyCards2, [card]);//删除手牌结果//把下面判断bi2需要消耗的手牌card先删掉,这样才能正确的判断出bi2
- bi2 = this.chiAnalyze(copyCards2, card);
- }
- // console.warn("==========================================111 ",i,j,bi2sfbxy,chiArr[i].type,bi1[j].type);
- if(!bi2sfbxy){
- let xhgs = 0;//消耗个数
- if(chiArr[i].type == 6) xhgs += 2;//这种类型消耗2张
- else xhgs += 1;//这种类型消耗1张
- if(bi1[j].type == 6) xhgs += 2;//这种类型消耗2张
- else xhgs += 1;//这种类型消耗1张
- if(xhgs < cdpsszs + 1) bi2sfbxy = true;//前面的吃比没有消耗完card,所以必须要有比2不然这种吃法就不行
- // console.warn("==========================================222 ",xhgs,chiArr[i].type,bi1[j].type);
- }
- // console.warn("得到吃牌时吃比数据 333 bi2 ",JSON.stringify(copyCards2),JSON.stringify(bi2));
- if(bi2.length > 0){
- zzcfsfky = true;
- // chiBiArr.bi1[ccd]=bi1;
- if(!chiBiArr.bi1[ccd]) chiBiArr.bi1[ccd]=[];
- chiBiArr.bi1[ccd].push(bi1[j]);
- if(!chiBiArr.bi2[ccd]) chiBiArr.bi2[ccd]=[];
- chiBiArr.bi2[ccd].push(bi2);
- // console.warn("各长度222=== ",i,j,ccd,b1cd,b2cd,JSON.stringify(chiBiArr));
- }
- else{
- // console.warn("得到吃牌时吃比数据 444 bi2 ",bi2sfbxy,JSON.stringify(copyCards2),JSON.stringify(bi2));
- if(!bi2sfbxy){
- zzcfsfky = true;
- // chiBiArr.bi1[ccd]=bi1;
- if(!chiBiArr.bi1[ccd]) chiBiArr.bi1[ccd]=[];
- chiBiArr.bi1[ccd].push(bi1[j]);
- if(!chiBiArr.bi2[ccd]) chiBiArr.bi2[ccd]=[];
- chiBiArr.bi2[ccd].push([]);
- }
- else {
- //至此是比2必须有且bi2.length = 0 则此种比法不行
- // if()
- // bi1[j] = null;
- }
- // console.warn("得到吃牌时吃比数据 555 bi2 ",bi2sfbxy,zzcfsfky)
- }
- }
- }
- if(zzcfsfky){
- chiBiArr.chi.push(chiItem);
- }
- }
- }
- // console.warn("吃比数据分析 ",JSON.stringify(chiBiArr));
- return chiBiArr;
- }
- // 顺子分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传
- proto.shunAnalyze = function (handCards, card, type) {
- // console.warn("吃牌分析,1-@**左吃, 2-*@*中吃, 3-@**右吃, type可以不传 ",handCards, card, type);
- // 结果集合
- var result = [];
- // 排除手牌不够情况
- if (handCards.length < 2) return result;
- // 牌面值
- let value = this.getValue(card);
- // 查找句子
- var length = handCards.length;
- for (let i = 0; i < length; ++i) {
- // @**左吃,吃类型(可以不指定)
- if (!type || type == 1) {
- if (value < 9 && 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 < 10 && 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 });
- }
- }
- }
- }
- let ctype = this.getType(card);
- //上面是吃普通顺子,下面是吃2,7,10顺子
- if (!type || type == 4) {
- let pos = [2,7,10].indexOf(value);
- if (pos != -1) {
- // let eqsszpzs = [,];//二七十顺的牌值列表
- let needList = [];//想吃手牌需要存在的牌
- if(ctype == 1) needList = [102,107,110];
- else if(ctype == 2) needList = [202,207,210];
- needList.splice(pos, 1);
- if (handCards.indexOf(needList[0]) != -1 && handCards.indexOf(needList[1]) != -1) {
- result.push({ type: 4, card: card });
- }
- }
- }
- //下面是吃绞牌
- let pzhsxtzs = 0;//自己手牌中与要吃的那张牌的牌值相同花色相同的张数
- let pzxthsbtzs = 0;//自己手牌中与要吃的那张牌的牌值相同花色不同的张数
- for (let i = 0; i < length; ++i) {
- if(this.getValue(handCards[i]) == value){
- if(this.getType(handCards[i]) == ctype) pzhsxtzs++;
- else pzxthsbtzs++;
- }
- }
- if (!type || type == 5) {//自己两牌花色和吃的那张牌的花色相同数量为0
- if(pzxthsbtzs == 2){
- result.push({ type: 5, card: card });
- }
- }
- if (!type || type == 6) {//自己两牌花色和吃的那张牌的花色相同数量为1
- if(pzhsxtzs >= 1 && pzxthsbtzs >= 1 && pzhsxtzs <= 2 && pzxthsbtzs <= 2){
- result.push({ type: 6, card: card });
- }
- }
- // console.warn("shunAnalyze result ",result);
- return result;
- };
- // 判断摸牌者能否偎牌
- proto.weiAnalyze = function (_handCards, card, zzpsfgd) {
- let handCards = this.arr2ToArr1(_handCards,false);
- //if(this.lastCount <= 0) return null;//红中不能碰杠
- let count = 0;
- for (var i = 0; i < handCards.length; i++) {
- if(handCards[i] == card) count++;
- }
- // console.warn("判断摸牌者能否偎牌 ",card,count,JSON.stringify(handCards));
- if(count == 2) {
- let type = 1;//偎牌
- if(zzpsfgd) type = 2;//臭偎 忍碰之后的偎牌称为“臭偎”
- return { style: STYLE.WEI,type:type,card: card, cards: [card, card, card] };
- }
- return null;
- }
- // 普通杠分析,1-普通杠, 2-暗杠, 3-自摸明杠
- proto.gangAnalyze = function (_handCards, card) {
- let handCards = this.arr2ToArr1(_handCards,true);
- // console.warn("普通杠分析,1 ",card,handCards,JSON.stringify(_handCards));
- // 结果对象
- var result = null;
- 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) {
- // console.warn("暗杠分析,1 ",card,JSON.stringify(handCards));
- // 结果对象
- 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]) {
- result.push({ type: 2, card: handCards[i] });
- }
- // 刚摸到杠牌
- else if (handCards[i] == moCard) {
- result.push({ type: 2, card: moCard });
- }
- }
- }
- // console.warn("暗杠分析,5================ ",result)
- return result;
- };
- // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
- proto.zmGangAnalyze = function (handCards, huCards, card) {
- // 返回结果
- var result = [];
- // if(this.lastCount <= 0) return result;//红中不能碰杠
- // 遍历句子
- for (let i = 0; i < huCards.length; ++i) {
- if (huCards[i].style != STYLE.PENG) {
- continue;
- }
- let _card = huCards[i].card;
- if (card && _card != card) continue;
- let pos = handCards.indexOf(_card);
- if (pos != -1) {
- result.push({ type: 3, card: _card });
- if (card) break;
- }
- }
- return result;
- };
- // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
- proto.zmGangAnalyze1 = function (_handCards, huCards, card) {
- let handCards = _.cloneDeep(_handCards)
- if(card) handCards.push(card);
- // 返回结果
- var result = [];
- // 遍历句子
- for (let i = 0; i < huCards.length; ++i) {
- if (huCards[i].style != STYLE.WEI) {
- continue;
- }
- let _card = huCards[i].card;
- if (card && _card != card) continue;
- let pos = handCards.indexOf(_card);
- if (pos != -1) {
- result.push({ type: 5, card: _card });
- if (card) break;
- }
- }
- return result;
- };
- // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
- proto.zmGangAnalyze2 = function (_handCards, huCards, card) {
- let handCards = _.cloneDeep(_handCards)
- if(card) handCards.push(card);
- // 返回结果
- var result = [];
- // 遍历句子
- for (let i = 0; i < huCards.length; ++i) {
- if (huCards[i].style != STYLE.WEI) {
- continue;
- }
- let _card = huCards[i].card;
- if (card && _card != card) continue;
- let pos = handCards.indexOf(_card);
- if (pos != -1) {
- result.push({ type: 2, card: _card });
- if (card) break;
- }
- }
- return result;
- };
- // 自摸杠分析,1-普通杠, 2-暗杠, 3-自摸明杠, card可以不传
- proto.zmGangAnalyze3 = function (_handCards, huCards, card) {
- let handCards = _.cloneDeep(_handCards)
- if(card) handCards.push(card);
- // 返回结果
- var result = [];
- // 遍历句子
- for (let i = 0; i < huCards.length; ++i) {
- if (huCards[i].style != STYLE.WEI) {
- continue;
- }
- let _card = huCards[i].card;
- if (card && _card != card) continue;
- let pos = handCards.indexOf(_card);
- if (pos != -1) {
- result.push({ type: 4, card: _card });
- if (card) break;
- }
- }
- return result;
- };
- // TL++得到某张牌是否合法
- proto.getACardIsHeFa = function (card) {
- if(card >= 101 && card <= 110) return true;
- if(card >= 201 && card <= 210) return true;
- return false;
- };
- // TL++,得到默认手牌中百搭牌当的数组 cards: 手牌去除百搭之后的牌
- proto.getBDMakeList = function (cards) {
- let reslist = [
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, //壹到拾
- ]
- let group1 = _.groupBy(cards, function (n) { return n })
- let res = [];
- for (var i = 0; i < reslist.length; i++) {
- let card = reslist[i];
- let ckey = card.toString();
- if(group1[ckey] && group1[ckey].length == 4){
- continue;
- }
- res.push(card);
- }
- return res;
- // return _.uniq(makeList);
- };
- // 三提五坎分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
- proto.stwkAnalyze = function (chairID,_handCards, card, huCards, isTouch,isAdd) {
- let handCards = this.arr2ToArr1(_handCards,true);
- if(isAdd){
- handCards = handCards.concat(card);/////不是自己抓的就把这张牌拼接进手牌中
- handCards = this.sort(handCards);
- }
- this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡
- // 手牌不全
- var length = handCards.length;
- let cphx = this.getCPHX(huCards);//此人吃碰胡息
- let result = null;
- //下面是判断3提5坎
- let spcards2 = this.groupCards(handCards);
- let spcards = [];
- if(spcards2.length + huCards.length > 7){
- let zhzq = [];//整合之前
- for (var i = 0; i < spcards2.length; i++) {
- if(spcards2[i].length < 3){
- zhzq = zhzq.concat(spcards2[i]);
- }
- else{
- spcards.push(spcards2[i]);
- }
- }
- let zhzqs = _.chunk(zhzq, 3);
- for (var i = 0; i < zhzqs.length; i++) {
- spcards.push(zhzqs[i]);
- }
-
- }
- else{
- spcards = spcards2;
- }
- // console.warn("只有在发牌阶段判断3提5坎呢????222 ",chairID,spcards);
- let styles = this.getCardStyle(spcards);
- let hxTypes = this.getCardHXType(spcards,styles);
- // let gbjg = this.sfxygbhxlx(isTouch,card,spcards,hxTypes);
- // if(gbjg) {
- // //胡息类型在此改变了
- // console.warn("胡息类型在此改变了 ",gbjg);
- // hxTypes[gbjg[0]] = gbjg[1];
- // }
- let hxValues = this.getCardHXValue(hxTypes);
- let sphxs = _.sum(hxValues);//手牌胡息数
- let crzhx = sphxs+cphx;//此人总胡息
- if(this.isSANTIWUKAN(spcards,huCards,[],[])){
- result = {
- zdhx: crzhx,
- card: card,
- cards: spcards,
- hxInfos: {
- styles: styles,
- hxTypes: hxTypes,
- hxValues: hxValues
- }
- }
- }
- // console.warn("胡牌分析返回值2222 ",result);
- return result;
- };
- // 胡牌分析 chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
- proto.huAnalyze = function (chairID,_handCards, card, huCards, isTouch,isAdd) {
- // console.error("sscc777胡牌分析card",card);
- // console.error("sscc777胡牌分析handCards",_handCards);
- // console.error("sscc777胡牌分析huCards",huCards);
- // console.error("sscc777胡牌分析isTouch,card",chairID,isTouch,card);
- let handCards = this.arr2ToArr1(_handCards,true);
- // console.error("sscc777胡牌分析handCards",chairID,JSON.stringify(handCards),_handCards);
- // let tempAllTai = 0/////临时总台数
- // let tempres = {}///本函数的返回值
- this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡
- if(isAdd){
- handCards = handCards.concat(card);/////不是自己抓的就把这张牌拼接进手牌中
- handCards = this.sort(handCards);
- }
- // 手牌不全
- var length = handCards.length;
- if (length % 3 == 1) return;//2个提还未补张,牌数不对无法胡排
- // console.warn("============================================== ",chairID,JSON.stringify(handCards),card);
- let khzh = this.getIsHu(handCards,card);//满足可胡牌型的所有手牌组合
- let cphx = this.getCPHX(huCards);//此人吃碰胡息
- let result = null;
-
- // console.warn("此人吃碰胡息 ",cphx,huCards," khzh ",khzh);
- let mqzdhx = 0;//目前最大胡息
- for (var i = 0; i < khzh.length; i++) {
- if(khzh[i].length + huCards.length < 7) continue;
- let spcards = this.pai2weiTo3Wei(khzh[i]);//把2位数手牌转换为3位数
- let styles = this.getCardStyle(spcards);
- let hxTypes = this.getCardHXType(spcards,styles);
- let gbjg = this.sfxygbhxlx(isTouch,card,spcards,hxTypes);
- if(gbjg) {
- //胡息类型在此改变了
- // console.warn("胡息类型在此改变了2 ",hxTypes[gbjg[0]],gbjg);
- hxTypes[gbjg[0]] = gbjg[1];
- }
- let hxValues = this.getCardHXValue(hxTypes);
- let sphxs = _.sum(hxValues);//手牌胡息数
- let crzhx = sphxs+cphx;//此人总胡息
- // console.warn(" khzh[i] ",JSON.stringify(khzh[i])," spcards ",spcards," styles ",styles," hxTypes ",hxTypes," hxValues ",hxValues);
- if(crzhx >= this.khMinHX){
- if(crzhx > mqzdhx){
- mqzdhx = crzhx;
- result = {
- zdhx: mqzdhx,
- card: card,
- cards: spcards,
- hxInfos: {
- styles: styles,
- hxTypes: hxTypes,
- hxValues: hxValues
- }
- }
- }
- }
- }
- // console.warn("胡牌分析返回值2222 ",result);
- return result;
- };
- // 摸牌时得到摸牌者是否能跑
- proto.getMPZSFNP = function (card, _huCards) {
- // console.error("摸牌时得到摸牌者是否能跑 ",_huCards);
- let huCards = this.deepCloneTL(_huCards);
- let kpIndex = -1;//可跑下标
- for (let i = 0; i < huCards.length; ++i) {
- if(huCards[i].card != card) continue;
- if (huCards[i].style == STYLE.PENG) {
- kpIndex = i;
- break;
- }
- }
- return kpIndex > -1;
- }
- // 摸牌时得到是否能跑
- proto.getMPSSFNP = function (card, _huCards,isTouch) {
- // console.error("摸牌时得到摸牌者是否能跑 ",_huCards);
- let huCards = this.deepCloneTL(_huCards);
- let kpIndex = -1;//可跑下标
- for (let i = 0; i < huCards.length; ++i) {
- if(huCards[i].card != card) continue;
- if (huCards[i].style == STYLE.PENG) {
- kpIndex = i;
- break;
- }
- else if (huCards[i].style == STYLE.WEI) {
- if(!isTouch) {
- kpIndex = i;
- break;
- }
- }
- }
- return kpIndex > -1;
- }
- // 跑胡牌分析 这个是判断那种跑之后是否可胡 和上面的区别是上面是判断跑之前是否可胡
- // chairID(TL++这个参数) 手牌 加上这张判断能不能胡 手上的吃碰杠牌 是否自己摸上来的
- proto.paohuAnalyze = function (chairID,_handCards, card, _huCards, isTouch,isAdd) {
- console.error("sscc777胡牌分析paohuCards",chairID,isTouch,_huCards);
- let huCards = this.deepCloneTL(_huCards);
- let kpIndex = -1;//可跑下标
- for (let i = 0; i < huCards.length; ++i) {
- if(huCards[i].card != card) continue;
- if (huCards[i].style == STYLE.PENG) {
- kpIndex = i;
- break;
- }
- else if (huCards[i].style == STYLE.WEI) {
- if(!isTouch) {
- kpIndex = i;
- break;
- }
- }
- }
- if(kpIndex < 0) return;
- else{
- huCards[kpIndex].style = STYLE.ZMGANG;
- huCards[kpIndex].cards.push(card);
- }
- // console.error("sscc777胡牌分析card",card);
- // console.error("sscc777胡牌分析handCards",_handCards);
- // console.error("sscc777胡牌分析huCards",huCards);
- // console.error("sscc777胡牌分析isTouch,card",chairID,isTouch,card);
- let handCards = this.arr2ToArr1(_handCards,true);
- // console.error("sscc777胡牌分析handCards",chairID,JSON.stringify(handCards),_handCards);
- // let tempAllTai = 0/////临时总台数
- // let tempres = {}///本函数的返回值
- this.addThisIsHu = card//////TL++,胡牌判断时加上这张能不能胡
- // if(isAdd){
- // handCards = handCards.concat(card);/////不是自己抓的就把这张牌拼接进手牌中
- // handCards = this.sort(handCards);
- // }
- // 手牌不全
- var length = handCards.length;
- if (length % 3 == 1) return;//2个提还未补张,牌数不对无法胡排
- // console.warn("============================================== ",chairID,JSON.stringify(handCards),card);
- let khzh = this.getIsHu(handCards,card);//满足可胡牌型的所有手牌组合
- let cphx = this.getCPHX(huCards);//此人吃碰胡息
- let result = null;
-
- // console.warn("此人吃碰胡息222 ",cphx,huCards," khzh ",khzh);
- let mqzdhx = 0;//目前最大胡息
- for (var i = 0; i < khzh.length; i++) {
- if(khzh[i].length + huCards.length < 7) continue;
- let spcards = this.pai2weiTo3Wei(khzh[i]);//把2位数手牌转换为3位数
- let styles = this.getCardStyle(spcards);
- let hxTypes = this.getCardHXType(spcards,styles);
- let gbjg = this.sfxygbhxlx(isTouch,card,spcards,hxTypes);
- if(gbjg) {
- //胡息类型在此改变了
- // console.warn("胡息类型在此改变了2 ",hxTypes[gbjg[0]],gbjg);
- hxTypes[gbjg[0]] = gbjg[1];
- }
- let hxValues = this.getCardHXValue(hxTypes);
- let sphxs = _.sum(hxValues);//手牌胡息数
- let crzhx = sphxs+cphx;//此人总胡息
- // console.warn(" khzh[i] ",JSON.stringify(khzh[i])," spcards ",spcards," styles ",styles," hxTypes ",hxTypes," hxValues ",hxValues);
- if(crzhx >= this.khMinHX){
- if(crzhx > mqzdhx){
- mqzdhx = crzhx;
- result = {
- zdhx: mqzdhx,
- card: card,
- cards: spcards,
- hxInfos: {
- styles: styles,
- hxTypes: hxTypes,
- hxValues: hxValues
- }
- }
- }
- }
- }
- // console.warn("胡牌分析返回值2222 ",result);
- return result;
- };
- // // TL++是否需要改变胡息类型,比如手上2个小三,别人摸小三自己胡了,算胡息时这三个小三不能按照“小刻”算胡息,应该按照“小碰”算胡息
- proto.sfxygbhxlx = function (isTouch,card,handCards, hxTypes) {
- // console.warn("是否需要改变胡息类型 isTouch,card,handCards, hxTypes ",isTouch,card,handCards, hxTypes);
- if(isTouch) return false;
- let res = [];//[修改的下标,修改之后的值]
- for (var i = 0; i < handCards.length; i++) {
- if(handCards[i].indexOf(card) != -1){
- // if(hxTypes[i] != HUXITYPE.XIAOKE && hxTypes[i] != HUXITYPE.DAKE) return false;
- // console.warn("????????????????????mmmm111 ",i,hxTypes[i] ,HUXITYPE.XIAOKE,HUXITYPE.XIAOPENG);
- if(hxTypes[i] == HUXITYPE.XIAOKE) {
- res = [i,HUXITYPE.XIAOPENG];
- // console.warn("????????111");
- }
- if(hxTypes[i] == HUXITYPE.DAKE) {
- res = [i,HUXITYPE.DAPENG];
- // console.warn("????????222");
- }
- if(hxTypes[i] == HUXITYPE.XIAOTI) {
- res = [i,HUXITYPE.XIAOPAO];
- // console.warn("????????111");
- }
- if(hxTypes[i] == HUXITYPE.DATI) {
- res = [i,HUXITYPE.DAPAO];
- // console.warn("????????222");
- }
- // console.warn("????????????????????mmmm222 ",i,hxTypes[i] ,HUXITYPE.XIAOKE,HUXITYPE.XIAOPENG,res);
- }
- }
- if(res.length == 2) return res;
- // console.warn("????????????????????mmmm333 ",card,res);
- return false;
- };
- //更新胡牌提示里面的剩余张数 _cards需要更新的牌,因为吃需要更新好几张所以这参数是数组
- proto.updateSYPS = function (chairID,_cards,handCards,allhuCards,outCards,hutip) {
- if(!hutip.kehuData || hutip.kehuData.length < 1) return;
- let cards = _.cloneDeep(_cards);
- cards = _.uniq(cards);
- let syzs = -1;
- for (var x = 0; x < cards.length; x++) {
- let card = cards[x];
- for (var i = 0; i < hutip.kehuData.length; i++) {
- for (var j = 0; j < hutip.kehuData[i].tpxq.length; j++) {
- if(hutip.kehuData[i].tpxq[j][0] == card){
- if(syzs < 0) syzs = this.getACardSYZS(chairID,card,handCards,allhuCards,outCards);
- hutip.kehuData[i].tpxq[j][2] = syzs;
- }
- }
- }
- }
- };
- // // TL++非当前玩家胡牌提示 和hutip方法的区别是这个是判断非当前玩家(当前玩家手牌是够的非当前玩家手牌少一张)
- proto.hutip2 = function (chairID,_handCards, _huCards,_allhuCards,outCards) {
-
- // console.error("hutip777胡牌提示handCards222 ",chairID,_handCards,_huCards,this.yscs);
- // console.error("sscc777胡牌提示huCards",_huCards);
- let hutipRes = [];
- let handCards = this.arr2ToArr1(_handCards,true);
- // if(chairID == 1) console.warn("sscc777胡牌提示handCards ",chairID,_handCards);
- let huCardsys = this.deepCloneTL(_huCards);
- let allhuCards = _.clone(_allhuCards);////用统计胡牌提示的剩余牌
- let dangPaiList = this.getBDMakeList(handCards);
-
-
- let cphxys = this.getCPHX(huCardsys);//此人吃碰胡息
- // console.warn("hutip777胡牌提示 dangPaiList ",dangPaiList.length,JSON.stringify(dangPaiList));
- let kdcdp = 100;////可打出的牌 就是打出这个牌之后可以胡
- let dczhkhdp = [];////打出 kdcdp 之后可以胡的牌
- let yjpdgdsp = 0;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
-
- let isSTWK = false;//是否3提5坎;
- for (var k = 0; k < dangPaiList.length; k++) {
- this.yscs++;
- let handCards1 = _.cloneDeep(handCards);
- // let isneedLog = (chairID == 1 && dangPaiList[k] == 209)
- // if(isneedLog) console.warn("111=============胡牌提示huCards",i,handCards[i] , dangPaiList[k],handCards,huCardsys);
- let huCards = this.deepCloneTL(huCardsys);
- let cphx = cphxys;//此人吃碰胡息
- let resKind = this.getNewHuCards(chairID,handCards1,huCards,dangPaiList[k]);
- if(resKind == 0){
- handCards1.push(dangPaiList[k]);
- handCards1 = this.sort(handCards1);
- }
- else {
- //至此当的牌dangPaiList[k]已经放入碰杠牌中,故被替换的原来牌在这里删除
- // this.remove(handCards1,[yjpdgdsp])
- cphx = this.getCPHX(huCards);//此人吃碰胡息
- }
- let sfbnxcwt = resKind != 1 && resKind != 3 && resKind != 4;//是否不能形成偎提
- // if(isneedLog) console.warn("222===============胡牌提示 handCards1 ",resKind,handCards1.length,JSON.stringify(handCards1));
- let khzh = this.getIsHu(handCards1,dangPaiList[k]);//满足可胡牌型的所有手牌组合
- // if(isneedLog) console.warn("222===============胡牌提示222222 khzh",khzh,resKind)
- if(khzh.length == 0 && resKind > 0){
- // if(isneedLog) console.warn("222===============到这里了2 khzh",khzh,resKind)
- //放入吃碰牌不能胡时在这里判断不放入吃碰牌情况
- let handCards2 = _.cloneDeep(handCards);
- cphx = cphxys;//此人吃碰胡息
- handCards2.push(dangPaiList[k]);
- handCards2 = this.sort(handCards2);
- huCards = this.deepCloneTL(huCardsys);
- khzh = this.getIsHu(handCards2,dangPaiList[k]);//满足可胡牌型的所有手牌组合
- // if(isneedLog) console.warn("222===============到这里了333 khzh",khzh)
- }
- let result = null;
- let crzdpxfs = 0;//此人最大牌型番数 如果牌型和胡息不满足此值不会被赋值
- if(khzh.length > 0) {
- // if(isneedLog) console.warn("至此这手牌牌型满足要求了 此人吃碰胡息 ",cphx,khzh.length,huCards);
- let mqzdpxfs = 0;//目前最大牌型番数
- for (var x = 0; x < khzh.length; x++) {
- let crzhx = 0;//此人总胡息
- if(khzh[x].length + huCards.length < 7) continue;
- let spcards = this.pai2weiTo3Wei(khzh[x]);//把2位数手牌转换为3位数
- let styles = this.getCardStyle(spcards);
- let hxTypes = this.getCardHXType(spcards,styles);
- let hxValues = this.getCardHXValue(hxTypes);
- let sphxs = _.sum(hxValues);//手牌胡息数
- crzhx = sphxs+cphx;//此人总胡息
- // if(isneedLog) console.warn(" khzh[x] ",x,JSON.stringify(khzh[x])," spcards ",spcards," styles ",styles," hxTypes ",hxTypes," hxValues ",hxValues);
- if(crzhx >= this.khMinHX){
- // let typeInfo = this.isGetCardTypeTL(chairID,spcards,huCards,[],true,dangPaiList[k])
- // let allFan = typeInfo.allFan;//第X种组合方式的总番数
- // if(allFan > mqzdpxfs){
- // if(isneedLog) console.warn("在这里刷新 目前最大牌型番数 mqzdpxfs, allFan ",mqzdpxfs, allFan);
- // mqzdpxfs = allFan;//刷新目前最大牌型番数
- // }
- crzdpxfs = 1;//如果要计算番数需要把这行去掉
- break;
- }
- }
- // 在这里对最高胡息最终结果进行赋值
- // if(mqzdpxfs > crzdpxfs) crzdpxfs = mqzdpxfs;
- }
- if(crzdpxfs > 0){//如果牌型和胡息不满足此值不会被赋值
- let syzs = this.getACardSYZS(chairID,dangPaiList[k],_handCards,allhuCards,outCards);
- // console.warn("111????????????????????????????????",dangPaiList[k],syzs);
- dczhkhdp[dczhkhdp.length] = [dangPaiList[k],crzdpxfs,syzs];////[可胡的牌,最大胡息,剩余张数]
- }
- }
- if(dczhkhdp.length > 0 || isSTWK){
- ////至此表示打出handCards[i]之后可以听牌
- let data = {
- "canTing": kdcdp,////表示打出这张牌之后可以听牌
- "youjin": isSTWK,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用
- "tpxq": dczhkhdp
- }
- hutipRes[hutipRes.length] = data;
- }
- // console.warn("333????????????????????????????????",JSON.stringify(hutipRes));
- // console.warn("222sscc777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs);
- let kehuData3 = {
- kehuData:hutipRes/////对象数组,分别表示打哪张可胡哪几张数据
- };
- return kehuData3;
- // return hutipRes;
- };
- //在胡牌提示里将 当的牌 放入碰杠牌里
- proto.getNewHuCards = function (chairID,_handCards, _huCards,card) {
- // console.warn("在胡牌提示里将当的牌放入碰杠牌里 _handCards",JSON.stringify(_handCards));
- let resKind = 0;//处理类型,0表示加入手牌,1表示需和手牌组成偎提,2表示可以和吃碰牌组成提跑
- let sameList = _handCards.filter(e => e === card);
- let addType = 0;//新增的吃碰类型
- if(sameList.length == 2) addType = STYLE.WEI;
- else if(sameList.length == 3) addType = STYLE.ANGANG;
- if(addType > 0){
- sameList.push(card);//手牌和当的牌成提牌
- let addItem = { style: addType, cards: sameList, card: card, origin: chairID}
- _huCards.push(addItem)
- this.remove(_handCards,sameList)
- // console.warn("在胡牌提示里将当的牌放入碰杠牌里 2222 ",JSON.stringify(sameList),JSON.stringify(_handCards));
- resKind = 1;
- if(addType = STYLE.WEI) resKind = 4;
- }
- else{
- for (let i = 0; i < _huCards.length; ++i) {
- if(_huCards[i].card != card) continue;
- if (_huCards[i].style == STYLE.PENG) {//跑牌情况2:当自己从墩上摸得牌,是自己已经碰的牌
- _huCards[i].style = STYLE.ZMGANG;
- _huCards[i].cards.push(card);
- resKind = 2;
- break;
- }
- else if (_huCards[i].style == STYLE.WEI) {//提牌情况3:当自己从墩上摸得牌,是自己已经“偎牌”的牌
- _huCards[i].style = STYLE.ANGANG;
- _huCards[i].cards.push(card);
- resKind = 3;
- break
- }
- }
- }
- return resKind;
- }
- // // TL++胡牌提示 chairID(TL++这个参数) 手牌 手上的吃碰杠牌 这个是胡牌提示里不统计台数
- proto.hutip = function (chairID,_handCards, _huCards,_allhuCards,outCards) {
- // return {
- // kehuData:[]/////对象数组,分别表示打哪张可胡哪几张数据
- // };////服务端运算量太大放到前端去计算了
- this.yscs = 0
- // console.error("hutip777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs);
- // console.error("sscc777胡牌提示huCards",_huCards);
- let hutipRes = [];
- let handCards = this.arr2ToArr1(_handCards,true);
- // if(chairID == 1) console.warn("sscc777胡牌提示handCards ",chairID,_handCards);
- let huCardsys = this.deepCloneTL(_huCards);
- let allhuCards = _.clone(_allhuCards);////用统计胡牌提示的剩余牌
- let dangPaiList = this.getBDMakeList(handCards);
-
-
- let cphxys = this.getCPHX(huCardsys);//此人吃碰胡息
- // console.warn("hutip777胡牌提示 dangPaiList ",dangPaiList.length,JSON.stringify(dangPaiList));
- let kdcdp = 0;////可打出的牌 就是打出这个牌之后可以胡
- let dczhkhdp = [];////打出 kdcdp 之后可以胡的牌
- let yjpdgdsp = 0;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
- // let yjpdgdzh = [];////已经判断过的组合 把28换成26 和 把26换成28 的结果是一样的所以可以剔除以减少运算
- // console.warn("=============胡牌提示 开始运算 ",handCards.length,JSON.stringify(handCards));
- for (var i = 0; i < handCards.length; i++) {
- kdcdp = handCards[i];////可打出的牌
- dczhkhdp = [];
- if(handCards[i] == yjpdgdsp) continue;////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
- if(this.getACardCount(handCards,handCards[i]) >= 3) continue;
- yjpdgdsp = handCards[i];////已经判断过的手牌 为了减少运算量判断过的手牌就不再判断了
- let isSTWK = false;//是否3提5坎;
- for (var k = 0; k < dangPaiList.length; k++) {
- this.yscs++;
- let handCards1 = _.cloneDeep(handCards);
- // let isneedLog = (handCards1[i] == 208 && dangPaiList[k] == 107)
- // if(isneedLog) console.warn("111=============胡牌提示huCards",i,handCards[i] , dangPaiList[k],handCards,huCardsys);
- let huCards = this.deepCloneTL(huCardsys);
- let cphx = cphxys;//此人吃碰胡息
- let resKind = this.getNewHuCards(chairID,handCards1,huCards,dangPaiList[k]);
- if(resKind == 4 && yjpdgdsp == dangPaiList[k]) resKind = 0;
- if(resKind == 0){
- if(handCards1[i] != dangPaiList[k]){
- handCards1[i] = dangPaiList[k];
- handCards1 = this.sort(handCards1);
- }
- }
- else {
- //至此当的牌dangPaiList[k]已经放入碰杠牌中,故被替换的原来牌在这里删除
- this.remove(handCards1,[yjpdgdsp])
- cphx = this.getCPHX(huCards);//此人吃碰胡息
- }
- // if(isneedLog) console.warn("222===============胡牌提示 handCards1 ",resKind,handCards1.length,JSON.stringify(handCards1));
- let khzh = this.getIsHu(handCards1,dangPaiList[k]);//满足可胡牌型的所有手牌组合
- let sfbnxcwt = resKind != 1 && resKind != 3;//是否不能形成偎提
- if(khzh.length == 0 && sfbnxcwt){
- //放入吃碰牌不能胡时在这里判断不放入吃碰牌情况
- let handCards2 = _.cloneDeep(handCards);
- cphx = cphxys;//此人吃碰胡息
- if(handCards2[i] != dangPaiList[k]){
- handCards2[i] = dangPaiList[k];
- handCards2 = this.sort(handCards2);
- }
- huCards = this.deepCloneTL(huCardsys);
- khzh = this.getIsHu(handCards2,dangPaiList[k]);//满足可胡牌型的所有手牌组合
- }
- let result = null;
- let crzdpxfs = 0;//此人最大牌型番数 如果牌型和胡息不满足此值不会被赋值
- if(khzh.length > 0) {
- // if(isneedLog) console.warn("至此这手牌牌型满足要求了 此人吃碰胡息 ",cphx,khzh.length,huCards);
- let mqzdpxfs = 0;//目前最大牌型番数
- for (var x = 0; x < khzh.length; x++) {
- let crzhx = 0;//此人总胡息
- if(khzh[x].length + huCards.length < 7) continue;
- let spcards = this.pai2weiTo3Wei(khzh[x]);//把2位数手牌转换为3位数
- let styles = this.getCardStyle(spcards);
- let hxTypes = this.getCardHXType(spcards,styles);
- let hxValues = this.getCardHXValue(hxTypes);
- let sphxs = _.sum(hxValues);//手牌胡息数
- crzhx = sphxs+cphx;//此人总胡息
- // if(isneedLog) console.warn(" khzh[x] ",x,JSON.stringify(khzh[x])," spcards ",spcards," styles ",styles," hxTypes ",hxTypes," hxValues ",hxValues);
- if(crzhx >= this.khMinHX){
- // let typeInfo = this.isGetCardTypeTL(chairID,spcards,huCards,[],true,dangPaiList[k])
- // let allFan = typeInfo.allFan;//第X种组合方式的总番数
- // if(allFan > mqzdpxfs){
- // if(isneedLog) console.warn("在这里刷新 目前最大牌型番数 mqzdpxfs, allFan ",mqzdpxfs, allFan);
- // mqzdpxfs = allFan;//刷新目前最大牌型番数
- // }
- crzdpxfs = 1;//如果要计算番数需要把这行去掉
- break;
- }
- }
- // 在这里对最高胡息最终结果进行赋值
- // if(mqzdpxfs > crzdpxfs) crzdpxfs = mqzdpxfs;
- }
- if(crzdpxfs > 0){//如果牌型和胡息不满足此值不会被赋值
- let syzs = this.getACardSYZS(chairID,dangPaiList[k],_handCards,allhuCards,outCards);
- // console.warn("111????????????????????????????????",dangPaiList[k],syzs);
- dczhkhdp[dczhkhdp.length] = [dangPaiList[k],crzdpxfs,syzs];////[可胡的牌,最大胡息,剩余张数]
- }
- }
- if(dczhkhdp.length > 0 || isSTWK){
- ////至此表示打出handCards[i]之后可以听牌
- let data = {
- "canTing": kdcdp,////表示打出这张牌之后可以听牌
- "youjin": isSTWK,////打出这张牌之后是不是游金(抛搭)这个在象山麻将里面没有用
- "tpxq": dczhkhdp
- }
- hutipRes[hutipRes.length] = data;
- }
- }
- // console.warn("333????????????????????????????????",JSON.stringify(hutipRes));
- // console.warn("222sscc777胡牌提示handCards ",chairID,_handCards,_huCards,this.yscs);
- let kehuData3 = {
- kehuData:hutipRes/////对象数组,分别表示打哪张可胡哪几张数据
- };
- return kehuData3;
- // return hutipRes;
- };
- ////TL++得到一张牌的剩余张数 用于胡牌提示提示该张的剩余张数
- proto.getACardSYZS = function (chairID,card,_handCards,allhuCards,outCards) {
- ////下面这段是适合胡牌提示里用的剩余牌数统计
- let yjcxdzs = 0;////该牌已经出现的张数
- for (var i = 0; i < _handCards.length; i++) {
- for (var j = 0; j < _handCards[i].length; j++) {
- if(card == _handCards[i][j]) 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 pgs = allhuCards[i][k].style;//碰杠类型
- let pgt = allhuCards[i][k].type;
- if(chairID != i && pgs == STYLE.WEI && pgt == 1) continue;//偎牌对于别人是暗牌所以不能统计
- 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
- let syzs = zs - yjcxdzs;////剩余张数 = 总张数 - 已经出现的张数
- // console.warn("333得到一张牌的剩余张数",card,syzs);
- if(syzs < 0) syzs = 0;
- return syzs;
- };
- ////二维数组转换为一维数组
- proto.arr2ToArr1 = function (_handCards,isSort) {
- let handCards = [];//_handCards.flat();
- for (var i = 0; i < _handCards.length; i++) {
- handCards = handCards.concat(_handCards[i]);
- }
- if(isSort) handCards = this.sort(handCards);
- return handCards;
- };
- //根据过掉的吃碰牌(yGDCPP)获得本次是否可以吃碰card
- proto.getIsCanCP = function (yGDCPP,card,type) {
- let kind = null;//过掉的类型=1表滑动打出,=2表过吃,=3表过碰,=4表过吃碰
- for (var i = 0; i < yGDCPP.length; i++) {
- if(yGDCPP[i][0] == card){
- kind = yGDCPP[i][1];
- break;
- }
- }
- if(!kind) return true;//没有过掉或打掉过此牌故可吃碰
- if(type == 1){//判断是否可吃
- if(kind == 3) return true;//过碰可以吃
- } else if(type == 2){//判断是否可碰
- }
- return false;
- };
- //根据过掉的吃碰牌(yGDCPP)获得card是否过掉用于判断臭偎(过吃肯定过碰)
- proto.getIsGuo = function (yGDCPP,card,type) {
- let kind = null;//过掉的类型=1表滑动打出,=2表过吃,=3表过碰,=4表过吃碰
- for (var i = 0; i < yGDCPP.length; i++) {
- if(yGDCPP[i][0] == card){
- kind = yGDCPP[i][1];
- break;
- }
- }
- if(!kind) return false;//没有过掉或打掉过此牌故可吃碰
- if(kind == 2 || kind == 3 || kind == 4) return true;//过碰可以吃
- return false;
- };
- //获得手牌张数
- proto.getSPZS = function (_handCards) {
- let count = 0;
- for (var i = 0; i < _handCards.length; i++) {
- count += _handCards[i].length;
- }
- return count;
- };
- //获得吃碰牌里提跑的个数
- proto.getCPPLTPGS = function (huCards) {
- let gwjdtgs = 0;//该玩家的提个数
- for (var i = 0; i < huCards.length; i++) {
- if(huCards[i].style == STYLE.ANGANG || huCards[i].style == STYLE.GANG) gwjdtgs++;
- }
- return gwjdtgs;
- };
- //获得是否需要不出牌(进子)
- proto.isNeedJinZi = function (_handCards,huCards) {
- let gwjdtgs = 0;//该玩家的提个数
- for (var i = 0; i < huCards.length; i++) {
- if(huCards[i].style == STYLE.ANGANG) gwjdtgs++;
- }
- if(gwjdtgs < 2) return false;
- let count = this.getSPZS(_handCards)
- if(count%3 == 0) return true;
- return false;
- };
- //获得吃碰之后是否需要不出牌(进子)在吃碰偎提跑之后调用,如果不需要出牌就给下家摸牌
- proto.isXYBCP = function (_handCards,huCards) {
- let gwjdtgs = 0;//该玩家的提个数
- for (var i = 0; i < huCards.length; i++) {
- if(huCards[i].style == STYLE.ANGANG) gwjdtgs++;
- }
- if(gwjdtgs < 2) return false;
- let count = this.getSPZS(_handCards)
- if(count%3 == 1) return true;
- return false;
- };
- //庄家手牌里增加一张牌(仅仅在发牌时无人可胡情况下才会调用)
- proto.addACardToCards = function (_handCards,card) {
- let handCards = this.arr2ToArr1(_handCards,false);
- handCards.push(card);
- return this.changeRes2(handCards);
- };
- //是否是发牌阶段
- proto.isFPJD = function () {
- return (this.moPaiCountTL == 1 && this.chuPaiCountTL == 0);
- };
- // 获得吃碰牌的胡息总数
- proto.getCPHX = function (huCards) {
- // console.warn("获得吃碰牌的胡息数 ",JSON.stringify(huCards));
- let res = 0
- for (let i = 0; i < huCards.length; ++i) {
- let phs = this.getType(huCards[i].card);
- if (huCards[i].style == STYLE.CHI) {
- let type = huCards[i].type;
- if(type >= 1 && type <=3){
- if(type == this.getValue(huCards[i].card)){
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOSHUN];//小顺
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DASHUN];//大顺
- }
- }
- else if(type == 4){
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOSHUN];//小顺
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DASHUN];//大顺
- }
- }
- else if (huCards[i].style == STYLE.PENG) {
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOPENG];//小碰
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DAPENG];//大碰
- }
- else if (huCards[i].style == STYLE.WEI) {
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOWEI];//小偎
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DAWEI];//大偎
- }
- else if (huCards[i].style == STYLE.GANG || huCards[i].style == STYLE.ZMGANG) {
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOPAO];//小跑
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DAPAO];//大跑
- }
- else if (huCards[i].style == STYLE.ANGANG) {
- if(phs == 1) res += HUXIVALUE[HUXITYPE.XIAOTI];//小提
- else if(phs == 2) res += HUXIVALUE[HUXITYPE.DATI];//大提
- }
- }
- return res;
- };
- // 获得吃碰牌的胡息数组
- proto.getCPHXInfo = function (huCards) {
- // console.warn("获得吃碰牌的胡息数组 ",JSON.stringify(huCards));
- let styles = [];
- let hxTypes = [];
- let hxValues = [];
- for (let i = 0; i < huCards.length; ++i) {
- let phs = this.getType(huCards[i].card);
- console.warn("");
- if (huCards[i].style == STYLE.CHI) {
- let type = huCards[i].type;
- if(type >= 1 && type <=3){
- if(type == this.getValue(huCards[i].card)){//小顺或者大顺
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOSHUN]);//小顺
- hxTypes.push(HUXITYPE.XIAOSHUN);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DASHUN]);//大顺
- hxTypes.push(HUXITYPE.DASHUN);
- }
- styles.push(STYLE.SUN);
- }
- else{//普通顺子
- styles.push(STYLE.SUN);
- hxValues.push(HUXIVALUE[HUXITYPE.NULL]);
- hxTypes.push(HUXITYPE.NULL);
- }
- }
- else if(type == 4){//二七十或贰柒拾
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOSHUN]);//小顺
- hxTypes.push(HUXITYPE.XIAOSHUN);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DASHUN]);//大顺
- hxTypes.push(HUXITYPE.DASHUN);
- }
- styles.push(STYLE.SUN);
- }
- else{//绞牌
- styles.push(STYLE.JIAO);
- hxValues.push(HUXIVALUE[HUXITYPE.NULL]);
- hxTypes.push(HUXITYPE.NULL);
- }
- }
- else if (huCards[i].style == STYLE.PENG) {
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOPENG]);//小碰
- hxTypes.push(HUXITYPE.XIAOPENG);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DAPENG]);//大碰
- hxTypes.push(HUXITYPE.DAPENG);
- }
- styles.push(STYLE.PENG);
- }
- else if (huCards[i].style == STYLE.WEI) {
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOWEI]);//小偎
- hxTypes.push(HUXITYPE.XIAOWEI);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DAWEI]);//大偎
- hxTypes.push(HUXITYPE.DAWEI);
- }
- styles.push(STYLE.WEI);
- }
- else if (huCards[i].style == STYLE.GANG || huCards[i].style == STYLE.ZMGANG) {
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOPAO]);//小跑
- hxTypes.push(HUXITYPE.XIAOPAO);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DAPAO]);//大跑
- hxTypes.push(HUXITYPE.DAPAO);
- }
- if (huCards[i].style == STYLE.GANG) styles.push(STYLE.GANG);
- else if (huCards[i].style == STYLE.ZMGANG) styles.push(STYLE.ZMGANG);
- }
- else if (huCards[i].style == STYLE.ANGANG) {
- if(phs == 1) {
- hxValues.push(HUXIVALUE[HUXITYPE.XIAOTI]);//小提
- hxTypes.push(HUXITYPE.XIAOTI);
- }
- else if(phs == 2) {
- hxValues.push(HUXIVALUE[HUXITYPE.DATI]);//大提
- hxTypes.push(HUXITYPE.DATI);
- }
- styles.push(STYLE.ANGANG);
- }
- else{
- styles.push(STYLE.NULL);
- hxValues.push(HUXIVALUE[HUXITYPE.NULL]);
- hxTypes.push(HUXITYPE.NULL);
- }
- }
- let res = {
- styles: styles,
- hxTypes: hxTypes,
- hxValues: hxValues,
- }
- return res;
- };
- //得到满足可胡的所有手牌搭配 kksfkc坎坷是否可拆
- proto.getIsHu = function (cards,addCard) {
- // let map1 = [1,1,2,2,3,3,11,11,12,12,13,13,4,4]
- let map1 = this.pai3weiTo2Wei(cards);
- // console.warn("getIsHu cards,map1 ",cards.length,JSON.stringify(cards),map1.length,JSON.stringify(map1));
- let map = _.fill(Array(this.MAX_PAI_CNT), 0);//[];
- let mapDeep = _.fill(Array(this.MAX_PAI_CNT), 0);//[];
- // console.warn("getIsHu map.length ",map.length,JSON.stringify(map));
- for (let i = 0; i < map1.length; i++) {
- map[map1[i]]++;//为了统计每个牌值的张数
- mapDeep[map1[i]]++;//为了统计每个牌值的张数
- }
- // console.warn("getIsHu map ",JSON.stringify(map));
- this.paiArr = _.cloneDeep(map);
- this.fromPaiId = 0;
- this.lastNum = map1.length;
- this.duiList = [];//保存所有可以胡的牌型,数组元素是long类型,有几个元素代表有几种不同的可组合成胡的方式
- // this.duiList[0] = item;
- this.laiZiList = [];//所有可以胡牌型用到的癞子保存在这里,元素代表本次可胡方式中百搭当的牌
- this.takeOffAll();
- // console.warn("下面是this.duiList ",this.byteType,this.bytePai,this.duiList.length,this.duiList);
- if(this.duiList.length == 0){
- this.paiArr = _.cloneDeep(mapDeep);
- this.fromPaiId = 0;
- this.lastNum = map1.length;
- this.takeOffAllTL(addCard);
- }
- // console.warn("下面是this.duiListTL ",this.byteType,this.bytePai,this.duiList.length,this.duiList);
- let result = [];
- for (var i = 0; i < this.duiList.length; i++) {
- let dui = bigInt(this.duiList[i]);
- let item = [];
- // console.warn("这是 dui "+dui.toString() + " "+ typeof dui+ " "+ typeof this.duiList[i]);
- while (dui > 0) {
- // console.warn("这是000 dui "+dui.toString()+" bitPai "+this.bitPai+" bitType "+this.bitType +" type "+ typeof dui);
- // item.push(this.popDui(dui.toString()));
- item.unshift(this.popDui(dui.toString()));
- // console.warn("这是111 dui "+dui.toString()+" bitPai "+this.bitPai+" bitType "+this.bitType+" type "+ typeof dui);
- let he = this.bitPai+this.bitType;//bigInt(this.bitPai).add(bigInt(this.bitType));
- let duiItem = dui;
- dui = duiItem.shiftRight(he);
- // console.warn("这是222 dui "+dui.toString()+" bitPai "+this.bitPai+" bitType "+this.bitType + " type "+typeof dui);
- }
- result.push(item)
- }
- // console.warn("getIsHu result ",result);
- return result;
- };
- // 拆分手牌(无参数,只在huanaly中调用)
- proto.takeOffAll = function () {
- let dui = bigInt("0").toString();//long类型
- // console.warn("dui的类型 ",typeof dui);
- // console.warn("拆分手牌(无参数,只在huanaly中调用)111-----------------------------------------");
- // 手里有3张以上相同的不可以拆
- for (let i = this.XIAO_YI; i <= this.DA_SHI; i++) {
- if (this.paiArr[i] >= 3 && i != this.fromPaiId) {
- // if(this.paiArr[i] == 4) console.warn("takeOffAll ",i,dui,this.paiArr[i],JSON.stringify(this.paiArr));
- dui = this.pushDui(dui, i, this.paiArr[i] == 3 ? this.KAN : this.TI);
- this.lastNum -= this.paiArr[i];
- this.paiArr[i] = 0;
- }
- }
- // console.warn("拆分手牌(无参数,只在huanaly中调用)222-----------------------------------------");
- //处理好提坎之后从最小的牌开始拆分
- this.takeOffAll2(this.XIAO_YI, dui);
- };
- // 牌1:[209,209,209,109,109,109,104,204,204,101,102,103,202,207,210,108,108,108,106,107],
- // 牌2:[209,209,209,109,109,109,104,204,204,101,102,103,202,207,210,108,108,108,106,106],
- //上面takeOffAll()判断牌1会出错所以增加了下,面这个takeOffAllTL(),为了实现亮张不必非和手牌组成坎刻不可拆
- // (因为两手牌对108使用不一样,一个是和自己手上3个108组成提一个是和手上的106,107组成6,7,8顺子)
- // 拆分手牌(无参数,只在huanaly中调用)
- proto.takeOffAllTL = function (addCard) {
- let dui = bigInt("0").toString();//long类型
- // 手里有3张以上相同的不可以拆
- let addCardZHZH = this.pai3weiTo2Wei([addCard])[0];//胡的那张牌转换之后
- for (let i = this.XIAO_YI; i <= this.DA_SHI; i++) {
- let count = this.paiArr[i];
- if(count >= 3 && addCardZHZH == i) {
- count--;
- }
- if (count >= 3 && i != this.fromPaiId) {
- dui = this.pushDui(dui, i, count == 3 ? this.KAN : this.TI);
- this.lastNum -= count;
- this.paiArr[i] -= count;
- }
- }
- // for (let i = this.XIAO_YI; i <= this.DA_SHI; i++) {
- // if (this.paiArr[i] == 3 && i != this.fromPaiId) {
- // dui = this.pushDui(dui, i, this.paiArr[i] == 3 ? this.KAN : this.TI);
- // this.lastNum -= this.paiArr[i];
- // this.paiArr[i] = 0;
- // }
- // else if (this.paiArr[i] == 4 && i != this.fromPaiId) {
- // // dui = this.pushDui(dui, i, this.paiArr[i] == 3 ? this.KAN : this.TI);
- // dui = this.pushDui(dui, i,this.KAN);
- // this.lastNum -= 3;
- // this.paiArr[i] = 1;
- // }
- // }
- //处理好提坎之后从最小的牌开始拆分
- this.takeOffAll2(this.XIAO_YI, dui);
- };
- // 拆分手牌(无参数,只在huanaly中调用)
- proto.takeOffAll2 = function (paiId, dui) {
- // console.warn("takeOffAll参数 lastNum "+this.lastNum+" dui "+dui+" paiId "+paiId);
- // 剩余3张以内的 0是拆完了可以胡 1不能胡 2刚好是个将就可以胡
- if (this.lastNum < 3) {
- if (this.lastNum == 0) {
- // 能胡
- // console.warn("这种方式能胡 ",dui,typeof dui);
- this.duiList.push(dui);
- // 保存癞子代替的牌
- let laizi = 0;
- for (let i = this.XIAO_YI; i <= this.DA_SHI; i++) {
- for (let j = this.paiArr[i]; j < 0; j++) {
- // laizi = laizi << this.bitPai | i;
- }
- }
- this.laiZiList.push(laizi);
- } else if (this.lastNum == 2) {
- // 剩余2张能否做将
- this.takeOffJiang(dui);
- }
- return;
- }
- for (let i = paiId; i <= this.DA_SHI; i++) {
- // 4张相同的
- this.takeOffSame(i, 4, this.TI, dui);
- // 3张相同的
- this.takeOffSame(i, 3, this.KAN, dui);
- // 2710
- this.takeOff2710(i, dui);
- // 拆顺子
- this.takeOff123(i, dui);
- // 拆混对
- this.takeOffHunDui(i, dui);
- }
- };
- //拆分将,剩余2张能否做将
- proto.takeOffJiang = function (dui) {
- // console.warn("拆分将,剩余2张能否做将 dui "+dui);
- let wangNum = this.paiArr[this.WANG];
- let paiNum = 2 - wangNum;
- this.paiArr[this.WANG] = 0;
- for (let i = this.XIAO_YI; i <= this.DA_SHI; i++) {
- if (this.paiArr[i] == paiNum) {
- this.paiArr[i] -= 2;
- this.lastNum -= 2;
- this.takeOffAll2(this.MAX_PAI_CNT, this.pushDui(dui, i, this.DUIZI));
- this.paiArr[i] += 2;
- this.lastNum += 2;
- }
- }
- this.paiArr[this.WANG] += wangNum;
- };
- //拆分相同的,
- proto.takeOffSame = function (i, cnt, type, dui) {
- // console.warn("拆分相同的, "+" i "+i+" cnt "+cnt+" type "+type+" dui "+dui);
- if (this.paiArr[i] + this.paiArr[this.WANG] >= cnt) {
- let needWang = cnt - this.paiArr[i];
- if (needWang > 0) {
- this.paiArr[this.WANG] -= needWang;
- }
- this.paiArr[i] -= cnt;
- this.lastNum -= cnt;
- this.takeOffAll2(i, this.pushDui(dui, i, type));
- this.lastNum += cnt;
- this.paiArr[i] += cnt;
- if (needWang > 0) {
- this.paiArr[this.WANG] += needWang;
- }
- }
- };
- //拆分普通顺子
- proto.takeOff123 = function (i, dui) {
- // console.warn("拆分普通顺子 "+" i "+i+" dui "+dui);
- // 处理边界的问题,9 10 11变成顺子的问题
- let border = (i - 1) % 10;
- if (border > 7) {
- return;
- }
- let i1 = i + 1;
- let i2 = i + 2;
- this.takeOffSingle(i, i1, i2, this.SHUNZI, dui);
- };
- //拆分2710
- proto.takeOff2710 = function (i, dui) {
- // 只有是2的时候才组合2710
- if (i % 10 != 2) {
- return;
- }
- let i1 = i + 5;
- let i2 = i + 8;
- // console.warn("takeOff2710 "+" i "+i+" i1 "+i1+" i2 "+i2+" S2710 "+this.S2710+" dui "+dui);
- this.takeOffSingle(i, i1, i2, this.S2710, dui);
- };
- //拆分单牌
- proto.takeOffSingle = function (i, i1, i2, type, dui) {
- let needWang = 0;
- if (this.paiArr[i] < 1)
- needWang++;
- if (this.paiArr[i1] < 1)
- needWang++;
- if (this.paiArr[i2] < 1)
- needWang++;
- // console.warn("takeOffSingle111 "+" needWang "+needWang+" this.paiArr[this.WANG] "+this.paiArr[this.WANG]+" WANG "+this.WANG+" dui "+dui+" i "+i+" i1 "+i1+" i2 "+i2);
- if (this.paiArr[this.WANG] >= needWang) {
- this.paiArr[this.WANG] -= needWang;
- this.paiArr[i]--;
- this.paiArr[i1]--;
- this.paiArr[i2]--;
- this.lastNum -= 3;
- // console.warn("takeOffSingle222 "+" needWang "+needWang+" this.paiArr[this.WANG] "+this.paiArr[this.WANG]+" this.WANG "+this.WANG+" dui "+dui+" i "+i+" type "+type);
- this.takeOffAll2(i, this.pushDui(dui, i, type));
- this.lastNum += 3;
- this.paiArr[i]++;
- this.paiArr[i1]++;
- this.paiArr[i2]++;
- this.paiArr[this.WANG] += needWang;
- }
- };
- //拆分混对(绞牌)和下面的参数不一样
- proto.takeOffHunDui = function (i, dui) {
- // console.warn("拆分混对(绞牌) "+" i "+i+" dui "+dui);
- let relatePai = i > 10 ? i - 10 : i + 10;
- if (this.paiArr[i] >= 1 && this.paiArr[relatePai] >= 1) {
- if (this.paiArr[i] >= 2) {
- this.takeOffHunDui2(i, relatePai, dui);
- } else if (this.paiArr[this.WANG] >= 1) {
- this.paiArr[this.WANG]--;
- this.takeOffHunDui2(i, relatePai, dui);
- this.paiArr[this.WANG]++;
- }
- }
- };
- //拆分混对(绞牌)和上面的参数不一样
- proto.takeOffHunDui2 = function (i, relatePai, dui) {
- // console.warn("拆分混对(绞牌)222 "+" i "+i+" relatePai "+relatePai+" dui "+dui);
- this.paiArr[i] -= 2;
- this.paiArr[relatePai]--;
- this.lastNum -= 3;
- this.takeOffAll2(i, this.pushDui(dui, i, this.HUNDUN));
- this.lastNum += 3;
- this.paiArr[i] += 2;
- this.paiArr[relatePai]++;
- };
- //
- proto.pushDui = function (dui, paiId, type) {
- // let typeStr = ""+type+"(";
- // if(type == 1) typeStr += "顺子";
- // else if(type == 2) typeStr += "混对";
- // else if(type == 3) typeStr += "坎";
- // else if(type == 4) typeStr += "提";
- // else if(type == 5) typeStr += "对子";
- // else if(type == 6) typeStr += "27十";
- // typeStr += ")";
- let x1 = bigInt(dui);
- let x2 = bigInt(paiId);
- let x3 = bigInt(type);
- // //上面是对参数进行类型转换,下面是运算
- let a1 = x1.shiftLeft(this.bitType);
- let a2 = a1.or(x3);//a1.or(bigInt("6"));
- let a3 = a2.shiftLeft(this.bitPai);
- let a4 = a3.or(x2);//a3.or(bigInt("12"));
- let res = a4.toString();
- // console.warn("pushDui res "+res+" dui "+dui+" paiId "+paiId+" type "+typeStr+" bitType "+this.bitType+" bitPai "+this.bitPai);
- return res;
- };
- proto.popDui = function (dui) {
- // let paiId = parseInt(dui & this.bytePai);
- // let type = parseInt(dui >>> this.bitPai & this.byteType);
- let x1 = bigInt(dui);
- let x2 = bigInt(this.bytePai);
- let x3 = bigInt(this.byteType);
- let a1 = x1.and(x2);
- let paiId = a1.valueOf();
- let a2 = x1.shiftRight(this.bitPai);
- let a3 = a2.and(x3);
- let type = a3.valueOf();
- // console.warn("popDui000 dui "+dui+" bitPai "+this.bitPai+" bytePai "+this.bytePai+" byteType "+this.byteType);
- // console.warn("popDui111 type "+type+" paiId "+paiId);
- switch (type) {
- case this.TI:
- return [paiId, paiId, paiId, paiId];
- case this.KAN:
- return [paiId, paiId, paiId];
- case this.SHUNZI:
- return [paiId, paiId + 1, paiId + 2];
- case this.S2710:
- return [paiId, paiId + 5, paiId + 8];
- case this.HUNDUN:
- let relatePai = paiId > 10 ? paiId - 10 : paiId + 10;
- return [paiId, paiId, relatePai];
- case this.DUIZI:
- return [paiId, paiId];
- }
- return [];
- };
- //3位数字的牌转换为2位数字的牌
- proto.pai3weiTo2Wei = function (cards) {
- // let pai2WeiList = [0n,1n,2n,3n,4n,5n,6n,7n,8n,9n,10n,11n,12n,13n,14n,15n,16n,17n,18n,19n,20n,21n,22n,23n];
- let res = [];
- for (var i = 0; i < cards.length; i++) {
- let ct = this.getType(cards[i]);
- if(ct == 1) res[i] = cards[i]-100;
- else if(ct == 2) res[i] = cards[i]-200+10;
- }
- return res;
- };
- //2位数字的牌转换为3位数字的牌 参数是数组,数组元素也是数组
- proto.pai2weiTo3Wei = function (cardsArr) {
- let res = [];
- for (var i = 0; i < cardsArr.length; i++) {
- let item = [];
- for (var j = 0; j < cardsArr[i].length; j++) {
- let card = cardsArr[i][j];
- let ct = Math.ceil(card / 10);
- if(ct == 1) item[j] = card+100;
- else if(ct == 2) item[j] = card-10+200;
- }
- res.push(item);
- }
- return res;
- };
- //得到偎完之后是否无牌可出
- proto.getSFWPKC2 = function (handCards,handHXInfos) {
- let kcdp = [];//可出的牌
- for (var i = 0; i < handHXInfos.hxTypes.length; i++) {
- if(handHXInfos.hxTypes[i] < 3) {//因为杂牌小顺大顺,这些牌都是能出的
- kcdp = kcdp.concat(handCards[i]);
- }
- }
- // console.warn("得到吃碰偎之后是否无牌可出 ",kcdp.length,JSON.stringify(handHXInfos),JSON.stringify(handCards),kcdp);
- return kcdp.length <= 0;
- }
- //得到吃碰偎之后是否无牌可出(手上都是刻子的时候就无牌可出了)
- proto.getSFWPKC = function (handCards,handHXInfos) {
- let kcdp = [];//可出的牌
- for (var i = 0; i < handHXInfos.hxTypes.length; i++) {
- if(handHXInfos.hxTypes[i] < 3) {//因为杂牌小顺大顺,这些牌都是能出的
- kcdp = kcdp.concat(handCards[i]);
- }
- }
- // console.warn("得到吃碰偎之后是否无牌可出 ",kcdp.length,JSON.stringify(handHXInfos),JSON.stringify(handCards),kcdp);
- return kcdp.length <= 2;
- }
- //得到剩余牌堆
- proto.getSYPaiDui = function () {
- // console.warn("得到剩余牌堆 ",this.castCount,this.cardsPool.length);
- let res = this.cardsPool.slice(this.castCount, this.cardsPool.length);
- // console.warn("得到剩余牌堆222 ",this.castCount,this.cardsPool.length);
- return res;
- };
- // 获得赢家每列牌的类型和胡息数
- proto.getWinerHXInfo = function (huResItem,huCards) {
- // console.warn("获得赢家每列牌的类型和胡息数 huResItem ",JSON.stringify(huResItem));
- // console.warn("获得赢家每列牌的类型和胡息数 huCards ",JSON.stringify(huCards));
- let cphxInfo = this.getCPHXInfo(huCards);
- let styles = cphxInfo.styles;
- let hxTypes = cphxInfo.hxTypes;
- let hxValues = cphxInfo.hxValues;
- // console.warn("获得赢家每列牌的类型和胡息数 cphxInfo ",JSON.stringify(cphxInfo));
- if(huResItem && huResItem.hxInfos){
- styles = styles.concat(huResItem.hxInfos.styles);
- hxTypes = hxTypes.concat(huResItem.hxInfos.hxTypes);
- hxValues = hxValues.concat(huResItem.hxInfos.hxValues);
- }
- let hxInfos = {
- styles: styles,
- hxTypes: hxTypes,
- hxValues: hxValues
- }
- return hxInfos;
- };
- ////////////////////下面是计算牌型相关的////////////////////
- //计算牌型和番数
- proto.isGetCardTypeTL = function (chairID,handCards, huCards, hures,isMoHu,addcard) {
- let tempsatisfyType = []////临时胡牌牌型
- for (let i = 0; i < this.huTypeTL.length; ++i) {
- tempsatisfyType[i] = 0
- }
- let curTaiShu = 0/////临时总台数
- let shoupai = []/////手牌
- for (var i = 0; i < handCards.length; i++) {
- shoupai = shoupai.concat(handCards[i])
- }
- let PGPai = huCards/////手上的碰杠牌
- let chengju = hures/////整理好之后成句的牌(包括碰杠牌)
- // let chengju = hures/////整理好之后成句的牌(包括碰杠牌)
- // console.warn("计算牌型和番数 PGPai ",JSON.stringify(PGPai));
- let geLeiCount = [0,0,0,0];//各类型个数[大子个数,小子个数,红牌个数,黑牌个数]
- for (var i = 0; i < handCards.length; i++) {
- for (var j = 0; j < handCards[i].length; j++) {
- let type = this.getType(handCards[i][j]);
- let value = this.getValue(handCards[i][j]);
- if(type == 1) geLeiCount[1]++;
- else if(type == 2) geLeiCount[0]++;
- if(value == 2 || value == 7 || value == 10) geLeiCount[2]++;
- else geLeiCount[3]++;
- }
- }
- for (var i = 0; i < PGPai.length; i++) {
- for (var j = 0; j < PGPai[i].cards.length; j++) {
- let ic = PGPai[i].cards[j];
- let type = this.getType(ic);
- let value = this.getValue(ic);
- if(type == 1) geLeiCount[1]++;
- else if(type == 2) geLeiCount[0]++;
- if(value == 2 || value == 7 || value == 10) geLeiCount[2]++;
- else geLeiCount[3]++;
- }
- }
- // console.warn("各类型个数[大子个数,小子个数,红牌个数,黑牌个数] ",JSON.stringify(geLeiCount));
- this.hongHuCount = 0;
- this.daHuCount = 0;
- this.xiaoHuCount = 0;
- this.datuanyuanCount = 0;
- this.wxdldgs = 0;//无息的列的个数,用来判断真假行息
- this.isBeiKaoBei = false;//是否满足背靠背,用来判断真假背靠背
- for (let i = 0; i < this.huTypeTL.length; ++i) {
- if(this.xypddpxlb.indexOf(i) == -1) continue;//需要判断的牌型列表
- if( i == 0 && this.isTIANHU(handCards,PGPai,chengju,geLeiCount,isMoHu)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 1 && this.isDIHU(handCards,PGPai,chengju,geLeiCount,isMoHu)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 2 && this.isHAIHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 3 && this.isTINGHU(handCards,PGPai,chengju,geLeiCount,chairID)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 4 && this.isHONGHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1] + this.hongHuCount*1;
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 5 && this.isHEIHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 6 && this.isDIANHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 7 && this.isDAHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1] + this.daHuCount*1;
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 8 && this.isXIAOHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1] + this.xiaoHuCount*1;
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 9 && this.isSHUAHOU(handCards,PGPai,chengju,geLeiCount,addcard)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 10 && this.isHUANGFAN(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 11 && this.isDUIZIHU(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 12 && this.isDATUANYUAN(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]*this.datuanyuanCount;
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 13 && this.isZHENHANGXI(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 14 && this.isJIAHANGXI(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 15 && this.isSIQIHONG(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 16 && this.isZHENBEIKAOBEI(handCards,PGPai,chengju,geLeiCount,isMoHu)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 17 && this.isJIABEIKAOBEI(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 18 && this.isSANTIWUKAN(handCards,PGPai,chengju,geLeiCount)){
- //满足3提5坎肯定满足天胡和听胡
- // curTaiShu = curTaiShu + this.huTypeTL[3][1]
- // tempsatisfyType[3] = 1/////设置胡牌满足的牌型
- let itemIndex = 3;
- if(this.gameKindTL == 3) itemIndex = 18
- curTaiShu = curTaiShu + this.huTypeTL[itemIndex][1]
- tempsatisfyType[itemIndex] = 1/////设置胡牌满足的牌型
- }
- else if( i == 19 && this.isJINWUCANGJIAO(handCards,PGPai,chengju,geLeiCount,isMoHu)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 20 && this.isDING(handCards,PGPai,chengju,geLeiCount)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- else if( i == 21 && this.isZHUOXIAOSAN(handCards,PGPai,chengju,geLeiCount,isMoHu)){
- curTaiShu = curTaiShu + this.huTypeTL[i][1]
- tempsatisfyType[i] = 1;/////设置胡牌满足的牌型
- }
- }
- let hutype = [];
- let allFan = 0;
- for (var i = 0; i < tempsatisfyType.length; i++) {
- if(tempsatisfyType[i] < 1) continue;
- if(i == 10) continue;//黄番在计算完之后算,因为比较特殊放在牌型最后一个
- let fanitem = this.huTypeTL[i][1];//此牌型的番数
- if(i == 4) fanitem = this.huTypeTL[i][1] + this.hongHuCount*1;
- else if(i == 7) fanitem = this.huTypeTL[i][1] + this.daHuCount*1;
- else if(i == 8) fanitem = this.huTypeTL[i][1] + this.xiaoHuCount*1;
- else if(i == 12) fanitem = this.huTypeTL[i][1] * this.datuanyuanCount*1;
- allFan += fanitem;//黄番最后*2,所以这里不加黄番的番数
- hutype.push([this.huTypeTL[i][0],fanitem]);
- }
- if(allFan == 0) allFan = 1;//没有牌型的话算1番
- if(tempsatisfyType[10]){//黄番最后*2
- hutype.push([this.huTypeTL[10][0],this.huTypeTL[10][1]]);
- allFan = allFan*2;
- }
- // console.warn("计算牌型和番数 tempsatisfyType ",JSON.stringify(tempsatisfyType)," hutype ",hutype);
- return{hutype:hutype,allFan:allFan}
- }
- //是否 "天胡",
- proto.isTIANHU = function (shoupai,PGPai,chengju,geLeiCount,isMoHu) {
- let isstwk = this.isSANTIWUKAN(shoupai,PGPai,chengju,geLeiCount);
- if(isstwk && isMoHu) return true;
- return this.chuPaiCountTL == 0 && isMoHu;
- };
- //是否 "地胡",
- proto.isDIHU = function (shoupai,PGPai,chengju,geLeiCount,isMoHu) {
- let isstwk = this.isSANTIWUKAN(shoupai,PGPai,chengju,geLeiCount);
- if(isstwk && (!isMoHu) && this.chuPaiCountTL == 0) return true;
- return (this.chuPaiCountTL == 0 && !isMoHu);
- };
- //是否 "海胡",
- proto.isHAIHU = function (shoupai,PGPai,chengju,geLeiCount) {
- return this.lastCount == 0;
- };
- //是否 "听胡", 这个判断方法的前提是3提五坎不能点过
- proto.isTINGHU = function (shoupai,PGPai,chengju,geLeiCount,chairId) {
- let tpgs = 0;//提跑个数
- for (var i = 0; i < PGPai.length; i++) {
- if(PGPai[i].style == STYLE.ANGANG || PGPai[i].style == STYLE.ZMGANG || PGPai[i].style == STYLE.GANG){
- tpgs++;
- }
- }
- // console.warn("===================听胡 ",chairId,tpgs,this.everyCPGS);
- let cpgsyq = 0;//出牌个数要求
- if(this.chBanker == chairId) cpgsyq = 1;
- if(tpgs >= 2 || this.everyCPGS[chairId] > cpgsyq) return false;
- return true;
- };
- //是否 "红胡",
- proto.isHONGHU = function (shoupai,PGPai,chengju,geLeiCount) {
- if(geLeiCount[2] >= 10){
- this.hongHuCount = geLeiCount[2] - 10;
- return true;
- }
- return false;
- };
- //是否 "黑胡",
- proto.isHEIHU = function (shoupai,PGPai,chengju,geLeiCount) {
- return geLeiCount[2] == 0;
- };
- //是否 "点胡",
- proto.isDIANHU = function (shoupai,PGPai,chengju,geLeiCount) {
- return geLeiCount[2] == 1;
- };
- //是否 "大胡",
- proto.isDAHU = function (shoupai,PGPai,chengju,geLeiCount) {
- if(geLeiCount[0] >= 18){
- this.daHuCount = geLeiCount[0] - 18;
- return true;
- }
- return false;
- };
- //是否 "小胡",
- proto.isXIAOHU = function (shoupai,PGPai,chengju,geLeiCount) {
- if(geLeiCount[1] >= 16){
- this.xiaoHuCount = geLeiCount[1] - 16;
- return true;
- }
- return false;
- };
- //是否 "耍猴",
- proto.isSHUAHOU = function (shoupai,PGPai,chengju,geLeiCount,addcard) {
- // console.warn("------------------------ 耍猴 ",count ,sp,addcard,shoupai);
- let sp = [];
- for (var i = 0; i < shoupai.length; i++) {
- sp = sp.concat(shoupai[i])
- }
- return sp.length == 2 && sp[0] == addcard;
- };
- //是否 "黄番",
- proto.isHUANGFAN = function (shoupai,PGPai,chengju,geLeiCount,dengshuValue) {
- // console.warn("是否 黄番 ",dengshuValue);
- return this.dengshuValue > 0;
- };
- //是否 "对子胡",
- proto.isDUIZIHU = function (shoupai,PGPai,chengju,geLeiCount) {
- for (var i = 0; i < PGPai.length; i++) {
- let style = PGPai[i].style;
- if(style == STYLE.CHI || style == STYLE.SUN || style == STYLE.JIAO || style == STYLE.BIPAI) return false;
- }
- let dzgs = 0;//对子个数
- for (var i = 0; i < shoupai.length; i++) {
- for (var j = 0; j < shoupai[i].length; j++) {
- if(shoupai[i][0] != shoupai[i][j]) return false;
- }
- if(shoupai[i].length == 2 && shoupai[i][0] == shoupai[i][1]) dzgs++;
- }
- if(dzgs > 1) return false;
- return true;
- };
- //是否 "大团圆",
- proto.isDATUANYUAN = function (shoupai,PGPai,chengju,geLeiCount) {
- let gpzptgs = _.fill(Array(10), 0);//各牌值跑提个数
- for (var i = 0; i < PGPai.length; i++) {
- let style = PGPai[i].style;
- if(style == STYLE.GANG || style == STYLE.ANGANG || style == STYLE.ZMGANG){
- let pz = this.getValue(PGPai[i].card)%10;
- gpzptgs[pz]++;
- }
- }
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 4){//起手时闲家的三提五坎
- if(shoupai[i][0] == shoupai[i][1] && shoupai[i][0] == shoupai[i][2] && shoupai[i][0] == shoupai[i][3]) {
- let pz = this.getValue(shoupai[i][0])%10;
- gpzptgs[pz]++;
- }
- }
- }
- // return gpzptgs.indexOf(2) != -1;
- // console.warn("大团圆 ",JSON.stringify(PGPai),gpzptgs);
- for (var i = 0; i < gpzptgs.length; i++) {
- if(gpzptgs[i] == 2) this.datuanyuanCount++;
- }
- return this.datuanyuanCount > 0;
- };
- //是否 "真行息",
- proto.isZHENHANGXI = function (shoupai,PGPai,chengju,geLeiCount) {
- let wxgs = 0;//无息的列的个数
- for (var i = 0; i < PGPai.length; i++) {
- let style = PGPai[i].style;
- if(style == STYLE.GANG || style == STYLE.ANGANG || style == STYLE.ZMGANG) continue;
- if(style == STYLE.PENG || style == STYLE.WEI) continue;
- if(style == STYLE.CHI){
- let zgcdhxInfo = this.getCPHXInfo([PGPai[i]]);//这个吃的胡息信息
- if(zgcdhxInfo.hxValues[0] > 0) continue;
- }
- wxgs++
- if(wxgs>= 2) break;
- }
- if(wxgs>= 2) {
- this.wxdldgs = wxgs;//无息的列的个数,用来判断真假行息
- return false;
- }
- for (var i = 0; i < shoupai.length; i++) {
- let zlspcd = shoupai[i].length;
- let lie = [];//第i列的牌
- if(zlspcd == 3 || zlspcd == 4){
- // lie = _.cloneDeep(shoupai[i]);//第i列的牌
- lie = this.sort(shoupai[i]);
- }
- if(zlspcd <= 2){
- wxgs++;
- }
- else if(zlspcd == 3){
-
- if(lie[0] == lie[1] && lie[0] == lie[2]) continue;
- if(this.getValue(lie[0]) == 1 && lie[0] + 1 == lie[1] && lie[0]+2 == lie[2]) continue;
- if(this.getValue(lie[0]) == 2 && this.getValue(lie[1]) == 7 && this.getValue(lie[2]) == 10){
- if(this.getType(lie[0]) == this.getType(lie[1]) && this.getType(lie[0]) == this.getType(lie[2])) continue;
- }
- wxgs++;
- }
- else if(zlspcd == 4){
- if(lie[0] == lie[1] && lie[0] == lie[2] && lie[0] == lie[3]) continue;
- wxgs++;
- }
- if(wxgs>= 2) break;
- }
- this.wxdldgs = wxgs;//无息的列的个数,用来判断真假行息
- return this.wxdldgs == 0;
- };
- //是否 "假行息",
- proto.isJIAHANGXI = function (shoupai,PGPai,chengju,geLeiCount) {
- let jiang = 0;
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 2 && shoupai[i][0] == shoupai[i][1]) {
- jiang = shoupai[i][0];
- break;
- }
- }
- // console.warn("是否 假行息, ",this.wxdldgs , jiang);
- return this.wxdldgs == 1 && jiang;
- };
- //是否 "四七红",
- proto.isSIQIHONG = function (shoupai,PGPai,chengju,geLeiCount) {
- return geLeiCount[2] == 4 || geLeiCount[2] == 7;
- };
- //是否 "真背靠背",
- proto.isZHENBEIKAOBEI = function (shoupai,PGPai,chengju,geLeiCount,isMoHu) {
- // console.warn("真背靠背 shoupai,PGPai ",this.addThisIsHu,shoupai,PGPai);
- let jiang = 0;
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 2 && shoupai[i][0] == shoupai[i][1]) {
- if(jiang > 0) {
- // console.error("真背靠背判断出错了 ",JSON.stringify(shoupai));
- return false;
- }
- jiang = shoupai[i][0];
- }
- }
- // console.warn("真背靠背 jiang ",jiang)
- if(!jiang) return false;//没将
- let jiangV = this.getValue(jiang);
- if(jiangV != this.getValue(this.addThisIsHu)) return false;
- //自摸胡的话会先偎掉所以应该用碰杠牌判断,非自摸胡才会用手牌判断
- if(isMoHu){
- for (var i = 0; i < PGPai.length; i++) {
- if(PGPai[i].style == STYLE.WEI && PGPai[i].card == this.addThisIsHu) {
- this.isBeiKaoBei = true;//是否满足背靠背,用来判断真假背靠背
- }
- }
- }
- else{
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 3 && shoupai[i][0] == shoupai[i][1] && shoupai[i][0] == shoupai[i][2]) {
- if(jiangV == this.getValue(shoupai[i][0]) && this.addThisIsHu == shoupai[i][0]) {
- this.isBeiKaoBei = true;//是否满足背靠背,用来判断真假背靠背
- }
- }
- }
- }
- let spcount = 0;
- if(this.isBeiKaoBei){
- for (var i = 0; i < shoupai.length; i++) {
- spcount += shoupai[i].length;
- }
- }
- else{
- return false;
- }
- return (isMoHu && spcount == 2)|| (!isMoHu && spcount == 5);
- };
- //是否 "假背靠背",
- proto.isJIABEIKAOBEI = function (shoupai,PGPai,chengju,geLeiCount) {
- let spcount = 0;
- if(this.isBeiKaoBei){
- for (var i = 0; i < shoupai.length; i++) {
- spcount += shoupai[i].length;
- }
- }
- else{
- return false;
- }
- return spcount > 5;
- };
- //是否 "三提五坎",
- proto.isSANTIWUKAN = function (shoupai,PGPai,chengju,geLeiCount) {
- let tiKanGS = [0,0];//提和坎分别的个数
- for (var i = 0; i < PGPai.length; i++) {
- let style = PGPai[i].style;
- if(style == STYLE.ANGANG) tiKanGS[0]++;
- }
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 3){
- if(shoupai[i][0] == shoupai[i][1] && shoupai[i][0] == shoupai[i][2]) tiKanGS[1]++;
- }
- else if(shoupai[i].length == 4){//起手时闲家的三提五坎
- if(shoupai[i][0] == shoupai[i][1] && shoupai[i][0] == shoupai[i][2] && shoupai[i][0] == shoupai[i][3]) tiKanGS[0]++;
- }
- }
- // console.warn("是否 三提五坎, ",tiKanGS,shoupai,PGPai);
- return (tiKanGS[0] >= 3 || tiKanGS[1] >= 5 || (tiKanGS[0]+tiKanGS[1]) >= 5)
- };
- //是否 "金屋藏娇",
- proto.isJINWUCANGJIAO = function (shoupai,PGPai,chengju,geLeiCount,isMoHu) {
- let sffpjd = this.isFPJD();//是否发牌阶段
- // console.warn("金屋藏娇 shoupai,PGPai ",sffpjd,this.addThisIsHu,isMoHu,shoupai,PGPai);
- for (var i = 0; i < PGPai.length; i++) {
- if(PGPai[i].style == STYLE.ANGANG && PGPai[i].card == 103) return true;
- }
- if(sffpjd){//发牌阶段
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 4){//起手时闲家的三提五坎
- if(shoupai[i][0] == shoupai[i][1] && shoupai[i][0] == shoupai[i][2] && shoupai[i][0] == shoupai[i][3]){
- if(shoupai[i][0] == 103) {
- if(isMoHu) return true;
- else{
- if(this.addThisIsHu != 103) return true;
- }
- }
- }
- }
- }
- }
- return false;
- };
- //是否 "丁", 需要满足胡牌牌型
- proto.isDING = function (shoupai,PGPai,chengju,geLeiCount) {
- let jiang = 0;
- for (var i = 0; i < shoupai.length; i++) {
- if(shoupai[i].length == 2 && shoupai[i][0] == shoupai[i][1]) {
- if(jiang > 0) {
- console.error("丁判断出错了 ",JSON.stringify(shoupai));
- return false;
- }
- jiang = shoupai[i][0];
- }
- }
- return this.addThisIsHu == jiang;
- };
- //是否 "捉小三",
- proto.isZHUOXIAOSAN = function (shoupai,PGPai,chengju,geLeiCount,isMoHu) {
- // console.warn("捉小三 ",this.addThisIsHu , isMoHu);
- return (this.addThisIsHu == 103 && isMoHu);//////TL++,胡牌判断时加上这张能不能胡
- };
|