【转载】德州扑克牌型算法-Lua代码实现

原文地址:https://www.namidame.tech/Lua-Texas.html

本文提供了一种用Lua实现的德州扑克牌型、得分及成牌选择算法,是在公司空余时间老板要求练手写的算法。。。包括了代码和测试用例,代码可以应用在德州扑克手游的牌型计算模块中。

这里有几个文件,直接上代码
安装Lua运行环境后命令行运行main.lua文件即可
其中CardDealer文件是自动发牌的,由于测试用例需要自己编写,这个类也没什么用了

main.lua

-- Author: luyuejun
-- Date: 2017/6/15

require("CardUtil")
require("TableUtil")
require("CardDealer")

	-- "高牌" 	1
	-- "一对" 	2
	-- "两对" 	3
	-- "三条" 	4
	-- "顺子" 	5
	-- "同花" 	6
	-- "葫芦" 	7
	-- "四条" 	8
	-- "同花顺" 9

-- 以下为测试用例
local datas = {}
table.insert(datas, {input={H={{1,1},{1,2}},P={{1,3},{1,4},{1,5}}},expectOutput={T=9,S=90504030201,C={{1,1},{1,2},{1,3},{1,4},{1,5}}}})
table.insert(datas, {input={H={{4,10},{4,12}},P={{4,11},{4,13},{4,1}}},expectOutput={T=9,S=91413121110,C={{4,10},{4,11},{4,12},{4,13},{4,1}}}})
table.insert(datas, {input={H={{4,10},{4,12}},P={{4,11},{4,8},{4,1}}},expectOutput={T=6,S=61412111008,C={{4,8},{4,10},{4,11},{4,12},{4,1}}}})
table.insert(datas, {input={H={{4,10},{4,12}},P={}},expectOutput={T=1,S=11210,C={{4,10},{4,12}}}})
table.insert(datas, {input={H={{4,10},{4,12},{3,12}},P={}},expectOutput={T=2,S=2121210,C={{4,10},{4,12},{3,12}}}})
table.insert(datas, {input={H={{1,12},{4,12}},P={{3,12}}},expectOutput={T=4,S=4121212,C={{1,12},{4,12},{3,12}}}})
table.insert(datas, {input={H={{1,1},{1,13}},P={{1,12}}},expectOutput={T=1,S=1141312,C={{1,12},{1,13},{1,1}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{1,12}}},expectOutput={T=2,S=2141412,C={{1,12},{2,1},{1,1}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,1}}},expectOutput={T=4,S=4141414,C={{1,1},{2,1},{3,1}}}})

table.insert(datas, {input={H={{1,1},{2,13}},P={{3,2},{3,3}}},expectOutput={T=1,S=114130302,C={{3,2},{3,3},{2,13},{1,1}}}})
table.insert(datas, {input={H={{1,1},{2,11}},P={{3,1},{3,3}}},expectOutput={T=2,S=214141103,C={{3,3},{2,11},{1,1},{3,1}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{4,2},{3,2}}},expectOutput={T=3,S=314140202,C={{4,2},{3,2},{1,1},{2,1}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,1},{3,2}}},expectOutput={T=4,S=414141402,C={{3,2},{3,1},{1,1},{2,1}}}})
table.insert(datas, {input={H={{4,4},{3,4}},P={{4,2},{3,2}}},expectOutput={T=3,S=304040202,C={{3,2},{4,2},{4,4},{3,4}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,1},{4,1}}},expectOutput={T=8,S=814141414,C={{1,1},{2,1},{3,1},{4,1}}}})
table.insert(datas, {input={H={{1,1},{2,2}},P={{3,2},{4,2},{1,2}}},expectOutput={T=8,S=80202020214,C={{1,1},{1,2},{2,2},{3,2},{4,2}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,1},{4,1},{1,2}}},expectOutput={T=8,S=81414141402,C={{1,2},{1,1},{2,1},{3,1},{4,1}}}})
table.insert(datas, {input={H={{1,1},{2,2}},P={{3,4},{4,7},{1,6}}},expectOutput={T=1,S=11407060402,C={{2,2},{3,4},{1,6},{4,7},{1,1}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,4},{4,7},{1,6}}},expectOutput={T=2,S=21414070604,C={{3,4},{1,6},{4,7},{1,1},{2,1}}}})
table.insert(datas, {input={H={{1,2},{2,2}},P={{3,4},{4,1},{1,6}}},expectOutput={T=2,S=20202140604,C={{3,4},{1,6},{4,1},{1,2},{2,2}}}})

table.insert(datas, {input={H={{1,2},{2,2}},P={{3,1},{4,1},{1,6}}},expectOutput={T=3,S=31414020206,C={{1,6},{1,2},{2,2},{3,1},{4,1}}}})
table.insert(datas, {input={H={{1,2},{2,2}},P={{3,3},{4,3},{1,1}}},expectOutput={T=3,S=30303020214,C={{1,1},{1,2},{2,2},{3,3},{4,3}}}})
table.insert(datas, {input={H={{1,2},{2,1}},P={{3,1},{4,1},{1,6}}},expectOutput={T=4,S=41414140602,C={{1,2},{1,6},{2,1},{3,1},{4,1}}}})
table.insert(datas, {input={H={{1,2},{2,2}},P={{3,2},{4,1},{1,6}}},expectOutput={T=4,S=40202021406,C={{1,6},{4,1},{2,2},{1,2},{3,2}}}})
table.insert(datas, {input={H={{1,2},{2,1}},P={{3,3},{4,4},{1,5}}},expectOutput={T=5,S=50504030201,C={{2,1},{1,2},{3,3},{4,4},{1,5}}}})
table.insert(datas, {input={H={{1,13},{2,1}},P={{3,12},{4,11},{1,10}}},expectOutput={T=5,S=51413121110,C={{1,10},{4,11},{3,12},{1,13},{2,1}}}})

table.insert(datas, {input={H={{1,13},{2,9}},P={{3,12},{4,11},{1,10}}},expectOutput={T=5,S=51312111009,C={{2,9},{1,10},{4,11},{3,12},{1,13}}}})
table.insert(datas, {input={H={{1,1},{1,2}},P={{1,4},{1,3},{1,8}}},expectOutput={T=6,S=61408040302,C={{1,2},{1,3},{1,4},{1,8},{1,1}}}})

table.insert(datas, {input={H={{1,1},{2,1}},P={{1,12},{1,11},{1,10},{1,4}}},expectOutput={T=6,S=61412111004,C={{1,4},{1,10},{1,11},{1,12},{1,1}}}})
table.insert(datas, {input={H={{1,3},{2,3}},P={{3,3},{4,1},{4,3},{1,4}}},expectOutput={T=8,S=80303030314,C={{4,1},{1,3},{2,3},{3,3},{4,3}}}})
table.insert(datas, {input={H={{1,1},{2,1}},P={{3,1},{4,4},{4,3},{1,4}}},expectOutput={T=7,S=71414140404,C={{1,4},{4,4},{1,1},{2,1},{3,1}}}})

table.insert(datas, {input={H={{1,1},{2,1}},P={{3,3},{4,3},{1,3},{1,4}}},expectOutput={T=7,S=70303031414,C={{1,1},{2,1},{3,3},{4,3},{1,3}}}})
table.insert(datas, {input={H={{1,2},{2,2}},P={{3,3},{4,3},{1,1},{3,10}}},expectOutput={T=3,S=30303020214,C={{1,1},{1,2},{2,2},{3,3},{4,3}}}})

table.insert(datas, {input={H={{1,2},{2,2}},P={{3,3},{4,3},{1,1},{3,10},{4,10}}},expectOutput={T=3,S=31010030314,C={{1,1},{3,3},{4,3},{3,10},{4,10}}}})
table.insert(datas, {input={H={{1,1},{1,2}},P={{1,3},{1,4},{1,5},{4,12},{4,13}}},expectOutput={T=9,S=90504030201,C={{1,1},{1,2},{1,3},{1,4},{1,5}}}})
table.insert(datas, {input={H={{4,10},{4,12}},P={{4,11},{4,13},{4,1},{2,1}}},expectOutput={T=9,S=91413121110,C={{4,10},{4,11},{4,12},{4,13},{4,1}}}})


require("CardTest")
CardTest.test(datas)

CardUtil.lua

-- Author: luyuejun
-- Date: 2017/6/15

require("TableUtil")

DEBUG_LOG = false

CARD_POINTS = {
	0x01, 0x02, 0x03, 0x04,
	0x05, 0x06, 0x07, 0x08,
	0x09, 0x0A, 0x0B, 0x0C,
	0x0D, 0x0E
}

TYPE_POINTS = {
	"01","02","03","04",
	"05","06","07","08",
	"09","10","11","12",
	"13","14"
}

PAI_XING_STRING = {
	"高牌",
	"一对",
	"两对",
	"三条",
	"顺子",
	"同花",
	"葫芦",
	"四条",
	"同花顺",
}

Card = {
	hua = 1,
	dian = 1,
	isHand = false,
}

Card.__index = Card

function printC(card)
	print("card===")
	print("hua=",card.hua,"dian=",card.dian)
	print("card===")
end

function printHD(tb)
	CardUtil.printHuaDic(tb)
end

function printDD(tb)
	CardUtil.printDianDic(tb)
end

function Card:new(hua, dian, isHand)
	local o = {}
	setmetatable(o, self)

	o.hua = hua
	o.dian = dian
	o.isHand = isHand or false

	return o
end

function Card:getHua()
	return self.hua
end

function Card:getDian()
	return self.dian
end

function Card:IsHand()
	return self.isHand
end

CardUtil = {}

function CardUtil.getCardInfo(hands, publics)
	local tb = hands
	TableUtil.concat(tb, publics)
	TableUtil.print(tb)
end

function CardUtil.isTongHua(tb)
	local flag = false
	local huas = {0,0,0,0}

	for i,v in ipairs(tb) do
		huas[v.hua] = huas[v.hua] + 1
	end

	for i,v in ipairs(huas) do
		if v >= 5 then 
			return true, i 
		end
	end
	return false
end

function CardUtil.isTongHuaVecShunZi(tb)
	local flag = false
	local curIndex = #tb
	local preIndex = #tb-1
	for i = #tb, 2, -1 do
		for j = i, i-3, -1 do
			curIndex = j
			preIndex = j - 1
			-- print("i = ",i,"j = ",j)
			-- print("compare ",curIndex," ",preIndex)
			if tb[preIndex] == nil then
				return false
			elseif curIndex == #tb then
				if tb[curIndex].dian == 1 then
				   	if tb[preIndex].dian ~= 13 then -- TJQKA的处理
						break
					end
				elseif tb[curIndex].dian ~= tb[preIndex].dian + 1 then
					break
				end
			elseif tb[curIndex].dian ~= tb[preIndex].dian + 1 then
				break
			elseif curIndex == i - 3 then --比完一轮5张都没断,即是顺子
				local isASpecial = false
				if tb[preIndex].dian == 1 then isASpecial = true end
				local cards = {}
				for k=i-4,i do
					-- print("insert ",k)
					table.insert(cards, tb[k])
				end
				return true, cards, isASpecial
			end
		end
	end
	return false
end

-- A有两个位置,权值1和14
function CardUtil.getDianDicSpec(tb)
	local dians = {
		{},{},{},{},
		{},{},{},{},
		{},{},{},{},
		{},{}
	}
	for i,v in ipairs(tb) do
		-- print("insert into dian=", v.dian)
		table.insert(dians[v.dian], v)		
		if v.dian == 1 then
			table.insert(dians[14], v)
		end
	end
	return dians
end

-- A只有权值14
function CardUtil.getDianDic14(tb)
	local dians = {
		{},{},{},{},
		{},{},{},{},
		{},{},{},{},
		{},{}
	}
	for i,v in ipairs(tb) do
		if v.dian == 1 then
			table.insert(dians[14], v)
		else
			table.insert(dians[v.dian], v)		
		end
	end
	return dians
end

function CardUtil.printDianDic(dictionary)
	print("dianDic=")
	CardUtil.printDic(dictionary)
	print("")
end	

function CardUtil.getHuaDic(tb)
	local huas = {
		{},{},{},{},
	}
	local As = { -- 先将A存起来,最后再放进每一种花色里,与默认A权值为14类似
		{},{},{},{},
	}
	for i,v in ipairs(tb) do
		-- print("insert into dian=", v.dian)
		if v.dian == 1 then
			table.insert(As[v.hua], v)
		else
			table.insert(huas[v.hua], v)
		end
	end
	for i,hua in ipairs(As) do
		for _,v in pairs(hua) do
			table.insert(huas[i], v)
		end
	end
	return huas
end

function CardUtil.printHuaDic(dictionary)
	print("huaDic=")
	CardUtil.printDic(dictionary)
	print("")
end	

function CardUtil.printDic(dictionary)
	for i, v in ipairs(dictionary) do
		TableUtil.print(v)
	end	
end

function CardUtil.isSiTiao(dictionary)
	for i,v in ipairs(dictionary) do
		if #v >= 4 then
			-- 拿出这四张牌
			local cards = {}
			for _, v1 in pairs(v) do
				table.insert(cards, v1)
			end
			-- 找出除四条外最大一张牌
			for j = #dictionary, 1, -1 do
				if i ~= j and #dictionary[j] > 0 then
					table.insert(cards, 1, dictionary[j][1])
					return true, cards
				end
			end
			return true, cards -- 四张卡时在这里返回
		end
	end
	return false
end

function CardUtil.isHuLu( dictionary )
	-- body
	local dian3 = 0 -- 最大三条所在点数
	local dian2 = 0 -- 最大一对所在点数
	for i = #dictionary, 1, -1 do -- 倒序查找,从最大的找起
		if #dictionary[i] == 3 then
			if dian3 == 0 then
				dian3 = i
			elseif dian2 == 0 then -- 如果已经取出最大的三条,应从第二大的三条里取两张作为一对
				dian2 = i
			end
		elseif #dictionary[i] == 2 then -- 这里有可能从三条里面拿,例如AAAKKK8
			if dian2 == 0 then
				dian2 = i
			end
		end
		if dian3 > 0 and dian2 > 0 then
			break
		end
	end
	if dian3 > 0 and dian2 > 0 then
		-- 先插入权值小的一对,再插入权值大的三条
		local cards = {}
		table.insert(cards, dictionary[dian2][1])
		table.insert(cards, dictionary[dian2][2])
		for _,v in pairs(dictionary[dian3]) do
			table.insert(cards, v)
		end
		return true, cards
	else
		return false
	end
end

function CardUtil.isSanTiao( dictionary )
	-- body
	local maxSame = 0
	local dian = 0
	local hasPair = false
	for i,v in ipairs(dictionary) do
		if #v >= maxSame then
			maxSame = #v
			dian = i
		end
		if #v == 2 then
			hasPair = true
		end		
	end
	if maxSame == 3 and not hasPair then
		local cards = {}
		-- 拿出最大的两张牌,不能是一对
		for i = #dictionary, 1, -1 do
			if #dictionary[i] == 1 then
				if #cards == 0 then
					table.insert(cards, dictionary[i][1])
				elseif #cards == 1 then
					table.insert(cards, 1, dictionary[i][1]) -- 为了按牌型升序排列,例如A8333
				end
			end
		end
		-- 拿出最大的三条
		for i = 1, 3 do
			table.insert(cards, dictionary[dian][i])
		end
		return true, cards
	else 
		return false
	end
end

function CardUtil.isTwoPairs(dictionary)
	if #dictionary[1] > 0 and dictionary[1][1].dian == 1 then
		dictionary[1] = {}
	end
	local pairCount = 0
	local maxSame = 0
	local maxPairIndex = 0
	local secMaxPairIndex = 0
	for i = #dictionary, 1, -1 do
		if #dictionary[i] == 2 then
			pairCount = pairCount + 1
			if maxPairIndex == 0 then
				maxPairIndex = i
			elseif secMaxPairIndex == 0 then
				secMaxPairIndex = i
			end
		end
		if #dictionary[i] >= maxSame then
			maxSame = #dictionary[i]
		end
	end
	if pairCount >= 2 and maxSame == 2 then
		local cards = {}
		-- 取出最大的一张
		for i = #dictionary, 1, -1 do
			if #dictionary[i] >= 1 and i ~= maxPairIndex and i ~= secMaxPairIndex then -- 剩下的一张可能从第三对两对里取,比如AAKKJJ
				table.insert(cards, dictionary[i][1])
				break
			end
		end
		-- 取出最大的两对
		for i = 1, 2 do table.insert(cards, dictionary[secMaxPairIndex][i]) end -- 倒序
		for i = 1, 2 do table.insert(cards, dictionary[maxPairIndex][i]) end
		return true, cards
	else
		return false
	end
end

function CardUtil.isOnePair(dictionary)
	local pairCount = 0
	local maxSame = 0
	local pairIndex = 0
	for i,v in ipairs(dictionary) do
		if #v == 2 then
			pairCount = pairCount + 1
			if pairIndex == 0 then
				pairIndex = i
			end
		end
		if #v >= maxSame then
			maxSame = #v
		end
	end
	if pairCount == 1 then
		local cards = {}
		-- 取最大的三张单牌
		for i = #dictionary, 1, -1 do
			if #dictionary[i] == 1 then
				if #cards < 3 then
					table.insert(cards, 1, dictionary[i][1])
				else
					break
				end
			end
		end
		-- 取出对子
		for i = 1,2 do table.insert(cards, dictionary[pairIndex][i]) end
		return true, cards
	else
		return false
	end
end

function CardUtil.getHighCard(dictionary)
	local cards = {}
	for i = #dictionary, 1, -1 do
		if #cards < 5 then
			if #dictionary[i] == 1 then
				local hasElement = false
				for _,v in pairs(cards) do
					if dictionary[i][1].dian == v.dian then
						hasElement = true
					end
				end
				if not hasElement then
					table.insert(cards, 1, dictionary[i][1])
				end
			end
		else
			break
		end
	end
	return cards
end

function CardUtil.isShunZiByDic(dictionary)
	for i = 14, 5, -1 do
		if #dictionary[i] > 0 then
			for j = i, i-4, -1 do
				-- print("i = ",i,"j = ",j)
				-- print("compare ",curIndex," ",nextIndex)
				
				if #dictionary[j] == 0 then
					break
				elseif j == i - 4 then --比完一轮都没断,即是顺子
					local cards = {}
					local isASpecial = false
					for k = j,i do
						if k == j and dictionary[k][1].dian == 1 then isASpecial = true end --A2345的情况
						table.insert(cards, dictionary[k][1])
					end
					return true, cards, isASpecial
				end
			end
		end
	end
	return false	
end

function CardUtil.isTongHuaByDic(dictionary)
	for i,v in ipairs(dictionary) do
		if #v >= 5 then
			return true, v
		end
	end
	return false
end

-- tb 从点数小到大排列
-- 当isASpecial为true时,A的权值由正常的14变为1,例如A2345
function CardUtil.getCardPoint(tb, paiXing, isASpecial)
	local paiXingPoint = TYPE_POINTS[paiXing]
	local strPoint = ""
	isASpecial = isASpecial or false -- 正常情况A权值为14
	for i,v in ipairs(tb) do
		if v.dian < 10 then
			if v.dian == 1 then
				if isASpecial then
					strPoint = strPoint.."01"
				else
					strPoint = "14"..strPoint
				end
			else
				strPoint = "0"..tostring(v.dian)..strPoint
			end
		else
			strPoint = tostring(v.dian)..strPoint
		end
	end
	strPoint = paiXingPoint..strPoint
	local point = tonumber(strPoint)
	return point
end

-- 确定牌型
-- 按牌型不同算分
--[[
	主要思路:
	将手牌与公共牌合并,并按点数升序排序
	A一般权值为14,只有在顺子/同花顺中的A2345中才有可能权值为1
	将牌按点数分别装入索引1到14数组中,getDianDicSpec中A会放入1和14两个数组中,即有两个权值; 
	getDianDic14中A只会放入14数组中,即只有一个权值
	getHuaDic按花色放入四个数组
	1.先判断是否同花顺:判断是否同花,若是,则判断“同花的数组”是否同时为顺子
	2.判断是否四条,注意第5张牌有可能从对子或三条里面拿
	3.判断是否葫芦,注意第4,5张牌可能从另外的三条里面拿,如3334447
	4.判断是否同花,这在同花顺时已经判断过
	5.判断是否顺子,这里不可以用判断同花顺时的结果,因为那只是判断同花的几张牌是否顺子,
		并未包含其他花色的牌,比如红桃45679+黑桃8,红桃的数组不是顺子,但56789是顺子
		为此写了两个判断顺子的函数isTongHuaVecShunZi/isShunzi
	6.判断是否三条,这时不会有另外的对子或三条,否则早就判断为葫芦
	7.判断是否两对,注意可能有三对的情况
	8.判断是否一对
	9.若以上都不是,直接判断为高牌
--]]

-- 牌型得分
 	-- "高牌" 	1
	-- "一对" 	2
	-- "两对" 	3
	-- "三条" 	4
	-- "顺子" 	5
	-- "同花" 	6
	-- "葫芦" 	7
	-- "四条" 	8
	-- "同花顺" 9

-- 输入
	-- hands: 手牌table,例如{{1,2},{3,4}}
	-- publics: 公共牌table,可有0/3/4/5张公共牌,例如{{3,3},{4,1},{4,3},{1,4}}
-- 输出
	-- paiXing:成牌牌型,例如9,为同花顺
	-- cardPoint:牌型得分,例如91413121110,前1或2位为牌型分值,和成牌牌型相对应,后面为每张牌的得分,直接比较得分可知牌型间大小
	-- returnVec:最大成牌,返回最大牌型的几张牌,例如{{4,10},{4,11},{4,12},{4,13},{4,1}}
function CardUtil.calculatePoint(hands, publics)
	local tb = TableUtil.concat(hands, publics)
	TableUtil.sort(tb)
	
	local dianDicSp = CardUtil.getDianDicSpec(tb)
	if DEBUG_LOG then CardUtil.printDianDic(dianDicSp) end
	local dianDic14 = CardUtil.getDianDic14(tb)
	if DEBUG_LOG then CardUtil.printDianDic(dianDic14) end
	local huaDic = CardUtil.getHuaDic(tb)
	if DEBUG_LOG then CardUtil.printHuaDic(huaDic) end

	local isTongHua, tongHuaVec = CardUtil.isTongHuaByDic(huaDic)
	if DEBUG_LOG then print("isTongHua=", isTongHua) end
	if DEBUG_LOG then if tongHuaVec then printT(tongHuaVec) end end
	local isTongHuaShun = false
	local isASpecial = false
	local isTongHuaVecShunZi = false
	local tongHuaShunVec = {}
	if isTongHua then
		if tongHuaVec[#tongHuaVec].dian == 1 then -- 需要处理一下vec
			if DEBUG_LOG then print("special") end
			local tmpVec = {}
			for _,v in pairs(tongHuaVec) do
				table.insert(tmpVec, v)
			end
			table.insert(tmpVec, 1, tongHuaVec[#tongHuaVec]) -- 如果有后面A,将A也加入最前面,类似生成dianDicSp
			if DEBUG_LOG then printT(tmpVec) end
			isTongHuaVecShunZi, tongHuaShunVec, isASpecial = CardUtil.isTongHuaVecShunZi(tmpVec)
		else
			isTongHuaVecShunZi, tongHuaShunVec, isASpecial = CardUtil.isTongHuaVecShunZi(tongHuaVec)
		end	
		isTongHuaShun = isTongHua and isTongHuaVecShunZi
	end
	if DEBUG_LOG then print("isTongHuaShun=",isTongHuaShun) end

	local typePoint = 0
	local cardPoint = 0
	local totalPoint = 0 -- 返回的牌型得分

	local paiXing = 0 -- 返回的牌型
	local returnVec = {} -- 返回选择哪几张牌

	if isTongHuaShun then -- 同花顺
		if DEBUG_LOG then print("tonghuashun") end
		if DEBUG_LOG then printT(tongHuaShunVec) end
		paiXing = 9
		cardPoint = CardUtil.getCardPoint(tongHuaShunVec, paiXing, isASpecial)
		returnVec = tongHuaShunVec -- 拿出同花的数组判断,如果也是顺子,则是同花顺,见上
	else
		local isSiTiao, siTiaoVec = CardUtil.isSiTiao(dianDic14)
		if DEBUG_LOG then print("isSiTiao=",isSiTiao) end
		if DEBUG_LOG then if siTiaoVec then TableUtil.print(siTiaoVec) end end
		if isSiTiao then -- 四条
			if DEBUG_LOG then print("siTiao") end
			paiXing = 8
			typePoint = TYPE_POINTS[paiXing]
			cardPoint = CardUtil.getCardPoint(siTiaoVec, paiXing)
			returnVec = siTiaoVec
		else
			local isHuLu, huLuVec = CardUtil.isHuLu(dianDic14)
			if DEBUG_LOG then print("isHuLu=  ",isHuLu) end
			if DEBUG_LOG then if isHuLu then TableUtil.print(huLuVec) end end
			if isHuLu then -- 葫芦
				if DEBUG_LOG then print("huLu") end
				paiXing = 7
				typePoint = TYPE_POINTS[paiXing]
				cardPoint = CardUtil.getCardPoint(huLuVec, paiXing)
				returnVec = huLuVec			
			elseif isTongHua then --同花
				if DEBUG_LOG then 
					print("tonghua") 
					if tongHuaVec then printT(tongHuaVec) end
				end
				paiXing = 6
				typePoint = TYPE_POINTS[paiXing]
				cardPoint = CardUtil.getCardPoint(tongHuaVec, paiXing)
				returnVec = tongHuaVec
			else 
				local isShunZi, shunZiVec, isASpecial = CardUtil.isShunZiByDic(dianDicSp) -- 只有顺子特殊处理,当A2345时权值为1
				if DEBUG_LOG then 
					print("isShunzi=",isShunZi) 
					if shunZiVec then printT(shunZiVec) end
				end				
				if isShunZi then--顺子
					if DEBUG_LOG then print("shunzi") end
					paiXing = 5
					typePoint = TYPE_POINTS[paiXing]
					cardPoint = CardUtil.getCardPoint(shunZiVec, paiXing, isASpecial)
					returnVec = shunZiVec
				else
					local isSanTiao, sanTiaoVec = CardUtil.isSanTiao(dianDic14)
					if DEBUG_LOG then print("isSanTiao=",isSanTiao) end
					if DEBUG_LOG then if isSanTiao then TableUtil.print(sanTiaoVec) end end
					if isSanTiao then -- 三条
						if DEBUG_LOG then print("santiao") end
						paiXing = 4
						typePoint = TYPE_POINTS[paiXing]
						cardPoint = CardUtil.getCardPoint(sanTiaoVec, paiXing)
						returnVec = sanTiaoVec
					else
						local isTwoPairs, twoPairsVec = CardUtil.isTwoPairs(dianDic14)
						if DEBUG_LOG then print("isTwoPairs=",isTwoPairs) end
						if DEBUG_LOG then if isTwoPairs then TableUtil.print(twoPairsVec) end end
						if isTwoPairs then -- 两对
							if DEBUG_LOG then print("two pairs") end
							paiXing = 3
							typePoint = TYPE_POINTS[paiXing]
							cardPoint = CardUtil.getCardPoint(twoPairsVec, paiXing)
							returnVec = twoPairsVec
						else
							local isOnePair, onePairVec = CardUtil.isOnePair(dianDic14)
							if DEBUG_LOG then print("isOnePair=",isOnePair) end
							if DEBUG_LOG then if isOnePair then TableUtil.print(onePairVec) end end
							if isOnePair then -- 一对
								if DEBUG_LOG then print("one pair") end
								paiXing = 2
								typePoint = TYPE_POINTS[paiXing]
								cardPoint = CardUtil.getCardPoint(onePairVec, paiXing)
								returnVec = onePairVec
							else -- 高牌
								if DEBUG_LOG then print("isHighCard=  ", true) end
								local cards = CardUtil.getHighCard(dianDic14)
								if DEBUG_LOG then 
									printT(cards)
									print("high cards")
								end
								paiXing = 1
								typePoint = TYPE_POINTS[paiXing]
								cardPoint = CardUtil.getCardPoint(cards, paiXing)
								returnVec = cards
							end		
						end	
					end
				end
			end
		end
	end
	totalPoint = typePoint + cardPoint
	if DEBUG_LOG then print("totalPoint=",totalPoint) end
	return paiXing, cardPoint, returnVec
end

CardTest.lua

-- Author: luyuejun
-- Date: 2017/6/15

require("CardUtil")

CardTest = {}

CardTest.__index = CardTest

function CardTest:new()
	local o = {}
	setmetatable(o, self)

	return o
end

function CardTest.test(datas)
	local correct = 0
	local incorrect = 0
	for i,v in ipairs(datas) do
		local inputData = v.input
		local expectOutPutData = v.expectOutput
		local flag = CardTest.testOne(inputData, expectOutPutData)
		if flag then correct = correct + 1
		else incorrect = incorrect + 1 end
	end
	print("")
	print("correct=",correct)
	print("error=   ",incorrect)
end

function CardTest.testOne(inputData, expectOutPutData)
	local inputHands = inputData["H"]
	local inputPublics = inputData.P

	local hands = {}
	local publics = {}

	for _,v in pairs(inputHands) do
		local card = Card:new(v[1], v[2], true)
		table.insert(hands, card)
	end

	for _,v in pairs(inputPublics) do
		local card = Card:new(v[1], v[2], false)
		table.insert(publics, card)
	end

	expectOutPutCardType = expectOutPutData.T
	expectOutPutScore = expectOutPutData.S
	expectOutPutCards = expectOutPutData.C
	--printT(expectOutPutCards)
	local outPutCardType, outPutScore, outPutCards = CardUtil.calculatePoint(hands, publics)
	print("牌型 = "..PAI_XING_STRING[outPutCardType])
	print("得分 = "..outPutScore)
	print("牌组 = ")
	printT(outPutCards)
	local isCardType = CardTest.verifyCardType(expectOutPutCardType, outPutCardType)
	local isScore = CardTest.verifyScore(expectOutPutScore, outPutScore)
	local isCards = CardTest.verifyCards(expectOutPutCards, outPutCards)

	if isCardType and isScore and isCards then
		return true
	else
		return false
	end
end

function CardTest.verifyCardType(expectOutPutCardType, outPutCardType)
	if expectOutPutCardType == outPutCardType then
		return true
	else
		print("out put card type expected:"..expectOutPutCardType)
		print("output: "..outPutCardType)
		return false
	end
end

function CardTest.verifyScore(expectOutPutScore, outPutScore)
	if expectOutPutScore == outPutScore then
		return true
	else
		print("out put score expected:"..expectOutPutScore)
		print("output: "..outPutScore)
		return false
	end
end

function CardTest.verifyCards(expectOutPutCards, outPutCards)
	local flag = true
	for i,v in ipairs(expectOutPutCards) do
		-- print("compare-----")
		-- printC(outPutCards[i])
		if not CardTest.sameCard(v, outPutCards[i]) then
			print("out put cards "..tostring(i).." expected:")
			print("hua=",v[1],"dian=",v[2])
			print("output:")
			printC(outPutCards[i])
			flag = false
		end
	end
	return flag
end

function CardTest.sameCard(inputCard, outPutCard)
	if inputCard[2] == outPutCard.dian then
		return true
	else
		return false
	end
end

TableUtil.lua

-- Author: luyuejun
-- Date: 2017/6/15

TableUtil = {}

function printT(tb)
	TableUtil.print(tb)
end

function TableUtil.concat(tb1, tb2)
	local newTb = {}
	for i,v in pairs(tb1) do
		table.insert(newTb, v)
	end
	if #tb2 > 0 then
		for i,v in pairs(tb2) do
			table.insert(newTb, v)
		end
	end
	return newTb
end

function TableUtil.print(tb)
	for i, v in ipairs(tb) do
		print(v.hua.." "..v.dian)
		if i == #tb then print("=========")
		else print("---") end
	end
end

function TableUtil.sort(tb, comps)
	local function defaultComps(a,b)
		return a.dian < b.dian
	end
	if not comps then
		comps = defaultComps
	end

	table.sort(tb, comps)
end

function TableUtil.uniqueConcat(tb1, tb2)
	for i,v1 in pairs(tb2) do
		local hasElement = false
		for _, v2 in pairs(tb1) do
			if v2.dian == v1.dian then
				hasElement = true
				break
			end
		end
		if not hasElement then
			table.insert(tb1, v1)
		end
	end
	return tb1
end

CardDealer.lua

-- Author: luyuejun
-- Date: 2017/6/15
require("CardUtil")

CardDealer = {
	cardStates = {

	}	
}

CardDealer.__index = CardDealer

function CardDealer:new()
	local o = {}
	setmetatable(o, self)

	return o
end

function CardDealer:reset()
	self.cardStates = {}
end

function CardDealer:dealTwoHands()
	local cards = {}
	--math.randomseed(tostring(os.time()):reverse():sub(1, 6))
	while #cards < 2 do
		local suit = math.random(1, 4)
		local rank = math.random(1, 13)
		local str = tostring(suit)..tostring(rank)
		-- print("suit=",suit)
		-- print("rank=",rank)
		-- print("str=",str)
		if self.cardStates[str] == nil then
			self.cardStates[str] = true
			local isHand = true
			local card = Card:new(suit, rank, isHand)
			table.insert(cards, card)
			-- print("insert str=",str)
		end
	end
	return cards
end

function CardDealer:dealPublic(amount)
	if amount < 0 or amount > 5 then
		print("CardDealer:dealPublic#amount error!")
		return
	else
		local cards = {}
		--math.randomseed(tostring(os.time()):reverse():sub(1, 6))
		while #cards < amount do
			local suit = math.random(1, 4)
			local rank = math.random(1, 13)
			local str = tostring(suit)..tostring(rank)
			-- print("suit=",suit)
			-- print("rank=",rank)
			--print("str=",str)
			if self.cardStates[str] == nil then
				self.cardStates[str] = true
				local isHand = false
				local card = Card:new(suit, rank, isHand)
				table.insert(cards, card)
			end
		end
		return cards
	end
end

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者: 你很德布罗意
邮箱: namidame@sina.cn
博客地址: https://www.namidame.tech/
原文地址: http://www.namidame.tech/Lua-Texas.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值