Lua 斗地主算法实现

--服务器定义的牌值  16进
Cards =
{
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,	--方块 A - K
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,	--梅花 A - K
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,	--红桃 A - K
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,	--黑桃 A - K
	0x4E,0x4F,
}
--获取花色
function GetColor( serverIndex )
    -- body
    return math.ceil(serverIndex / 16)  --1-方块   2-梅花   3-红桃    4-黑桃
end
--获取数字
function GetNumber( serverIndex )
    -- body
    return serverIndex % 16             --大王 15  小王14
end
--获取卡牌优先级 15 ~ 1(王、2、1、K、Q、J、10 ~ 3)
function GetGrad( serverIndex )
    -- body
    local num = serverIndex % 16 
    if num == 1 then
        return 12;
    elseif num == 2 then
        return 13;
    elseif num > 2 and num < 14 then
        return num - 2;
    else
        return num
    end
end
function SortCards( cardsData )
    -- body
    --卡牌排序(先优先级,后花色)
    local cachePos = #cardsData - 1;
    while cachePos > 0 do
        local pos = 0;
        for i=1,cachePos do
            if this.GetGrad(cardsData[i])  < this.GetGrad(cardsData[i+1])  then  --判断优先级
                pos = i;
                local tmp = cardsData[i];       --缓存小值
                cardsData[i] = cardsData[i+1];
                cardsData[i+1] = tmp;
            end
            if this.GetGrad(cardsData[i]) == this.GetGrad(cardsData[i+1]) then   --判断花色
                if this.GetColor(cardsData[i]) < this.GetColor(cardsData[i+1]) then
                    pos = i;
                    local tmp = cardsData[i];
                    cardsData[i] = cardsData[i+1];
                    cardsData[i+1] = tmp;
                end
            end
            cachePos = pos;
        end
    end
    
    return cardsData;
end
--u3d 滑动选牌
function OnGUI()
	-- body
	if UnityEngine.Event.current.type == UnityEngine.EventType.MouseDown then
		this.touchFirst = UnityEngine.Event.current.mousePosition;                --记录第一次点击位置
	end
	if UnityEngine.Event.current.type == UnityEngine.EventType.MouseDrag then
        this.timer = this.timer + UnityEngine.Time.deltaTime;  --计时器  
        if this.timer > this.offsetTime then                   --间隔时间进入
            this.timer = 0;                                    --时间重置
            this.touchSecond = UnityEngine.Event.current.mousePosition;           --记录结束下的位置  
            local slideDirection = this.touchFirst - this.touchSecond;            --开始减去结束
            local x = slideDirection.x;
            local y = slideDirection.y;
            --处理范围内的牌,加入选牌列表
            this.chooseCard = {};                               --选中牌清空
            for i=1,#this.selfInfo.cardsInfo do
            	if this.selfInfo.cardsInfo[i].parent.gameObject.activeSelf == true then
            		local lossyScaleX = this.selfInfo.cardsInfo[i].image.transform.lossyScale.x;
            		local leftPiont = UnityEngine.RectTransformUtility.WorldToScreenPoint(nil, this.selfInfo.cardsInfo[i].image.transform.position).x - this.cardWidth * lossyScaleX / 2; 
            		local rightPoint = UnityEngine.RectTransformUtility.WorldToScreenPoint(nil, this.selfInfo.cardsInfo[i].image.transform.position).x + this.cardWidth * lossyScaleX / 2;
            		local lossyScaleY = this.selfInfo.cardsInfo[i].image.transform.lossyScale.y;
            		local topPoint = UnityEngine.Screen.height - UnityEngine.RectTransformUtility.WorldToScreenPoint(nil, this.selfInfo.cardsInfo[i].image.transform.position).y + this.cardHeight * lossyScaleX / 2; 
            		local bottomPoint = UnityEngine.Screen.height - UnityEngine.RectTransformUtility.WorldToScreenPoint(nil, this.selfInfo.cardsInfo[i].image.transform.position).y - this.cardHeight * lossyScaleX / 2; 
            		if x > 0 then --向左
            			if leftPiont > this.touchSecond.x and leftPiont < this.touchFirst.x then
            				if this.touchSecond.y > bottomPoint and this.touchSecond.y < topPoint then
                                this.selfInfo.cardsInfo[i].image.color = Color.gray;                    --选中牌置灰
                                this.chooseCard[#this.chooseCard +1] = i;                               --记录选中牌下标
            				end
            			end
            		else          --向右
            			if leftPiont < this.touchSecond.x and leftPiont > this.touchFirst.x then
            				if this.touchSecond.y > bottomPoint and this.touchSecond.y < topPoint then
								this.selfInfo.cardsInfo[i].image.color = Color.gray;
								this.chooseCard[#this.chooseCard +1] = i;                               --记录选中牌下标
            				end
            			end
            		end
            	end
            end
        end
    elseif UnityEngine.Event.current.type == UnityEngine.EventType.MouseUp then
        --选中的牌操作
        for i=1,#this.chooseCard do
        	if this.selfInfo.cardsInfo[this.chooseCard[i]].isUp then
        		this.selfInfo.cardsInfo[this.chooseCard[i]].image.transform.localPosition = Vector3(0, 0, 0);
        		this.selfInfo.cardsInfo[this.chooseCard[i]].isUp = false;
        	else
        		this.selfInfo.cardsInfo[this.chooseCard[i]].image.transform.localPosition = Vector3(0, 50, 0);
        		this.selfInfo.cardsInfo[this.chooseCard[i]].isUp = true;
        	end
        end
        for i=1,#this.selfInfo.cardsInfo do
        	this.selfInfo.cardsInfo[i].image.color = Color.white;
        end
        this.chooseCard = {};
    end
end
--获取牌型
function .GetCardType( cardsData )
    -- body
    local cardsCount = #cardsData                   --卡牌数量
    if cardsCount == 0 then                         --空牌
        return CardType.CT_ERROR
    elseif cardsCount == 1 then                     --单张
        return CardType.CT_SINGLE
    elseif cardsCount == 2 then                     --对子、火箭
        if  this.IsMissile(cardsData) then
            return CardType.CT_MISSILE_CARD
        end
        if this.IsDouble(cardsData) then
            return CardType.CT_DOUBLE
        end
        return CardType.CT_ERROR
    elseif cardsCount == 3 then                     --三条
        if this.IsThree(cardsData) then
            return CardType.CT_THREE
        end
    elseif cardsCount == 4 then                     --炸弹、三带一
        if this.IsBomb(cardsData) then
            return CardType.CT_BOMB_CARD 
        end
        if this.IsThreeTakeOne(cardsData) then
            return CardType.CT_THREE_TAKE_ONE 
        end
    elseif cardsCount >= 5 then                     --三带二,连对,飞机,顺子
        if cardsCount == 5 then --三带二
            if this.IsThreeTakeTwo(cardsData) then
                return CardType.CT_THREE_TAKE_TWO 
            end
        elseif cardsCount == 6 then --四带两单
            if this.IsFourTakeTwo(cardsData) then
                return CardType.CT_FOUR_TAKE_ONE 
            end
        elseif cardsCount == 8 then --四带两对
            if this.IsFourTakeTwoDouble(cardsData) then
                return CardType.CT_FOUR_TAKE_TWO 
            end
        end

        if cardsCount >= 8 then  --飞机
            if this.IsThreeLine(cardsData) then
                return CardType.CT_THREE_LINE 
            end
        end
        if cardsCount > 5 and cardsCount % 2 == 0 then --连对
            if this.IsDoubleLine(cardsData) then
                return CardType.CT_DOUBLE_LINE 
            end
        end
        if this.IsSingleLine(cardsData) then --顺子
            return CardType.CT_SINGLE_LINE 
        end
    end
    return CardType.CT_ERROR 
end

--牌型判断(先排序,大到小)
--对子
function IsDouble( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) then 
        return true
    end
    return false
end

--火箭(王炸)
function IsMissile( cardsData )
    -- body
    if (cardsData[1] == 78 or cardsData[1] == 79)  and  (cardsData[2] == 78 or cardsData[2] == 79) then 
        return true
    end
    return false
end

--三条
function IsThree( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) then 
        return true
    end
    return false
end

--炸弹
function IsBomb( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[4]) then
        return true
    end
    return false
end

--三带一
function IsThreeTakeOne( cardsData )
    -- body
    if this.IsBomb(cardsData) then 
        return false
    end
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) then
        return true
    end
    if this.GetGrad(cardsData[2]) == this.GetGrad(cardsData[3]) and this.GetGrad(cardsData[2]) == this.GetGrad(cardsData[4]) then
        return true
    end
    return false
end

--三带二
function IsThreeTakeTwo( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) then
        if this.GetGrad(cardsData[4]) == this.GetGrad(cardsData[5]) then
            return true
        end
    end
    if this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[4]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[5]) then
        if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) then
            return true
        end
    end
    return false
end

--四带二
function IsFourTakeTwo( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[4]) then
        return true
    end
    if this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[4]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[5]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[6]) then
        return true
    end
    return false
end


--四带两对
function IsFourTakeTwoDouble( cardsData )
    -- body
    if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[3]) and this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[4]) then
        if this.GetGrad(cardsData[5]) == this.GetGrad(cardsData[6]) and this.GetGrad(cardsData[7]) == this.GetGrad(cardsData[8]) then
            return true
        end
    end
    if this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[4]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[5]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[6]) then
        if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[7]) == this.GetGrad(cardsData[8]) then
            return true
        end
    end
    if this.GetGrad(cardsData[5]) == this.GetGrad(cardsData[6]) and this.GetGrad(cardsData[5]) == this.GetGrad(cardsData[7]) and this.GetGrad(cardsData[5]) == this.GetGrad(cardsData[8]) then
        if this.GetGrad(cardsData[1]) == this.GetGrad(cardsData[2]) and this.GetGrad(cardsData[3]) == this.GetGrad(cardsData[4]) then
            return true
        end
    end
    return false
end

--顺子
function IsSingleLine( cardsData )
    -- body
    local length = #cardsData
    for i=1,length do
        if cardsData[i] == 78 or cardsData[i] == 79 or this.GetGrad(cardsData[i]) == 13 then     --顺子不包括大小王 and 2
            return false
        end
        if i + 1 < length then
            if this.GetGrad(cardsData[i]) - this.GetGrad(cardsData[i+1]) ~= 1 then
                return false
            end
        end
    end
    return true
end

--连对
function IsDoubleLine( cardsData )
    -- body
    local length = #cardsData
    for i=1,length do
        if cardsData[i] == 78 or cardsData[i] == 79 or this.GetGrad(cardsData[i]) == 13 then     --连对不包括大小王 and 2
            return false
        end 
    end
    for i=1,length,2 do
        if this.GetGrad(cardsData[i]) ~= this.GetGrad(cardsData[i+1]) then
            return false
        end
        if i + 2 <  length then
            if this.GetGrad(cardsData[i]) - this.GetGrad(cardsData[i+2]) ~= 1 then
                return false
            end 
        end
    end
    return true
end

--飞机
function IsThreeLine( cardsData )
    -- body
    local length = #cardsData
    --找出连续三张,并且连续三张不能是 2
    local threeCache = {}
    for i=1,length do
        if i + 2 <= length then
            if this.GetGrad(cardsData[i]) == this.GetGrad(cardsData[i+1]) and this.GetGrad(cardsData[i]) == this.GetGrad(cardsData[i+2]) then
                if this.IsContainGrad(threeCache,cardsData[i]) == false then
                    threeCache[#threeCache + 1] = cardsData[i]  
                end
            end
        else
            break
        end
    end
    --查找三张是否连续
    local threeCacheLength = #threeCache
    if threeCacheLength > 1 then
        for i=1,threeCacheLength do
            if i + 1 < threeCacheLength then
                if this.GetGrad(threeCache[i]) - this.GetGrad(threeCache[i+1]) ~= 1 then
                    return false
                end
            end
        end
    else 
        return false
    end
    --只能是带一个或是带一对
    --计算带牌数量
    if threeCacheLength * (3 + 1) == length then
        return true
    end
    local doubleCache = {}
    if threeCacheLength * (3 + 2) == length then
        --找对子,对子数量 = 三条的数量
        for i=1,length,2 do
            if i + 2 < length then 
                if this.GetGrad(cardsData[i])  == this.GetGrad(cardsData[i+1]) then
                    for j=1,threeCacheLength do
                        if this.IsContainGrad(threeCache,cardsData[i]) == false and this.IsContainGrad(doubleCache,cardsData[i]) == false then
                            doubleCache[#doubleCache + 1] = cardsData[i]
                        end
                    end
                end
            end
        end
        if #doubleCache == threeCacheLength then
            return true
        end
    end
    return false
end

--是否包含同级牌
function IsContainGrad( data,value )
    -- body
    local length = #data
    if length == 0 then
        return false
    end
    for i=1,length do
        if this.GetGrad(data[i]) == this.GetGrad(value) then
            return true
        end
    end
    return false
end

你可能感兴趣的:(Lua)