用lua写一个红中麻将的听牌算法
时间: 2024-05-04 08:22:02 浏览: 168
红中麻将的听牌算法可以分为两个步骤:1.计算所有可能的牌型;2.排除不可能的牌型,得到所有可能的听牌。
Step 1: 计算所有可能的牌型
首先,需要将手牌、已打出的牌和红中牌合并成一个数组,然后对数组进行排序。接着,可以将数组按照顺序分成三个部分:雀头、顺子和刻子。其中,雀头必须是一对相同的牌,顺子必须是三个相邻的牌,刻子必须是三个相同的牌。如果出现了四个相同的牌,那么可以将其拆成一个刻子和一个顺子。
接下来,可以对顺子进行扩展。如果手牌中有相邻的牌可以与顺子形成一个新的顺子,那么就将其合并。这里需要注意的是,如果将顺子和牌型中的其他牌拆开后,可以形成新的顺子或刻子,那么就需要将其加入到牌型中。最后,将所有牌型保存到一个数组中。
Step 2: 排除不可能的牌型,得到所有可能的听牌
在得到所有可能的牌型后,需要对每个牌型进行分析,排除不可能的听牌。具体来说,可以对每个牌型中的每张牌进行分析,看看这张牌是否可以作为雀头或是将来形成一个顺子或刻子。如果不可以,就可以将这张牌作为可能的听牌。
下面是Lua的代码示例:
```lua
-- 手牌、已打出的牌和红中牌
local hand = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 19}
local discard = {10, 11, 12, 13, 14}
local hongzhong = {19}
-- 合并数组并排序
local tiles = {}
for _, v in ipairs(hand) do table.insert(tiles, v) end
for _, v in ipairs(discard) do table.insert(tiles, v) end
for _, v in ipairs(hongzhong) do table.insert(tiles, v) end
table.sort(tiles)
-- 计算牌型
local function calculate_patterns(tiles)
local patterns = {}
local function dfs(index, jiang)
if index > #tiles then
table.insert(patterns, jiang)
return
end
for i = index + 1, #tiles do
if tiles[i] == tiles[i - 1] then
if not jiang and i - index >= 2 then
dfs(i + 1, {tiles[i], tiles[i]})
end
if jiang and tiles[i] == jiang[1] then
dfs(i + 1, jiang)
end
elseif tiles[i] == tiles[i - 1] + 1 then
if jiang and tiles[i] == jiang[1] + 1 then
dfs(i + 1, jiang)
end
if i + 1 <= #tiles and tiles[i + 1] == tiles[i] then
dfs(i + 2, jiang)
end
elseif tiles[i] == tiles[i - 1] + 2 then
if i + 1 <= #tiles and tiles[i + 1] == tiles[i] then
dfs(i + 2, jiang)
end
else
if not jiang then
dfs(i, {tiles[i], tiles[i]})
end
end
end
end
dfs(1, nil)
return patterns
end
local patterns = calculate_patterns(tiles)
-- 计算听牌
local function calculate_ting(patterns)
local ting = {}
for _, p in ipairs(patterns) do
for i = 1, #p do
local t = p[i]
if i == 1 or p[i] ~= p[i - 1] then
-- 判断是否可以作为雀头
if t == p[i + 1] then
goto continue
end
-- 判断是否可以形成顺子
if t <= 7 and table.indexof(p, t + 1) and table.indexof(p, t + 2) then
goto continue
end
-- 判断是否可以形成刻子
if table.count(p, t) >= 2 then
goto continue
end
-- 可以作为听牌
table.insert(ting, t)
end
::continue::
end
end
return ting
end
local ting = calculate_ting(patterns)
-- 输出结果
print("手牌: ", table.concat(hand, " "))
print("已打出的牌: ", table.concat(discard, " "))
print("红中: ", table.concat(hongzhong, " "))
print("听牌: ", table.concat(ting, " "))
```
这段代码首先将手牌、已打出的牌和红中牌合并成一个数组,并对数组进行排序。接着,调用`calculate_patterns`函数计算所有可能的牌型。最后,调用`calculate_ting`函数计算所有可能的听牌。
`calculate_patterns`函数使用深度优先搜索算法计算所有可能的牌型。具体来说,它首先将数组按照顺序分成三个部分:雀头、顺子和刻子。然后,对顺子进行扩展,并将所有牌型保存到一个数组中。
`calculate_ting`函数遍历所有可能的牌型,并对每个牌型进行分析,排除不可能的听牌。具体来说,它对每个牌型中的每张牌进行分析,看看这张牌是否可以作为雀头或是将来形成一个顺子或刻子。如果不可以,就可以将这张牌作为可能的听牌。
最后,输出所有可能的听牌。
阅读全文