斗地主基本牌型判断


/**
 * Created by xujw on 2017/10/16.
 * 斗地主
 * 单副扑克
 * 没有癞子玩法
 * 牌对象为{grade:3,face:1}
 * grade 牌面点数(3-13:3-K, 14:A, 15:2, 16:小王 17:大王)
 * face  牌面花色(1:黑桃、2:红桃、3:梅花、4:方块)
 */

var CARD_TYPE_INVALID = -1;                 // 无效手牌
var CARD_TYPE_SINGLE = 1;                   // 单张
var CARD_TYPE_DOUBLE = 2;                   // 对子
var CARD_TYPE_THREE = 3;                    // 三张
var CARD_TYPE_THREE_ONE = 4;                // 三带一(三带一张或者一对)
var CARD_TYPE_BOMB = 5;                     // 炸弹
var CARD_TYPE_FORE_TWO = 6;                 // 四带二
var CARD_TYPE_CONTINUOUS_SIGNGLE = 7;       // 单顺(5张起)
var CARD_TYPE_CONTINUOUS_DOUBLE = 8;        // 双顺(3对起)
var CARD_TYPE_AIRPLANE = 9;                 // 飞机 (两个三张起)
var CARD_TYPE_AIRPLANE_WING = 10;           // 飞机带翅膀 (三顺+同数量单牌或者对牌)
var CARD_TYPE_KING = 11;                    // 火箭

/**
 * 洗牌
 * @param arr
 * @return {*}
 */
function shuffle(arr) {
    var i,
        j,
        temp;
    for (i = arr.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    return arr;
}

/***
 * 从大到小排序手牌
 * @param cardsArr 手牌数组
 */
function sortBig2Samll(cardsArr) {
    cardsArr.sort(function (c1, c2) {
        return c2.grade - c1.grade;
    });
}

/**
 * 判定手牌类型
 * @param cardsArr 要判定的手牌信息数组(已经按照从大到小排好序)
 * @return {Number}
 */
function judgeCardType(cardsArr) {
    if (!cardsArr || cardsArr.length < 1) return CARD_TYPE_INVALID;
    sortBig2Samll(cardsArr);
    var cardType = CARD_TYPE_INVALID;
    var len = cardsArr.length;
    if (len === 1) {
        cardType = CARD_TYPE_SINGLE;
        cc.log('牌型:单张');
    } else if (len === 2) {
        if (checkDouble(cardsArr)) {
            cardType = CARD_TYPE_DOUBLE;
            cc.log('牌型:对子');
        } else if (checkKingBomb(cardsArr)) {
            cardType = CARD_TYPE_KING;
            cc.log('牌型:王炸');
        }
    } else if (len === 3) {
        if (checkAllCardSame(cardsArr)) {
            cardType = CARD_TYPE_THREE;
            cc.log('牌型:三张');
        }
    } else if (len === 4) {
        if (checkAllCardSame(cardsArr)) {
            cardType = CARD_TYPE_BOMB;
            cc.log('牌型:炸弹');
        } else if (checkThreeOne(cardsArr)) {
            cardType = CARD_TYPE_THREE_ONE;
            cc.log('牌型:三带一张');
        }
    } else if (len === 5) {
        if (checkContinuousSingle(cardsArr)) {
            cardType = CARD_TYPE_CONTINUOUS_SIGNGLE;
            cc.log('牌型:顺子' + len + '张.');
        } else if (checkThreeOne(cardsArr)) {
            cardType = CARD_TYPE_THREE_ONE;
            cc.log('牌型:三带一对');
        }
    } else if (len === 6) {
        if (checkContinuousSingle(cardsArr)) {
            cardType = CARD_TYPE_SINGLE;
            cc.log('牌型:顺子' + len + '张.');
        } else if (checkContinuousDouble(cardsArr)) {
            cardType = CARD_TYPE_DOUBLE;
            cc.log('牌型:连对(3对)');
        } else if (checkAirplane(cardsArr)) {
            cardType = CARD_TYPE_AIRPLANE;
            cc.log('牌型:飞机');
        } else if (checkFourWithTwo(cardsArr)) {
            cardType = CARD_TYPE_FORE_TWO;
            cc.log('牌型:4带2');
        }
    } else {
        // 6 张以上需要判断单顺、双顺、飞机、飞机带翅膀、4带2
        if (checkContinuousSingle(cardsArr)) {
            cardType = CARD_TYPE_CONTINUOUS_SIGNGLE;
            cc.log('牌型:单顺' + len + '张.');
        } else if (checkContinuousDouble(cardsArr)) {
            cardType = CARD_TYPE_CONTINUOUS_DOUBLE;
            cc.log('牌型:连对' + len / 2 + '对');
        } else if (checkAirplane(cardsArr)) {
            cardType = CARD_TYPE_AIRPLANE;
            cc.log('牌型:飞机');
        } else if (checkAirplaneWithWing(cardsArr)) {
            cardType = CARD_TYPE_AIRPLANE_WING;
            cc.log('牌型:飞机带翅膀');
        } else if (checkFourWithTwo(cardsArr)) {
            cardType = CARD_TYPE_FORE_TWO;
            cc.log('牌型:4带2');
        }
    }

    /****************start**************/
    // 检测所有牌都相同
    function checkAllCardSame(arr) {
        var len = arr.length;
        var isSame = true;
        for (var i = 0; i < len - 1; i++) {
            if (arr[i].grade !== arr[i + 1].grade) {
                isSame = false;
                break;
            }
        }
        return isSame
    }

    // 检测是不是递增(3/4/5, 6/7/8/9...)
    function checkIncrease(arr) {
        var len = arr.length;
        if (len < 2) {
            return false;
        }
        var ret = true;
        for (var i = 0; i < len - 1; i++) {
            if (arr[i].grade !== (arr[i + 1].grade + 1)) {
                ret = false;
                break;
            }
        }
        return ret;
    }

    // 检测单张
    function checkSignle(arr) {
        return arr.length === 1;
    }

    // 检测对子
    function checkDouble(arr) {
        if (arr.length !== 2) return false;
        return checkAllCardSame(arr);
    }

    // 检测王炸
    function checkKingBomb(arr) {
        if (arr.length !== 2) return false;
        var kingCount = 0;
        for (var i = 0; i < arr.length; i++) {
            if (arr[i].grade === 16 || arr[i].grade === 17) {
                kingCount++;
            }
        }
        return kingCount === 2;
    }

    // 三张不带
    function checkThree(arr) {
        if (arr.length !== 3) return false;
        return checkAllCardSame(arr);
    }

    // 检测三带一(带一张或者一对)
    function checkThreeOne(arr) {
        var len = arr.length;
        if (len !== 4 && len !== 5) return false;
        // 炸弹不算三带一
        if (checkBomb(arr)) return false;
        var ret = false;
        if (len === 4) {
            if (checkAllCardSame(arr.slice(0, arr.length - 1)) || checkAllCardSame(arr.slice(arr.length - 3, arr.length))) {
                ret = true;
            }
        } else if (len === 5) {
            if (checkAllCardSame(arr.slice(0, arr.length - 2)) && checkAllCardSame(arr.slice(arr.length - 2, arr.length))) {
                ret = true;
            } else if (checkAllCardSame(arr.slice(0, arr.length - 3)) && checkAllCardSame(arr.slice(arr.length - 3, arr.length))) {
                ret = true;
            }
        }
        return ret;
    }

    // 检测炸弹(5555)
    function checkBomb(arr) {
        if (arr.length !== 4)  return false;
        return checkAllCardSame(arr);
    }

    // 检测单顺(34567)
    function checkContinuousSingle(arr) {
        var len = arr.length;
        if (len < 5 || len > 12) {
            return false;
        }
        // 大小王、2不能算在顺子里
        var ret = true;
        for (var i = 0; i < len - 1; i++) {
            var pre = arr[i].grade;
            var next = arr[i + 1].grade;
            if (pre === 15 || pre === 16 || pre == 17 || next === 15 || next === 16 || next === 17) {
                ret = false;
                break;
            }
            else if (pre !== (next + 1)) {
                ret = false;
                break;
            }
        }
        return ret;
    }

    // 检测双顺(连对334455)
    function checkContinuousDouble(arr) {
        var len = arr.length;
        if (len < 6 || len % 2 !== 0) {
            return false;
        }

        var ret = true;
        for (var i = 0; i < len; i = i + 2) {
            // 2不能参与连对
            if (arr[i].grade === 15) {
                ret = false;
                break;
            }
            if (!checkAllCardSame(arr.slice(i, i + 2))) {
                ret = false;
                break;
            }
            if (i < len - 2) {
                if (arr[i].grade !== (arr[i + 2].grade + 1)) {
                    ret = false;
                    break;
                }
            }
        }

        return ret;
    }

    // 检测飞机(333444)
    function checkAirplane(arr) {
        var len = arr.length;
        if (len < 6 || len % 3 !== 0) {
            return false;
        }
        var ret = true;
        for (var i = 0; i < len; i += 3) {
            // 2不参与飞机
            if (arr[i].grade === 15) {
                ret = false;
                break;
            }
            if (!checkThree(arr.slice(i, i + 3))) {
                ret = false;
                break;
            }
            if (i < len - 3) {
                if (arr[i].grade !== (arr[i + 3].grade + 1)) {
                    ret = false;
                    break;
                }
            }
        }

        return ret;
    }

    // 检测飞机带翅膀(33344456、3334445566)
    function checkAirplaneWithWing(arr) {
        var len = arr.length;
        if (len < 8) {
            return false;
        }

        var threeArr = [];
        var othersArr = [];
        // 先找出所有的三张
        for (var i = 0; i < len;) {
            // 剩余手牌已经不够三张了
            if (i >= (len - 2)) {
                for (var k = i; k < len; k++) {
                    othersArr.push(arr[k]);
                }
                break;
            }
            // 剩余手牌大于二张
            var key = arr[i].grade;
            var count = 1;
            for (var j = i + 1; j < len; j++) {
                if (key === arr[j].grade) {
                    count++;
                } else {
                    break;
                }
            }
            // 如果count === 4 说明有炸弹,不符合规则
            if (count === 4) {
                return false;
            } else if (count === 3) {
                threeArr.push(arr[i], arr[i + 1], arr[i + 2]);
                i = j;
            } else {
                for (var h = i; h < j; h++) {
                    othersArr.push(arr[h]);
                }
                i = j;
            }
        }

        cc.log('-------飞机带翅膀判定------');
        cc.log('threes:' + JSON.stringify(threeArr));
        cc.log('others:' + JSON.stringify(othersArr));
        cc.log('-------------------------');

        // 判定三张是不是飞机
        if (!checkAirplane(threeArr)) {
            // 有可能三张相同牌作为单牌带出, 此时剔除一组三张作为带牌
            // 如:333444555+888
            // 如:333444555666 + 8889
            var threeLen = threeArr.length;
            if (checkAirplane(threeArr.slice(0, threeLen - 3))) {
                othersArr.push(threeArr[threeLen - 3], threeArr[threeLen - 2], threeArr[threeLen - 1]);
                threeArr = threeArr.slice(0, threeLen - 3);
            } else if (checkAirplane(threeArr.slice(3, arr.length))) {
                othersArr.push(threeArr[0], threeArr[1], threeArr[2]);
                threeArr = threeArr.slice(3, threeLen);
            } else {
                return false;
            }
        }

        // 需要翅膀数(单牌或者对子个数)
        var threeCounts = threeArr.length / 3;
        // 翅膀是单牌
        if (threeCounts === othersArr.length) {
            // 翅膀不能同时包含大小王
            var kingCount = 0;
            for (var v = 0; v < othersArr.length; v++) {
                if (othersArr[v].grade === 16 || othersArr[v].grade === 17) {
                    kingCount++;
                }
            }
            return kingCount < 2;
        } else if (threeCounts === othersArr.length / 2) {
            // 翅膀是对子
            // 判断otherArr是不是全是对子
            for (var u = 0; u < othersArr.length; u = u + 2) {
                if (!checkAllCardSame(othersArr.slice(u, u + 2))) {
                    return false;
                }
            }
            return true;
        } else {
            // 翅膀数目不对
            return false;
        }
    }

    // 检测4带二
    function checkFourWithTwo(arr) {
        var ret = false;
        if (checkAllCardSame(arr.slice(0, arr.length - 2))) {
            ret = true;
        } else if (checkAllCardSame(arr.slice(1), arr.length - 1)) {
            ret = true;
        } else if (checkAllCardSame(arr.slice(2), arr.length)) {
            ret = true;
        }

        return ret;
    }

    /****************end**************/

    return cardType;
}

/**
 * 比较两组手牌大小
 * @param cards1
 * @param cards2
 * @return {Boolean} true 表示 cards1 大于 cards2
 */
function compareCards(cards1, cards2) {
    var cardType1 = judgeCardType(cards1);
    var cardType2 = judgeCardType(cards2);
    if (cardType1 === cardType2){

    }else {

    }

}

原文地址:https://www.cnblogs.com/skyxu123/p/11369747.html

时间: 2024-08-10 14:19:13

斗地主基本牌型判断的相关文章

斗地主特殊牌型定义

游戏内一些牌型的定义,不做过多解释代码很详细,哪有不懂可以留言询问 public enum DDZPaiType { HuoJian("火箭",30,"HuoJian"), ZhaDan("炸弹",20,"ZhaDan"), DanPai("单牌",10,"DanPai"), DuiPai("对牌",10,"DuiPai"), SanZhangPa

扑克模拟,牌型判断java版

Card类 package com.company; public class Card { private String color; private Integer value; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Integer getValue() { return value; } public void

斗地主牌型基本算法升级版本

斗地主牌型基本算法升级版本 好久没更新博客了,前段时间和朋友一起开了一个公司 做APP,最后失败了.现在又开始做棋牌游戏了,最近在看网狐的源码,发现里面斗地主的基本算法太强大了,现在想想我原来的算法简直是弱爆了,分享一下 希望能对你有一点点帮助.以下主要涉及到判断牌型,牌型大小比较2块,如果你想了解更多关于棋牌游戏的东西请访问我的 棋牌游戏专栏. 一.判断牌型 定义一个结构来表示每张相同牌的信息. //分析结构 structtagAnalyseResult { BYTE cbFourCount;

斗地主算法判断牌型

由于近年来网络棋牌游戏的火爆导致个各个地区的特色棋牌游戏开发进入红火时期,也有越来越多的团队个人开始研究棋牌游戏的开发,所以本文主旨在于各个开发人员之间的交流. 每个游戏都有属于自己的规则,当然斗地主也不例外,常斗地主的朋友可能知道在斗地主里面一共有13种牌型,你所出的牌必须符合13种的一种才能够出得了牌,这个就叫地主的规则.那么我们下面可以通过一个枚举结构来表示每一种的牌型,在这里我们把错误的牌型也当成是一种牌型. 那么在编程中我们该怎么来判断一组牌到底该属于哪一种牌型了?? ?这就是接下来我

棋牌游戏开发之地主算法判断牌型

棋牌游戏开发疑问交流 QQ:325131039(勿发广告) 棋牌游戏开发技术交流群: 490287966(勿发广告) ps: 本文转载自博主 wojiushi3344 每个游戏都有属于自己的规则,当然地主也不例外,常斗地主的朋友可能知道在斗地主里面一共有13种牌型,你所出的牌必须符合13种的一种才能够出得了牌,这个就叫地主的规则.那么我们下面可以通过一个枚举结构来表示每一种的牌型,在这里我们把错误的牌型也当成是一种牌型. [cpp] view plaincopy enum  CARD_TYPE

Map集合、HashMap集合、LinkedHashMap集合、Hashtable集合、Collections工具类和模拟斗地主洗牌和发牌

1.Map集合概述和特点 * A:Map接口概述  * 查看API可以知道:  * 将键映射到值的对象  * 一个映射不能包含重复的键  * 每个键最多只能映射到一个值 * B:Map接口和Collection接口的不同  * Map是双列的,Collection是单列的  * Map的键唯一,Collection的子体系Set是唯一的  * Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效 2.Map集合的功能概述 * A:Map集合的功能概述  *

蓝桥杯历届试题:牌型种数

小明被劫持到X赌城,被迫与其他3人玩牌.一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张.这时,小明脑子里突然冒出一个问题:如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢? 请填写该整数,不要填写任何多余的内容或说明文字. 最容易想到的方法是dfs暴力枚举,但刚上手很容易写成这样,即标记每种牌出现次数枚举所有情况可能的牌的出现情况: 错误的解法: #include<cstring> #include<cstdio&

模拟斗地主洗牌、发牌(含有排序和不排序的)

不排序的: package cn.idcast5; import java.util.ArrayList; import java.util.Collections; //模拟斗地主洗牌发牌 //分析 //A 创建一个牌盒 //B 装牌 //C 洗牌 //D 发牌 //E 看牌 public class Shiyue31 { public static void main(String[] args) { // 创建一个牌盒 ArrayList<String> array = new Arra

代码实现:模拟斗地主洗牌和发牌并对牌进行排序的代码实现

package com.loaderman.test; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.TreeSet; public class Test{ /** * * A:案例演示 * 模拟斗地主洗牌和发牌并对牌进行排序的代码实现 * * 分析: * 1,买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去 * 2,洗牌 * 3,