用LUA实现麻将胡牌的一个思路
hand_table={ 41 , 42 , 43 , 22 , 21 , 43 , 22 , 11 , 11 , 11 , 42 , 33 , 33 , 33} -- 手牌
card_count_table={
[1]={ [1] = 0 , [2] = 0 , [3] = 0 , [4] = 0 , [5] = 0 , [6] = 0 , [7] = 0 , [8] = 0 , [9] = 0 }, -- 筒(11-19)
[2]={ [1] = 0 , [2] = 0 , [3] = 0 , [4] = 0 , [5] = 0 , [6] = 0 , [7] = 0 , [8] = 0 , [9] = 0 }, -- 万(21-29)
[3]={ [1] = 0 , [2] = 0 , [3] = 0 , [4] = 0 , [5] = 0 , [6] = 0 , [7] = 0 , [8] = 0 , [9] = 0 }, -- 条(31-39)
[4]={ [1] = 0 , [2] = 0 , [3] = 0 , [4] = 0 }, -- 东南西北(41-44)
[5]={ [1] = 0 , [2] = 0 , [3] = 0 } -- 中发白(51-53)
}
omnipotent_card = 21 -- 癞子
function CopyTable(old_table) -- 复制table
local new_table={}
if(old_table == nil) then return end
for i = 1,#old_table do
if(type(old_table[i]) == "table") then
local temp = CopyTable(old_table[i])
table.insert(new_table,temp)
else
table.insert(new_table,old_table[i])
end
end
return new_table
end
function ClassifyHand(hand , count) -- 手牌分类
for hand_key , hand_card in pairs(hand) do
local card_type = math.modf(hand_card / 10)
local card_number = hand_card % 10
count[card_type][card_number] = count[card_type][card_number] + 1
end
end
function SurplusHands(count) -- 剩余手牌
local total = 0
for card_type , card_numbers in pairs(count) do
for card_number , card_count in pairs(card_numbers) do
total = total + card_count
end
end
return total
end
function RemoveThreeSame(count) -- 移除三张手牌
for card_type,card_number in pairs(count) do
for i = 1,#card_number do
if(card_number[i] >= 3) then -- 原生可凑3
card_number[i] = card_number[i] - 3
return true
elseif(omnipotent_card ~= nil) then -- 使用癞子凑三
if(count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] >= 3 - card_number[i]) then
count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] = count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] - (3 - card_number[i])
card_number[i] = 0
return true
end
end
end
end
return false
end
function RemoveStraight(count) -- 移除三张顺子
for i = 1 ,#count - 2 do
for j = 1,# count[i] - 2 do
if(count[i][j] > 0 and count[i][j + 1] > 0 and count[i][j + 2] > 0) then -- 原生可凑顺子
count[i][j] = count[i][j] - 1
count[i][j + 1] = count[i][j + 1] - 1
count[i][j + 2] = count[i][j + 2] - 1
return true
elseif(omnipotent_card ~= nil and count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] > 0) then -- 使用癞子凑顺子
local need_card = 0
for p = 0,2 do
if(count[i][j + p] <= 0) then need_card = need_card + 1
end
end
if(need_card <= count[math.modf(omnipotent_card / 10)][omnipotent_card % 10]) then
count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] = count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] - need_card
for q = 0,2 do
if(count[i][j + q] >0 ) then count[i][j + q] = count[i][j + q] - 1
end
end
return true
end
end
end
end
for i = 1,#count[4] do -- 字牌做串
local index = 0
local own_card = 0
for j = 0,2 do
if( i + j > #count[4]) then index = i + j - #count[4] -- 获取已有的字牌数
else index = i + j
end
if(count[4][index] > 0) then
own_card = own_card + 1
end
end
if(own_card >= 3) then -- 原有可以构成串
for j = 0,2 do
if( i + j > #count[4]) then index = i + j - #count[4]
else index = i + j
end
if(count[4][index] > 0) then
count[4][index] = count[4][index] - 1
end
end
return true
elseif(omnipotent_card ~= nil) then -- 使用癞子构成
if( 3 - own_card <= count[math.modf(omnipotent_card / 10)][omnipotent_card % 10]) then
for j = 0,2 do
if( i + j > #count[4]) then index = i + j - #count[4]
else index = i + j
end
if(count[4][index] > 0) then
count[4][index] = count[4][index] - 1
end
end
count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] = count[math.modf(omnipotent_card / 10)][omnipotent_card % 10] - 1
return true
end
end
end
return false
end
function MathingThreeN(count) -- 剩余部分能否凑成多个3N
local temp_1 = CopyTable(count)
local temp_2 = CopyTable(count)
if(RemoveThreeSame(temp_1)) then -- 移除三个相同的
if(SurplusHands(temp_1) == 0 or MathingThreeN(temp_1)) then return true
end
end
if(RemoveStraight(temp_2)) then -- 移除一个顺子
if(SurplusHands(temp_2) == 0 or MathingThreeN(temp_2)) then return true
end
end
return false
end
function MathingHand(count)
for i = 1,#count do
for j = 1,#count[i] do
if(count[i][j] >= 2) then -- 寻找对子
local temp_1 = CopyTable(count)
temp_1[i][j] = temp_1[i][j] - 2
if(MathingThreeN(temp_1)) then return true
end
elseif(2 - count[i][j] <= count[math.modf(omnipotent_card / 10)][omnipotent_card % 10]) then -- 使用癞子凑对子
local temp_2 = CopyTable(count)
temp_2[math.modf(omnipotent_card / 10)][omnipotent_card % 10] = temp_2[math.modf(omnipotent_card / 10)][omnipotent_card % 10] - (2 - temp_2[i][j])
temp_2[i][j] = 0
if(MathingThreeN(temp_2)) then return true
end
end
end
end
return false
end
for i = 1,#card_count_table do -- 清空计数表
for j = 1,#card_count_table[i] do
card_count_table[i][j] = 0
end
end
ClassifyHand(hand_table,card_count_table)
print(MathingHand(card_count_table))
table.sort(hand_table)
str=""
for i=1,#hand_table do -- 输出排序后的手牌
str = str .. hand_table[i] .. ","
end
print(str)