Skip to content

Instantly share code, notes, and snippets.

@cuixiping
Last active August 29, 2015 13:57
Show Gist options
  • Save cuixiping/9745564 to your computer and use it in GitHub Desktop.
Save cuixiping/9745564 to your computer and use it in GitHub Desktop.
checkSequence 检测一组牌里有没有顺子
//这个是一组的,大城小胖是两组,那就先concat合并数组再传进来即可检测
function checkSequence(cards){
var B=[0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768];
var found = false, i, n = cards.length;
var sum = 0, queueSum = [], queueSumDic = {}, specials = {1:0, 14:0, 15:0};
while((i=cards.pop())){
(i in specials) ? (specials[i]++) : (sum |= B[i]);
} //#1
function appendSum(sum){ //存入一手牌
if(!queueSumDic[sum]) {
if(sum.toString(2).indexOf('11111')>=0){
found=true;
}
queueSum.push(sum);
queueSumDic[sum]=true;
}
}
function insertCard(sum,vArr){ //一手牌,再插入一张
for(var t=false,i=vArr.length-1; !found && i>=0; i--){
if(!(B[vArr[i]] & sum)){
appendSum(sum | B[vArr[i]]);
t = true;
}
}
return t;
}
function insertCards(sum,vArr,count){ //一手牌,再插入N张
while(!found && count-- && insertCard(sum,vArr)){}
}
function insertCardsAll(vArr,count){ //M手牌,再插入N张
for(var i=queueSum.length-1; !found && i>=0; i--){
insertCards(queueSum[i],vArr,count);
}
}
appendSum(sum); //未填充A和王
insertCardsAll([1,14],specials[1]); //填充A
insertCardsAll([1,2,3,4,5],specials[14]); //填充小王1-5
insertCardsAll([1,2,3,4,5,6,7,8,9,10,11,12,13,14],specials[15]); //填充大王1-14
return found;
}
//检测一组牌是不是顺子,每张都要用且只用一次。
//这里是检测用的核心函数,和小胖的形式上略有差别
//测试页面:http://cuixiping.github.io/test/checkSequence/checkSequence.html
//大城小胖的gist: https://gist.github.com/finscn/9744730
function checkSequence(cards){ //入口,传入牌值数组,0表示A,15表示小王,16表示大王,2~13表示2~K
var total = cards.length, count=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
if(total>14 || total<2 || (/\b([2-9]|1[0-3]),.*\b\1\b|\b0,.*\b0,.*\b0\b/).test(cards.join(','))){
return false; //牌数太多、太少,或有3个以上A,或2~K有重复
}
for(var i=0; i<total; i++){
count[cards[i]]++;
}
if(count[0]==2){ //2个A,换算成1,14
count[1] = count[14] = (count[0]=0)+1;
}
if(count[15]+count[1]+count[2]+count[3]+count[4]+count[5]>5){ //5以内超过5个
return false;
}
if(count[0] && count[15]+count[2]+count[3]+count[4]+count[5]==5){ //有A且只能作14
count[14] = count[0]--;
}
return check(count[15] ? checkWithXW : checkWithoutXW, count);
}
function checkWithoutXW(count){ //检测不含小王的情况
return (count.slice(1,15).join(',').replace(/^(0,)+|(,0)+$/g,'').match(/\b0\b/g)||'').length <= count[16];
}
function checkWithXW(count){ //检测含小王的情况
if(count.slice(1,6).indexOf(1)<0){ //没有1~5的牌,从5开始填小王
for(var i=0,j=5;i<count[15];i++){
count[15] -= count[j--]=1;
}
}else{ //补缺 >> 补大 >> 补小
for(i=count.indexOf(1,1)+1,j=count.lastIndexOf(1,5); count[15] && i<j; i++){
if(!count[i]){
count[15] -= count[i]=1;
}
}
for(i=count.lastIndexOf(1,5)+1; count[15] && i<=5; i++){
count[15] -= count[i]=1;
}
for(i=count.lastIndexOf(1,1)-1; count[15] && i>=1; i--){
count[15] -= count[i]=1;
}
}
return check(checkWithoutXW, count);
}
function check(fn,count){ //A的情况分别检测
if(count[0]){
var c1 = count.slice(0), c2 = count.slice(0);
c1[1] = c1[0]--;
c2[14] = c2[0]--;
return fn(c1) || fn(c2);
}
return fn(count);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment