赖子麻将胡牌算法-lua版-红中麻将

废话不多说,网上找的你们懂的。直接上代码
1楼上用法,2楼上源码
local GameLogic = require(“GameLogic”)
local game = GameLogic:new()
local start = os.time()
local mj = {1,1,1,2,3,4,5,6,7,7,8,9,9,9}
game:calc(mj)
local useTime = os.time()-start
print(‘耗时:’,useTime)

目前只实现了判断14张牌是否胡牌(可能还有BUG,但目前测的没有,有的话请留言)。
如果要自己添加听牌的话。多添加一张赖子,然后判断是否能胡牌,如果可以胡,则去判断searchPath这个变量

GameLogic = {}

local MAX_CARD_NUM = 14

function GameLogic:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
self:init()
return o
end

function printTable(tab)
local logs = ‘’;
for k,v in ipairs(tab) do
logs = logs…v…’,’
end
return logs
end

function removeArray(v,arr)
local a = {}
local first = true
for i, j in pairs(arr) do
if j == v and first then
first = false
else
table.insert(a,j)
end
end
return a;
end

function insertArray(v,arr)
table.insert(arr,v);
local sort = function(a,b)
return b>a;
end
table.sort(arr,sort);
return arr;
end

function copyArray(arr)
local a = {}
for i, j in pairs(arr) do
table.insert(a,j)
end
return a;
end

function GameLogic:init()
self.numLaiZi = 1
self.searchPath = ‘’
end

function GameLogic:calc(cards)
local mj = {}
self.numLaiZi = 0

local wans = {}
local tongs = {}
local tiaos = {}
for i, v in pairs(cards) do
	if v ~= 35 then
		if v < 10 then
			table.insert(wans,v)
		elseif v < 20 then
			table.insert(tongs,v)
		elseif v < 30 then
			table.insert(tiaos,v)
		end
	else
		self.numLaiZi = self.numLaiZi+1;
	end
end
print('牌局分析结果: '..self.numLaiZi..'个赖子,'..#wans..'个万子,'..#tongs..'个筒子,'..#tiaos..'个条子')
self.needMinHunNum = 14;
self:getMinLaiZi(wans,0,'')
self.numWanMinHum = self.needMinHunNum
self.needMinHunNum = MAX_CARD_NUM;

self:getMinLaiZi(tongs,0,'')
self.numTongMinHum = self.needMinHunNum
self.needMinHunNum = MAX_CARD_NUM;

self:getMinLaiZi(tiaos,0,'')
self.numTiaoMinHum = self.needMinHunNum
self.needMinHunNum = MAX_CARD_NUM;
print('胡牌所需要的赖子数: 万子:'..self.numWanMinHum..',筒子:'..self.numTongMinHum..',条子:'..self.numTiaoMinHum)--]]

local wanLaiZi = self.numLaiZi-(self.numTongMinHum+self.numTiaoMinHum)
if wanLaiZi >= 0 then
	local resWan = self:canJiangHu(copyArray(wans),wanLaiZi);
	if resWan then
		print('resTong:万子作将可胡牌:',self.searchPath)
		return true;
	end
end

local tongLaiZi = self.numLaiZi-(self.numWanMinHum+self.numTiaoMinHum)
if tongLaiZi >= 0 then
	local resTong = self:canJiangHu(copyArray(tongs),tongLaiZi);
	if resTong then
		print('resTong:筒子作将可胡牌',self.searchPath)
		return true;
	end
end

local tiaoLaiZi = self.numLaiZi-(self.numWanMinHum+self.numTongMinHum)
if tiaoLaiZi >= 0 then
	local resTiao = self:canJiangHu(copyArray(tiaos),tiaoLaiZi);
	if resTiao then
		print('resTong:条子作将可胡牌:',self.searchPath)
		return true;
	end
end
return false

end

function GameLogic:getMinLaiZi(cards,needNum,logs)
self.needMinHunNum = self.needMinHunNum or 14
if self.needMinHunNum == 0 then
return
end

if needNum > self.numLaiZi then
	return --没有那么多赖子
end
local lastNum = self.needMinHunNum
local len = #cards
if len == 0 then
	self.needMinHunNum = math.min(needNum,self.needMinHunNum)
	if self.needMinHunNum < lastNum then
		self.searchPath = logs;
	end
	return
elseif len == 1 then
	self.needMinHunNum = math.min(needNum+2,self.needMinHunNum)
	if self.needMinHunNum < lastNum then
		self.searchPath = logs;
	end
	return
elseif len == 2 then
	local c1 = cards[1];
	local c2 = cards[2];
	if c2-c1 < 3 then
		self.needMinHunNum = math.min(needNum+1,self.needMinHunNum)
	end
	if self.needMinHunNum < lastNum then
		self.searchPath = logs;
	end
	return
end

local p1 = cards[1];
local p2 = cards[2];
local p3 = cards[3];

if needNum+2<self.needMinHunNum then
	cards = removeArray(p1,cards);
	logs = logs..p1..','
	self:getMinLaiZi(cards,needNum+2,logs);
	cards = insertArray(p1,cards);
	local l = 1
	if p1 > 10 then l = 2 end
	logs = string.sub(logs,0,string.len(logs)-1-l)
end

if (needNum + 1<self.needMinHunNum) then
	for i=2, len do
		if needNum+1 < self.needMinHunNum then
			p2 = cards[i];
			local con = false
			if i+1 <= len then
				p3 = cards[i+1];
				if p3 == p2 then
					con = true
				end
			end
			if con == false and p2 - p1 < 3 then
				cards = removeArray(p1,cards);
				cards = removeArray(p2,cards);
				logs = logs..p1..p2..','
				self:getMinLaiZi(cards,needNum+1,logs);
				cards = insertArray(p2,cards)
				cards = insertArray(p1,cards);
				local l = 1
				if p1 > 10 then l = 2 end;
				logs = string.sub(logs,0,string.len(logs)-2*l-1)
			end
			
		end
	end
end
	
for i=2, len do
	if (needNum < self.needMinHunNum) then
		p2 = cards[i];
		local con = false
		if i+2 <= len then
			if cards[i+2] == p2 then
				con = true;
			end
		end
		if con == false then
			
			for j=i+1,len do
				local con1 = false;
				if (needNum >= self.needMinHunNum) then
					break;
				end
				p3 = cards[j]
				if j+1 <= len then
					if p3 == cards[j+1] then
						con1 = true
					end
				end
				
				if con1 == false then
					if p3 + p1 == p2*2 and p2-p1 <= 1 then   -- 验证 123 和 111
						cards = removeArray(p1,cards);
						cards = removeArray(p2,cards);
						cards = removeArray(p3,cards);
						logs = logs..p1..p2..p3..','
						self:getMinLaiZi(cards,needNum,logs);
						cards = insertArray(p3,cards);
						cards = insertArray(p2,cards);
						cards = insertArray(p1,cards);
						local l = 1
						if p1 > 10 then l = 2 end;
						logs = string.sub(logs,0,string.len(logs)-3*l-1)
					end
				end
			end
		end
	end
end

end

function GameLogic:canJiangHu(cards,numHu)
local len = #cards
if len == 0 then
if needNum == 2 then – 鬼吊的情况
return 35
end
end
local copyCards = copyArray(cards);
for i,v in ipairs(copyCards) do
if i == len then
if numHu > 0 then
numHu = numHu - 1
cards = removeArray(v,cards)
self.needMinHunNum = MAX_CARD_NUM
self:getMinLaiZi(cards,0,v…’,’);
if self.needMinHunNum <= numHu then
return v;
end
numHu = numHu + 1
cards = insertArray(v,cards);
end
else
if i+2 == len or v ~= copyCards[i+2] then
if copyCards[i+1] == v then
cards = removeArray(v,cards)
cards = removeArray(copyCards[i+1],cards)
self:getMinLaiZi(cards,0,v…copyCards[i+1]…’,’);
if self.needMinHunNum <= numHu then
return v;
end
cards = insertArray(v,cards);
cards = insertArray(copyCards[i+1],cards);
end

		end
		if numHu > 0 and v ~= copyCards[i+1] then
			numHu = numHu - 1
			cards = removeArray(v,cards)
			self.needMinHunNum = MAX_CARD_NUM
			self:getMinLaiZi(cards,0,v..',');
			if self.needMinHunNum <= numHu then
				return v;
			end
			numHu = numHu + 1
			cards = insertArray(v,cards);
		end
	end
end
return nil

end

return GameLogic

手牌有多张赖子按你这算法听牌提示会卡死的!~

目前这份只能判断14张是否能否,听牌还要修改一下