1090 lines
28 KiB
JavaScript
1090 lines
28 KiB
JavaScript
///////////////////////////////////////////////////
|
|
////////// cls_youle_erqiwang_arith: 算法 /////////
|
|
///////////////////////////////////////////////////
|
|
var cls_youle_erqiwang_arith = cls_youle_erqiwang_arith || {
|
|
|
|
//根据叫分计算倍数
|
|
get_multiple_bycall: function(callgrade){
|
|
if (callgrade > 60){
|
|
return 1;
|
|
}
|
|
if (callgrade > 40){
|
|
return 2;
|
|
}
|
|
if (callgrade > 0){
|
|
return 4;
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
//牌id转花色
|
|
id_to_flower: function(cardid){
|
|
if (cardid == 52 || cardid == 106){
|
|
//小王
|
|
return 5;
|
|
}
|
|
if (cardid == 53 || cardid == 107){
|
|
//大王
|
|
return 5;
|
|
}
|
|
return parseInt((cardid % 54) / 13) + 1;
|
|
},
|
|
|
|
//牌id转牌面数值
|
|
id_to_number: function(cardid){
|
|
if (cardid == 52 || cardid == 106){
|
|
//小王
|
|
return 53;
|
|
}
|
|
if (cardid == 53 || cardid == 107){
|
|
//大王
|
|
return 54;
|
|
}
|
|
return (cardid % 54) % 13 + 1;
|
|
},
|
|
|
|
//牌id转牌编码
|
|
id_to_code: function(mainflower, cardid){
|
|
if (cardid == 52 || cardid == 106){
|
|
//小王
|
|
return 9553;
|
|
}
|
|
if (cardid == 53 || cardid == 107){
|
|
//大王
|
|
return 9554;
|
|
}
|
|
var flower = cls_youle_erqiwang_arith.id_to_flower(cardid);
|
|
var number = cls_youle_erqiwang_arith.id_to_number(cardid);
|
|
var code = flower * 100 + number;
|
|
//特殊处理
|
|
switch (number)
|
|
{
|
|
case 1:
|
|
code = code + 13;
|
|
break;
|
|
case 2:
|
|
code = code + 2000;
|
|
break;
|
|
case 7:
|
|
code = code + 7000;
|
|
break;
|
|
}
|
|
//主牌花色处理
|
|
if (flower == mainflower){
|
|
code = code + 1000;
|
|
}
|
|
return code;
|
|
},
|
|
|
|
//从大到小排序(冒泡排序)
|
|
order_cards: function(mainflower, aryCardIDs){
|
|
if (aryCardIDs){
|
|
for (var i = 0; i < aryCardIDs.length; i++) {
|
|
for (var j = i + 1; j < aryCardIDs.length; j++) {
|
|
var i_code = cls_youle_erqiwang_arith.id_to_code(mainflower, aryCardIDs[i]);
|
|
var j_code = cls_youle_erqiwang_arith.id_to_code(mainflower, aryCardIDs[j]);
|
|
if (i_code < j_code) {
|
|
var tmp = aryCardIDs[j];
|
|
aryCardIDs[j] = aryCardIDs[i];
|
|
aryCardIDs[i] = tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return aryCardIDs;
|
|
},
|
|
|
|
//判断两个牌是否是连续的
|
|
is_continuous: function(bigcode, smallcode){
|
|
//是小王
|
|
var is_xiaowang = function(_code){
|
|
if (_code == 9553){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是正7
|
|
var is_zheng7 = function(_code){
|
|
if (_code > 8000 && _code < 9000){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是负7
|
|
var is_fu7 = function(_code){
|
|
if (_code > 7000 && _code < 8000){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是正2
|
|
var is_zheng2 = function(_code){
|
|
if (_code > 3000 && _code < 4000){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是负2
|
|
var is_fu2 = function(_code){
|
|
if (_code > 2000 && _code < 3000){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是主A
|
|
var is_zhuA = function(_code){
|
|
if (_code > 1000 && _code < 2000 && _code % 100 == 14){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是8
|
|
var is_8 = function(_code){
|
|
if (_code % 100 == 8){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//是6
|
|
var is_6 = function(_code){
|
|
if (_code % 100 == 6){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//普通的连牌
|
|
if (bigcode - smallcode == 1){
|
|
return true;
|
|
}
|
|
//小王、正7
|
|
if (is_xiaowang(bigcode) && is_zheng7(smallcode)){
|
|
return true;
|
|
}
|
|
//正7、负7
|
|
if (is_zheng7(bigcode) && is_fu7(smallcode)){
|
|
return true;
|
|
}
|
|
//负7、正2
|
|
if (is_fu7(bigcode) && is_zheng2(smallcode)){
|
|
return true;
|
|
}
|
|
//正2、负2
|
|
if (is_zheng2(bigcode) && is_fu2(smallcode)){
|
|
return true;
|
|
}
|
|
//负2、主A
|
|
if (is_fu2(bigcode) && is_zhuA(smallcode)){
|
|
return true;
|
|
}
|
|
//8、6
|
|
if (is_8(bigcode) && is_6(smallcode)){
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
//获取对子列表,cards为同一花色的排过序的牌列表
|
|
get_pairlist: function(mainflower, flowercards){
|
|
var pairlist = [];
|
|
var i = 0;
|
|
while (i < flowercards.length - 1){
|
|
//牌编码,两张牌两张牌一取
|
|
var code_i = cls_youle_erqiwang_arith.id_to_code(mainflower, flowercards[i]);
|
|
var code_j = cls_youle_erqiwang_arith.id_to_code(mainflower, flowercards[i + 1]);
|
|
if (code_i == code_j){
|
|
pairlist.push([flowercards[i], flowercards[i + 1]]);
|
|
i = i + 2;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
return pairlist;
|
|
},
|
|
|
|
//获取拖拉机列表,pairlist为同一花色的排过序的对子列表,cardtype为拖拉机牌型
|
|
get_tuolaji_list: function(mainflower, pairlist, cardtype){
|
|
var tuolaji = [];
|
|
var count = cardtype - 300; //拖拉机的对子数量
|
|
var i = 0;
|
|
for (var i = 0; i < pairlist.length - count + 1; i++){
|
|
//每次按拖拉机的对子数量取N对
|
|
var tmplist = pairlist.slice(i, i + count);
|
|
//判断是否是cardtype类型的拖拉机
|
|
var is_tlj = true;
|
|
for (var j = 0; j < tmplist.length - 1; j++) {
|
|
var code_j1 = cls_youle_erqiwang_arith.id_to_code(mainflower, tmplist[j][0]);
|
|
var code_j2 = cls_youle_erqiwang_arith.id_to_code(mainflower, tmplist[j+1][0]);
|
|
if (!cls_youle_erqiwang_arith.is_continuous(code_j1, code_j2)){
|
|
is_tlj = false;
|
|
break;
|
|
}
|
|
}
|
|
if (is_tlj){
|
|
var tlj = [];
|
|
for (var k = 0; k < tmplist.length; k++){
|
|
tlj = tlj.concat(tmplist[k]);
|
|
}
|
|
tuolaji.push(tlj);
|
|
}
|
|
}
|
|
return tuolaji;
|
|
},
|
|
|
|
//第一个位置是否可出牌
|
|
can_playcard: function(mainflower, cards, selfseat, seatlist){
|
|
/*
|
|
参数:
|
|
mainflower: 主牌花色
|
|
cards : 要出的牌id列表
|
|
selfseat : 出牌者的位置
|
|
seatlist : 座位列表,四维数组,
|
|
[ //第一层表示玩家,与位置序号对应
|
|
[ //第二层表示花色,与花色-1对应
|
|
[
|
|
0, //无该花色的牌标志
|
|
0 //该花色无对标志
|
|
], [0, 0], [0, 0], [0, 0]
|
|
],
|
|
[[0, 0], [0, 0], [0, 0], [0, 0]],
|
|
[[0, 0], [0, 0], [0, 0], [0, 0]]
|
|
]
|
|
返回结果json:
|
|
result : true可出,false不可出
|
|
flower : 花色,result=false时无此属性,下同
|
|
cardtype : 牌型
|
|
cardvalue: 牌型值,取满足牌型的最小牌的牌编码
|
|
*/
|
|
|
|
//返回的结果
|
|
var can = {};
|
|
can.result = true;
|
|
can.flower = null;
|
|
can.cardtype = null;
|
|
can.cardvalue = null;
|
|
|
|
//返回不能出牌的结果
|
|
var do_returnfalse = function(){
|
|
can.result = false;
|
|
delete can.flower;
|
|
delete can.cardtype;
|
|
delete can.cardvalue;
|
|
}
|
|
|
|
//规则外的约定,一次最多只能出14张牌
|
|
if (cards.length > 14){
|
|
do_returnfalse;
|
|
return can;
|
|
}
|
|
|
|
/////////// 计算牌型 ///////////
|
|
//将牌从大到小排序
|
|
cards = cls_youle_erqiwang_arith.order_cards(mainflower, cards);
|
|
var i = 0;
|
|
while (i < cards.length){
|
|
//牌编码
|
|
var code = cls_youle_erqiwang_arith.id_to_code(mainflower, cards[i]);
|
|
//牌的花色
|
|
var flower = parseInt(code / 100);
|
|
if (code > 1000){ //大于1000是主牌
|
|
flower = mainflower;
|
|
}
|
|
|
|
//是第一张牌
|
|
if (i == 0){
|
|
can.flower = flower;
|
|
can.cardtype = 101;
|
|
can.cardvalue = code;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
//不是第一张牌
|
|
//花色必须一致
|
|
if (flower != can.flower){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
|
|
//之前是单张牌型
|
|
if (can.cardtype > 100 && can.cardtype < 200){
|
|
if (can.cardtype == 101 && code == can.cardvalue){
|
|
can.cardtype = 201; //是一对
|
|
} else {
|
|
can.cardtype = can.cardtype + 1; //单张甩牌
|
|
can.cardvalue = code;
|
|
}
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
//之前是对子或拖拉机牌型,则两张两张牌一取
|
|
//如果是最后一张牌,取不到后面一张牌了
|
|
if (i == cards.length - 1){
|
|
can.cardtype = 100 + i + 1; //单张甩牌
|
|
can.cardvalue = code;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
//后面一张牌的编码
|
|
var code_2 = cls_youle_erqiwang_arith.id_to_code(mainflower, cards[i + 1]);
|
|
//后面一张牌的花色
|
|
var flower_2 = parseInt(code_2 / 100);
|
|
if (code_2 > 1000){ //大于1000是主牌
|
|
flower_2 = mainflower;
|
|
}
|
|
//后面一张牌的花色必须一致
|
|
if (flower_2 != flower){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
|
|
//当前两张牌不是对子
|
|
if (code_2 != code){
|
|
can.cardtype = 100 + i + 2; //单张甩牌
|
|
can.cardvalue = code_2;
|
|
i = i + 2;
|
|
continue;
|
|
}
|
|
|
|
//当前两张牌是对子
|
|
//之前是对子牌型
|
|
if (can.cardtype > 200 && can.cardtype < 300){
|
|
if (can.cardtype == 201 && cls_youle_erqiwang_arith.is_continuous(can.cardvalue, code)){
|
|
//之前是一对,且现在是连牌,则是拖拉机
|
|
can.cardtype = 302;
|
|
can.cardvalue = code;
|
|
} else {
|
|
//是多对
|
|
can.cardtype = can.cardtype + 1; //多对甩牌
|
|
can.cardvalue = code;
|
|
}
|
|
i = i + 2;
|
|
continue;
|
|
}
|
|
|
|
//之前是拖拉机牌型
|
|
if (can.cardtype > 300 && can.cardtype < 400){
|
|
if (cls_youle_erqiwang_arith.is_continuous(can.cardvalue, code)){
|
|
//现在是连牌,则还是拖拉机
|
|
can.cardtype = can.cardtype + 1;
|
|
can.cardvalue = code;
|
|
} else {
|
|
//是多对
|
|
can.cardtype = 200 + can.cardtype % 100 + 1; //多对甩牌
|
|
can.cardvalue = code;
|
|
}
|
|
i = i + 2;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/////////// 甩牌处理 ///////////
|
|
//其他玩家没有主牌
|
|
var other_noflower = function(_flower){
|
|
for (var i = 0; i < seatlist.length; i++){
|
|
if (i != selfseat){
|
|
if (seatlist[i][_flower - 1][0] == 0){
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//其他玩家没有主对
|
|
var other_noflowerpair = function(_flower){
|
|
for (var i = 0; i < seatlist.length; i++){
|
|
if (i != selfseat){
|
|
if (seatlist[i][_flower - 1][1] == 0){
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//不可甩牌判断
|
|
if (can.cardtype > 101 && can.cardtype < 200){ //单张甩牌
|
|
//其他玩家有主牌则不能甩牌
|
|
if (!other_noflower(mainflower)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
//副牌甩牌需要满足其他玩家没有主牌且其他玩家都没有该花色的牌
|
|
if (!other_noflower(can.flower)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
} else if (can.cardtype > 201 && can.cardtype < 300){ //对子甩牌
|
|
if (can.flower == mainflower){ //甩主对
|
|
//其他玩家有主牌对子则不能甩牌
|
|
if (!other_noflowerpair(mainflower)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
} else { //甩副牌对子
|
|
//其他玩家有主牌则不能甩牌
|
|
if (!other_noflower(mainflower)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
//副牌甩牌需要其他玩家没有主牌且其他玩家没有该花色的对子
|
|
if (!other_noflowerpair(can.flower)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
}
|
|
}
|
|
|
|
return can;
|
|
},
|
|
|
|
//根据第一个玩家的出牌获取后面玩家必出的和可出的牌
|
|
get_followcard: function(mainflower, inhandcards, startcount, startflower, startcardtype){
|
|
/*
|
|
参数:
|
|
mainflower : 主牌花色
|
|
inhandcards : 手上的牌id列表
|
|
startcount : 第一个玩家出牌的数量
|
|
startflower : 第一个玩家出牌的牌花色
|
|
startcardtype: 第一个玩家出牌的牌型
|
|
返回结果json:
|
|
mustcard: 必出的牌列表
|
|
cancard : 可出的牌列表
|
|
cantype : 可出的牌中需要的牌型
|
|
*/
|
|
//返回的结果
|
|
var re = {};
|
|
re.mustcard = [];
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
|
|
//拷贝数组
|
|
var _inhandcards = inhandcards.concat();
|
|
//将牌从大到小排序
|
|
_inhandcards = cls_youle_erqiwang_arith.order_cards(mainflower, _inhandcards);
|
|
|
|
//如果手上的牌数量与要求的出牌数量一样则全是必出的牌
|
|
if (_inhandcards.length == startcount){
|
|
re.mustcard = _inhandcards;
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
|
|
//获取相同花色的牌与其他花色的牌
|
|
var _startflowercards = []; //相同花色的牌
|
|
var _otherflowercards = []; //其他花色的牌
|
|
for (var i = 0; i < _inhandcards.length; i++){
|
|
//牌编码
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, _inhandcards[i]);
|
|
//牌的花色
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){ //大于1000是主牌
|
|
_flower = mainflower;
|
|
}
|
|
if (_flower == startflower){
|
|
_startflowercards.push(_inhandcards[i]);
|
|
} else {
|
|
_otherflowercards.push(_inhandcards[i]);
|
|
}
|
|
}
|
|
|
|
//如果没有相同花色的牌,则全部为可出的牌
|
|
if (_startflowercards.length == 0){
|
|
re.mustcard = [];
|
|
re.cancard = _inhandcards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
}
|
|
|
|
//如果相同花色的牌数量不够,则相同花色的牌为必出的牌,其他花色为可出的牌
|
|
if (_startflowercards.length < startcount){
|
|
re.mustcard = _startflowercards;
|
|
re.cancard = _otherflowercards;
|
|
re.cantype = 100 + startcount - re.mustcard.length;
|
|
return re;
|
|
}
|
|
|
|
//如果相同花色的牌数量与要求的出牌数量一样则全是必出的牌,没有可出的牌
|
|
if (_startflowercards.length == startcount){
|
|
re.mustcard = _startflowercards;
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
|
|
//如果相同花色的牌数量大于要求的出牌数量
|
|
if (startcardtype == 101){
|
|
//一张单张
|
|
re.mustcard = [];
|
|
re.cancard = _startflowercards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
} else if (startcardtype > 101 && startcardtype < 200){
|
|
//多张单张
|
|
re.mustcard = [];
|
|
re.cancard = _startflowercards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
} else if (startcardtype == 201){
|
|
//一对
|
|
//获取对子列表
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, _startflowercards);
|
|
//没有对子
|
|
if (pairlist.length == 0){
|
|
re.mustcard = [];
|
|
re.cancard = _startflowercards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
}
|
|
//只有一对
|
|
if (pairlist.length == 1){
|
|
re.mustcard = pairlist[0];
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
//有多对
|
|
re.mustcard = [];
|
|
for (var i = 0; i < pairlist.length; i++){
|
|
re.cancard = re.cancard.concat(pairlist[i]);
|
|
}
|
|
re.cantype = 201;
|
|
return re;
|
|
} else if (startcardtype > 201 && startcardtype < 300){
|
|
//多对
|
|
re.mustcard = [];
|
|
re.cancard = _startflowercards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
} else if (startcardtype > 300 && startcardtype < 400){
|
|
//拖拉机
|
|
//获取对子列表
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, _startflowercards);
|
|
|
|
//没有对子
|
|
if (pairlist.length == 0){
|
|
re.mustcard = [];
|
|
re.cancard = _startflowercards;
|
|
re.cantype = 100 + startcount;
|
|
return re;
|
|
}
|
|
|
|
//对子数量不够
|
|
if (pairlist.length * 2 < startcount){
|
|
for (var i = 0; i < pairlist.length; i++){
|
|
re.mustcard = re.mustcard.concat(pairlist[i]);
|
|
}
|
|
re.cancard = min_ary_deduct(_startflowercards, re.mustcard);
|
|
re.cantype = 100 + startcount - re.mustcard.length;
|
|
return re;
|
|
}
|
|
|
|
//对子数量刚好够
|
|
if (pairlist.length * 2 == startcount){
|
|
for (var i = 0; i < pairlist.length; i++){
|
|
re.mustcard = re.mustcard.concat(pairlist[i]);
|
|
}
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
|
|
//对子有多
|
|
//拖拉机列表
|
|
var tuolaji_list = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, pairlist, startcardtype);
|
|
|
|
//有多个符合条件的拖拉机
|
|
if (tuolaji_list.length > 1){
|
|
re.mustcard = [];
|
|
re.cancard = [];
|
|
//这里要去重复项
|
|
for (var i = 0; i < tuolaji_list.length; i++){
|
|
for (var j = 0; j < tuolaji_list[i].length; j++) {
|
|
var found = false;
|
|
for (var k = 0; k < re.cancard.length; k++){
|
|
if (re.cancard[k] == tuolaji_list[i][j]){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found){
|
|
re.cancard.push(tuolaji_list[i][j]);
|
|
}
|
|
}
|
|
}
|
|
re.cantype = startcardtype;
|
|
return re;
|
|
}
|
|
|
|
//只有一个符合条件的拖拉机
|
|
if (tuolaji_list.length == 1){
|
|
re.mustcard = tuolaji_list[0];
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
|
|
//没有符合条件的拖拉机
|
|
if (tuolaji_list.length == 0){
|
|
re.mustcard = [];
|
|
for (var i = 0; i < pairlist.length; i++){
|
|
re.cancard = re.cancard.concat(pairlist[i]);
|
|
}
|
|
re.cantype = startcardtype - 100;
|
|
//如果是连两对拖拉机
|
|
if (startcardtype == 302){
|
|
return re;
|
|
}
|
|
|
|
//如果是3连对及以上的拖拉机则降低拖拉机的规格再继续找
|
|
var tlj_type = startcardtype; //需要的牌型
|
|
var tlj_find = startcardtype - 1; //当前查找的牌型
|
|
//再继续找
|
|
while (tlj_type >= 302 && tlj_find >= 302){
|
|
var tlj_list = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, pairlist, tlj_find);
|
|
if (tlj_list.length == 1){
|
|
//找到一个
|
|
re.mustcard = re.mustcard.concat(tlj_list[0]);
|
|
re.cantype = re.cantype - (tlj_find - 100) + 200;
|
|
if (re.cantype < 201){
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
re.cancard = min_ary_deduct(re.cancard, tlj_list[0]);
|
|
//删除对子列表
|
|
i = 0;
|
|
while (i < pairlist.length){
|
|
if (min_ary_include(tlj_list[0], pairlist[i])){
|
|
pairlist.splice(i, 1);
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
tlj_type = (tlj_type - tlj_find) + 300;
|
|
continue;
|
|
}
|
|
|
|
if (tlj_list.length > 1){
|
|
//找到多个
|
|
if ((tlj_find - 300) * tlj_list.length <= (tlj_type - 300)){
|
|
re.mustcard = re.mustcard.concat(tlj_list[0]);
|
|
re.cantype = re.cantype - (tlj_find - 100) + 200;
|
|
if (re.cantype < 201){
|
|
re.cancard = [];
|
|
re.cantype = null;
|
|
return re;
|
|
}
|
|
re.cancard = min_ary_deduct(re.cancard, tlj_list[0]);
|
|
//删除对子列表
|
|
i = 0;
|
|
while (i < pairlist.length){
|
|
if (min_ary_include(tlj_list[0], pairlist[i])){
|
|
pairlist.splice(i, 1);
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
tlj_type = (tlj_type - tlj_find) + 300;
|
|
continue;
|
|
} else {
|
|
return re;
|
|
}
|
|
}
|
|
tlj_find = tlj_find - 1;
|
|
}
|
|
return re;
|
|
}
|
|
}
|
|
},
|
|
|
|
//第二、三个位置是否可跟牌
|
|
can_followcard: function(mainflower, inhandcards, followcards, startcount, startflower, startcardtype){
|
|
/*
|
|
参数:
|
|
mainflower : 主牌花色
|
|
inhandcards : 手上的牌id列表
|
|
followcards : 要跟的牌id列表
|
|
startcount : 第一个玩家出牌的数量
|
|
startflower : 第一个玩家出牌的牌花色
|
|
startcardtype: 第一个玩家出牌的牌型
|
|
返回结果json:
|
|
result : true可跟,false不可跟
|
|
cardvalue: 满足第一个玩家出牌的牌型值
|
|
noflower : 出牌后没有了第一个玩家出牌花色的牌标志
|
|
nopair : 出牌后没有了第一个玩家出牌花色的对子标志
|
|
*/
|
|
|
|
//返回的结果
|
|
var can = {};
|
|
can.result = true;
|
|
can.cardvalue = null;
|
|
can.noflower = false;
|
|
can.nopair = false;
|
|
|
|
//返回不能出牌的结果
|
|
var do_returnfalse = function(){
|
|
can.result = false;
|
|
delete can.cardvalue;
|
|
delete can.noflower;
|
|
delete can.nopair;
|
|
}
|
|
|
|
//牌的数量必须相等
|
|
if (followcards.length != startcount){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
|
|
//拷贝数组
|
|
var _inhandcards = inhandcards.concat();
|
|
var _followcards = followcards.concat();
|
|
|
|
//将牌从大到小排序
|
|
_inhandcards = cls_youle_erqiwang_arith.order_cards(mainflower, _inhandcards);
|
|
_followcards = cls_youle_erqiwang_arith.order_cards(mainflower, _followcards);
|
|
|
|
//根据第一个玩家的出牌获取后面玩家必出的和可出的牌
|
|
var get = cls_youle_erqiwang_arith.get_followcard(mainflower, _inhandcards, startcount, startflower, startcardtype);
|
|
|
|
////////// 判断是否可跟牌 ///////////
|
|
//如果有必出的牌则必须包含必出的牌
|
|
if (get.mustcard.length > 0){
|
|
if (!min_ary_include(_followcards, get.mustcard)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
//除去必出的牌还要出的牌
|
|
_followcards = min_ary_deduct(_followcards, get.mustcard);
|
|
}
|
|
|
|
if (_followcards.length > 0){
|
|
//必须在可出的牌里面
|
|
if (!min_ary_include(get.cancard, _followcards)){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
|
|
//必须满足需要的牌型
|
|
if (get.cantype > 100 && get.cantype < 200){
|
|
//单张牌型
|
|
//牌数量要正确
|
|
if (_followcards.length != get.cantype - 100){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
} else if (get.cantype > 200 && get.cantype < 300){
|
|
//对子牌型
|
|
//牌数量要正确
|
|
if (_followcards.length != (get.cantype - 200) * 2){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
//对子数量要正确
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, _followcards);
|
|
if (pairlist.length != get.cantype - 200){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
} else if (get.cantype > 300 && get.cantype < 400){
|
|
//拖拉机牌型
|
|
//牌数量要正确
|
|
if (_followcards.length != (get.cantype - 300) * 2){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
//要是正确的拖拉机牌型
|
|
if (tuolaji_list.length == 0){
|
|
do_returnfalse();
|
|
return can;
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////// 可以跟牌 ///////////
|
|
//根据跟牌情况获取是否有相同花色的牌,是否有对子
|
|
//如果第一张牌的花色与第一家的出牌花色不一样则认为没有了相同花色的牌
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, followcards[0]);
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){
|
|
_flower = mainflower;
|
|
}
|
|
if (_flower != startflower){
|
|
can.noflower = true;
|
|
can.nopair = true;
|
|
}
|
|
//如果最后一张牌的花色与第一家的出牌花色不一样则认为没有了相同花色的牌
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, followcards[followcards.length - 1]);
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){
|
|
_flower = mainflower;
|
|
}
|
|
if (_flower != startflower){
|
|
can.noflower = true;
|
|
can.nopair = true;
|
|
}
|
|
//如果第一家出的是对子或拖拉机牌型,而跟牌没有出对子则认为没有相同花色的对子
|
|
if (startcardtype > 200){
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, followcards);
|
|
if (pairlist.length != startcardtype % 100){
|
|
can.nopair = true;
|
|
}
|
|
}
|
|
|
|
//根据第一家的出牌计算牌值大小
|
|
//一张单张
|
|
if (startcardtype == 101){
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, followcards[0]);
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){ //大于1000是主牌
|
|
_flower = mainflower;
|
|
}
|
|
|
|
if (_flower == startflower || _flower == mainflower){
|
|
if (_code > 7000 && _code < 8000){ //副7
|
|
can.cardvalue = 7000;
|
|
} else if (_code > 2000 && _code < 3000){ //副2
|
|
can.cardvalue = 2000;
|
|
} else {
|
|
can.cardvalue = _code;
|
|
}
|
|
} else {
|
|
can.cardvalue = 0;
|
|
}
|
|
return can;
|
|
}
|
|
|
|
//甩多张单张
|
|
if (startcardtype > 101 && startcardtype < 200){
|
|
//第一个玩家是甩牌,则跟牌一定没有第一家玩家的牌大
|
|
can.cardvalue = 0;
|
|
return can;
|
|
}
|
|
|
|
//一对
|
|
if (startcardtype == 201){
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, followcards);
|
|
if (pairlist.length != 1){
|
|
can.cardvalue = 0;
|
|
return can;
|
|
}
|
|
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, followcards[0]);
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){
|
|
_flower = mainflower;
|
|
}
|
|
if (_flower == startflower || _flower == mainflower){
|
|
if (_code > 7000 && _code < 8000){ //副7
|
|
can.cardvalue = 7000;
|
|
} else if (_code > 2000 && _code < 3000){ //副2
|
|
can.cardvalue = 2000;
|
|
} else {
|
|
can.cardvalue = _code;
|
|
}
|
|
} else {
|
|
can.cardvalue = 0;
|
|
}
|
|
return can;
|
|
}
|
|
|
|
//甩多对
|
|
if (startcardtype > 201 && startcardtype < 300){
|
|
//第一个玩家是甩牌,则跟牌一定没有第一家玩家的牌大
|
|
can.cardvalue = 0;
|
|
return can;
|
|
}
|
|
|
|
//拖拉机
|
|
if (startcardtype > 300 && startcardtype < 400){
|
|
var pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, followcards);
|
|
var tuolaji_list = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, pairlist, startcardtype);
|
|
if (tuolaji_list.length != 1){
|
|
can.cardvalue = 0;
|
|
return can;
|
|
}
|
|
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, followcards[0]);
|
|
var _flower = parseInt(_code / 100);
|
|
if (_code > 1000){
|
|
_flower = mainflower;
|
|
}
|
|
if (_flower == startflower || _flower == mainflower){
|
|
can.cardvalue = _code;
|
|
} else {
|
|
can.cardvalue = 0;
|
|
}
|
|
return can;
|
|
}
|
|
},
|
|
|
|
//闲家抠底倍数
|
|
get_bottom_multiple: function(mainflower, cards){
|
|
//拷贝数组
|
|
var _cards = cards.concat();
|
|
//将牌从大到小排序
|
|
_cards = cls_youle_erqiwang_arith.order_cards(mainflower, _cards);
|
|
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, _cards[0]);
|
|
if (_code < 1000){
|
|
return 0;
|
|
}
|
|
var _code = cls_youle_erqiwang_arith.id_to_code(mainflower, _cards[_cards.length - 1]);
|
|
if (_code < 1000){
|
|
return 0;
|
|
}
|
|
|
|
var _pairlist = cls_youle_erqiwang_arith.get_pairlist(mainflower, _cards);
|
|
if (_pairlist.length == 0){
|
|
return 2;
|
|
}
|
|
|
|
var _tljlist = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, _pairlist, 302);
|
|
if (_tljlist.length == 0){
|
|
return 4;
|
|
}
|
|
|
|
var _tljlist = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, _pairlist, 303);
|
|
if (_tljlist.length == 0){
|
|
return 8;
|
|
}
|
|
|
|
var _tljlist = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, _pairlist, 304);
|
|
if (_tljlist.length == 0){
|
|
return 16;
|
|
}
|
|
|
|
var _tljlist = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, _pairlist, 305);
|
|
if (_tljlist.length == 0){
|
|
return 32;
|
|
}
|
|
|
|
var _tljlist = cls_youle_erqiwang_arith.get_tuolaji_list(mainflower, _pairlist, 306);
|
|
if (_tljlist.length == 0){
|
|
return 64;
|
|
}
|
|
},
|
|
|
|
//冲关计算关数
|
|
get_chongguan: function(mainflower, cards){
|
|
var re = {};
|
|
re.count = 0; //关数
|
|
re.wang = 0; //王牌数量
|
|
re.cards = []; //王牌和冲关的牌
|
|
if (cards.length < 28){
|
|
return re;
|
|
}
|
|
|
|
//拷贝数组
|
|
var _cards = cards.concat();
|
|
//将牌从大到小排序
|
|
_cards = cls_youle_erqiwang_arith.order_cards(mainflower, _cards);
|
|
|
|
var _wlist = []; //王
|
|
var _2list = []; //2
|
|
var _7list = []; //7
|
|
var _incards = []; //是否添加得到了re.cards标志
|
|
for (var i = 0; i < _cards.length; i++) {
|
|
var _number = cls_youle_erqiwang_arith.id_to_number(_cards[i]);
|
|
if (_number >= 53){
|
|
_wlist.push(i);
|
|
re.wang = re.wang + 1;
|
|
re.cards.push(_cards[i]);
|
|
} else if (_number == 2){
|
|
_2list.push(i);
|
|
} else if (_number == 7){
|
|
_7list.push(i);
|
|
}
|
|
_incards.push(0);
|
|
}
|
|
|
|
//添加到re.cards
|
|
var do_addlisttocards = function(_list){
|
|
for (var i = 0; i < _list.length; i++){
|
|
if (!_incards[_list[i]]){
|
|
re.cards.push(_cards[_list[i]]);
|
|
_incards[_list[i]] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//三王四王冲关判断
|
|
if (_wlist.length >= 3){
|
|
re.count = 1;
|
|
var _code = 9553; //当前的牌编码
|
|
var i = 3; //后面查找的起始位置
|
|
if (_wlist.length == 4){
|
|
re.count = 3;
|
|
i = 4;
|
|
}
|
|
//往后查找,看是否还有冲关
|
|
while (i < _cards.length - 1){
|
|
//牌编码,两张牌两张牌一取
|
|
var code_i = cls_youle_erqiwang_arith.id_to_code(mainflower, _cards[i]);
|
|
var code_j = cls_youle_erqiwang_arith.id_to_code(mainflower, _cards[i + 1]);
|
|
if (code_i == code_j){
|
|
if (cls_youle_erqiwang_arith.is_continuous(_code, code_i)){
|
|
re.count = re.count + 1;
|
|
re.cards.push(_cards[i]);
|
|
re.cards.push(_cards[i + 1]);
|
|
_incards[i] = 1;
|
|
_incards[i + 1] = 1;
|
|
_code = code_i;
|
|
}
|
|
i = i + 2;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//六2六7判断
|
|
if (_7list.length >= 6){
|
|
re.count = re.count + _7list.length - 5;
|
|
do_addlisttocards(_7list);
|
|
}
|
|
if (_2list.length >= 6){
|
|
re.count = re.count + _2list.length - 5;
|
|
do_addlisttocards(_2list);
|
|
}
|
|
|
|
//10个老主判断
|
|
var _total = _wlist.length + _7list.length + _2list.length;
|
|
if (_total >= 10){
|
|
re.count = re.count + _total - 9;
|
|
do_addlisttocards(_7list);
|
|
do_addlisttocards(_2list);
|
|
}
|
|
|
|
re.cards = cls_youle_erqiwang_arith.order_cards(mainflower, re.cards);
|
|
return re;
|
|
},
|
|
|
|
//计算升级级数
|
|
get_upgrade: function(call, grade){
|
|
//叫分的一半
|
|
var _halfcall;
|
|
if (call % 2 == 0){
|
|
_halfcall = call / 2;
|
|
} else {
|
|
_halfcall = (call + 5) / 2;
|
|
}
|
|
|
|
if (grade == 0){
|
|
return 4;
|
|
}
|
|
if (grade < _halfcall){
|
|
return 2;
|
|
}
|
|
if (grade < call){
|
|
return 1;
|
|
}
|
|
return -1 * (parseInt((grade - call) / _halfcall) + 1);
|
|
}
|
|
}
|
|
|