--[[
file:mahjongArithmetic.lua
desc:胡牌算法
auth:Carol Luo
之前那个版本速度不太稳定 这个版本 总体速度要好一些
也没考虑癞子,这个版本性能主要卡在 mappingKey 组合字符串key 消耗比较大
如果能改成数字那么性能可以提升一倍 多(目前没有思路)
1,目前我是提前把生成的隐射放在另外一个文件加载 因为自己生成需要2~3秒的时间 提前生成 require 速度很快 是毫秒级别
2, 有些方法需要你自己实现,还有生成映射表 代码我注释掉了 取消注释 然后打印复制到一个文件里加载就可以了
3,目前
{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06}
也是6~7秒10万次 这个应该算是最复杂的牌型之一了
4,这个是最近看到别人博客,重新写的 多上论坛逛逛总有意想不到的收获,感谢各位前辈的分享
5 ,不排除有bug
]]
local pairs = pairs
local ipairs = ipairs
local skynet = require("skynet")
local tostring = require("extend_tostring")
local string = require("extend_string")
local table = require("extend_table")
local mjHelper = require("mahjongHelper")
---@class arithmetic 麻将算法
---@field ableHu 胡牌检查
---@field init 是否初始化
local arithmetic = {
init = false, --是否初始化
}
local this = arithmetic
---@class mapping 胡牌隐射
local mapping = require("mahjongMapping")
local keys = {}
local function mappingKey(...)
local args = {...}
table.clear(keys)
for _,arr in ipairs(args) do
for v,count in pairs(arr) do
for i=1,count do
table.insert(keys,"a"..tostring(v))
end
end
end
table.sort(keys)
return table.concat(keys)
end
local function mappingKey4(a,b,c,d)
return mappingKey(a,b,c,d)
end
local function mappingKey3(a,b,c)
return mappingKey(a,b,c)
end
local function mappingKey2(a,b)
return mappingKey(a,b)
end
local function mappingKey1(a)
return mappingKey(a)
end
--所有刻子
local kz111 = {[1]=3}
local kz222 = {[2]=3}
local kz333 = {[3]=3}
local kz444 = {[4]=3}
local kz555 = {[5]=3}
local kz666 = {[6]=3}
local kz777 = {[7]=3}
local kz888 = {[8]=3}
local kz999 = {[9]=3}
--所有顺子
local sz123 = {[1]=1,[2]=1,[3]=1}
local sz234 = {[2]=1,[3]=1,[4]=1}
local sz345 = {[3]=1,[4]=1,[5]=1}
local sz456 = {[4]=1,[5]=1,[6]=1}
local sz567 = {[5]=1,[6]=1,[7]=1}
local sz678 = {[6]=1,[7]=1,[8]=1}
local sz789 = {[7]=1,[8]=1,[9]=1}
local arrGroup = {
--所有刻子
kz111,
kz222,
kz333,
kz444,
kz555,
kz666,
kz777,
kz888,
kz999,
--所有顺子
sz123,
sz234,
sz345,
sz456,
sz567,
sz678,
sz789,
}
local hasGroup = {
[1] = {sz123,kz111},
[2] = {sz123,sz234,kz222},
[3] = {sz123,sz234,sz345,kz333},
[4] = {sz234,sz345,sz456,kz444},
[5] = {sz345,sz456,sz567,kz555},
[6] = {sz456,sz567,sz678,kz666},
[7] = {sz567,sz678,sz789,kz777},
[8] = {sz678,sz789,kz888},
[9] = {sz789,kz999},
}
local mapSun = { --允许组顺子
[0x01] = true, --1万
[0x02] = true, --2万
[0x03] = true, --3万
[0x04] = true, --4万
[0x05] = true, --5万
[0x06] = true, --6万
[0x07] = true, --7万
[0x08] = true, --8万
[0x09] = true, --9万
[0x11] = true, --1条
[0x12] = true, --2条
[0x13] = true, --3条
[0x14] = true, --4条
[0x15] = true, --5条
[0x16] = true, --6条
[0x17] = true, --7条
[0x18] = true, --8条
[0x19] = true, --9条
[0x21] = true, --1筒
[0x22] = true, --2筒
[0x23] = true, --3筒
[0x24] = true, --4筒
[0x25] = true, --5筒
[0x26] = true, --6筒
[0x27] = true, --7筒
[0x28] = true, --8筒
[0x29] = true, --9筒
}
function arithmetic.inittialize()
--避免重复初始化
if this.init then
return
end
-- --填充隐射
-- for _,m1 in ipairs(arrGroup) do
-- for _,m2 in ipairs(arrGroup) do
-- for _,m3 in ipairs(arrGroup) do
-- for _,m4 in ipairs(arrGroup) do
-- mapping[mappingKey4(m1,m2,m3,m4)] = true
-- mapping[mappingKey3(m1,m2,m3)] = true
-- mapping[mappingKey2(m1,m2)] = true
-- mapping[mappingKey1(m1)] = true
-- end
-- end
-- end
-- end
--标记初始化
this.init = true
end
---@field ableKanHu 坎胡检查
---@param hasHand 手牌
---@return an 分析数据
---@return mj 将对麻将
function arithmetic.analyze(hasHand)
local an = {}
--统计每种花色的牌
local dui = 0
--只能组成刻子牌
local jiang = false
for mj,count in pairs(hasHand) do
if mapSun[mj] then
local color = mjHelper.getColor(mj)
local value = mjHelper.getValue(mj)
local has = an[color] or {}
has[value] = count
an[color] = has
else
if 0 == count % 2 then
jiang = mj
dui = dui + 1
elseif 0 ~= count % 2 and 0 ~= count % 3 then
return false
end
end
end
--只能有一个将对
if dui > 1 then
return false
end
return an,jiang
end
---@field ableHu 胡牌检查
---@param hand 手牌
function arithmetic.ableHu(hand)
local len = #hand
if 2 == len then
return hand[1] == hand[2]
end
if 2 ~= len % 3 then
return false
end
local has = table.has_count(hand)
local an,jiang = this.analyze(has)
if not an then
return false
end
local mks = {}
--如果将对固定了
if jiang then
return this.ableKanHu(an,mks)
end
for mj,count in pairs(has) do
local color = mjHelper.getColor(mj)
local value = mjHelper.getValue(mj)
--去除将对
if count >= 2 then
if mapSun[mj] then
mks[color] = nil
an[color][value] = an[color][value] - 2
if this.ableKanHu(an,mks) then
return true
end
an[color][value] = an[color][value] + 2
end
end
end
return false
end
---@field ableKanHu 坎胡检查
---@param an 分析数据
function arithmetic.ableKanHu(an,mks)
--判断每种花色
for color,has in pairs(an) do
mks[color] = mks[color] or mappingKey(has)
if not mapping[mks[color]] then
return false
end
end
--require("skynet").error("ableKanHu:",tostring({mks=mks,an=an}))
return true
end
arithmetic.inittialize()
return arithmetic
--[[
胡牌思路
查表法 总数量 46375 种
]]