高效查表判断胡牌算法的lua版本
来源:互联网 发布:mac u盘复制文件 编辑:程序博客网 时间:2024/05/21 09:40
来源于日本论坛的一套用于麻将的判断胡牌算法,运用查表方式实现。原文链接(http://hp.vector.co.jp/authors/VA046927/mjscore/mjalgorism.html)
原算法是java实现,这里移植为lua版本。
移植为lua版本的代码如下
local M = {}local MAN1 = 0local MAN2 = 1local MAN3 = 2local MAN4 = 3local MAN5 = 4local MAN6 = 5local MAN7 = 6local MAN8 = 7local MAN9 = 8local PIN1 = 9local PIN2 = 10local PIN3 = 11local PIN4 = 12local PIN5 = 13local PIN6 = 14local PIN7 = 15local PIN8 = 16local PIN9 = 17local SOU1 = 18local SOU2 = 19local SOU3 = 20local SOU4 = 21local SOU5 = 22local SOU6 = 23local SOU7 = 24local SOU8 = 25local SOU9 = 26local TON = 27local NAN = 28local SHA = 29local PEI = 30local HAK = 31local HAT = 32local CHU = 33local PRINT_MAP = { [0] = "一万", [1] = "二万", [2] = "三万", [3] = "四万", [4] = "五万", [5] = "六万", [6] = "七万", [7] = "八万", [8] = "九万", [9] = "一条", [10] = "二条", [11] = "三条", [12] = "四条", [13] = "五条", [14] = "六条", [15] = "七条", [16] = "八条", [17] = "九条", [18] = "一筒", [19] = "二筒", [20] = "三筒", [21] = "四筒", [22] = "五筒", [23] = "六筒", [24] = "七筒", [25] = "八筒", [26] = "九筒", [27] = "东风", [28] = "南风", [29] = "西风", [30] = "北风", [31] = "红中", [32] = "发财", [33] = "白板",}function M:init() self.tbl = require "hupai_table"end--==============================----desc: 计算每一种牌的个数,1-9万、1-9索、1-9筒、东南西北中发白共34种牌--@hai: 玩家的手牌--return 返回每种牌个数的数组--==============================--function M:analyse(hai) local n = {} for i = 0, 33 do n[i] = 0 end for _, v in ipairs(hai) do n[v] = n[v] + 1 end return nend-- key对应的值定义-- 3bit 0: 刻子の数(0~4)-- 3bit 3: 順子の数(0~4)-- 4bit 6: 頭の位置(1~13)-- 4bit 10: 面子の位置1(0~13)-- 4bit 14: 面子の位置2(0~13)-- 4bit 18: 面子の位置3(0~13)-- 4bit 22: 面子の位置4(0~13)-- 计算牌型对应的key值function M:calc_key(n, pos) local p = -1 local x = 0 local pos_p = 0 local b = false local tmp = 0 -- 数牌(万、索、筒) for i = 0, 2 do for j = 0, 8 do if n[i * 9 + j] == 0 then if b then b = false x = x | (0x1 << p) p = p + 1 end else p = p + 1 b = true pos[pos_p] = i * 9 + j pos_p = pos_p + 1 tmp = n[i * 9 + j] if tmp == 2 then x = x | (0x3 << p) p = p + 2 elseif tmp == 3 then x = x | (0xf << p) p = p + 4 elseif tmp == 4 then x = x | (0x3f << p) p = p + 6 end end end if b then b = false x = x | (0x1 << p) p = p + 1 end end -- 字牌 for i = TON, CHU do if n[i] > 0 then p = p + 1 pos[pos_p] = i pos_p = pos_p + 1 tmp = n[i] if tmp == 2 then x = x | (0x3 << p) p = p + 2 elseif tmp == 3 then x = x | (0xf << p) p = p + 4 elseif tmp == 4 then x = x | (0x3f << p) p = p + 6 end x = x | (0x1 << p) p = p + 1 end end return xend-- 获取key值对应的胡牌值(包括:刻子个数、顺子个数、雀头、刻子值、顺子值(顺子第一张牌值)、其他特殊胡牌类型)function M:agari(key) return self.tbl[key]end-- 计算是否胡牌-- 牌值定义:0-26: 万条筒,27-33:字牌(东南西北中发白)-- 传入参数是非亮牌外的正常手牌,加上自摸(或吃、碰)到的牌,可能是14、11、8、5、2张牌-- 返回胡牌类型function M:check_hupai(hai) local pos = {} local n = self:analyse(hai) local key = self:calc_key(n, pos) local ret = self:agari(key) if not ret then return false end local hu = false local tbl = {} -- 保存胡牌结果 for _, r in ipairs(ret) do hu = true tbl.duizi = pos[(r >> 6) & 0xf] print("雀头=", tbl.duizi, PRINT_MAP[tbl.duizi]) local num_kotsu = r & 0x7 local num_shuntsu = (r >> 3) & 0x7 tbl.kezi = {} for i = 0, num_kotsu - 1 do table.insert(tbl.kezi, pos[(r >> (10 + i * 4)) & 0xf]) print("刻子=", tbl.kezi[i + 1], PRINT_MAP[tbl.kezi[i + 1]]) end tbl.shunzi = {} for i = 0, num_shuntsu - 1 do table.insert(tbl.shunzi, pos[(r >> (10 + num_kotsu * 4 + i * 4)) & 0xf]) print("顺子=", tbl.shunzi[i + 1], PRINT_MAP[tbl.shunzi[i + 1]]) end end return hu, tblendfunction M:test() local hai = { MAN1, MAN1, MAN1, MAN2, MAN3, MAN4, MAN6, MAN7, MAN8, TON, TON, TON, SHA, SHA } local n local pos = {} local ret local t = os.time() for i = 1, 1000000 do n = self:analyse(hai) local key = self:calc_key(n, pos) ret = self:agari(key) end print(string.format("cost time: %ds", os.time()-t)) for _, r in ipairs(ret) do print("雀头=", pos[(r >> 6) & 0xf]) local num_kotsu = r & 0x7 local num_shuntsu = (r >> 3) & 0x7 for i = 0, num_kotsu - 1 do print("刻子=", pos[(r >> (10 + i * 4)) & 0xf]) end for i = 0, num_shuntsu - 1 do print("顺子=", pos[(r >> (10 + num_kotsu * 4 + i * 4)) & 0xf]) end endendreturn M
胡牌表定义hupai_table.lua
return { [0x74444] = {0x258c320}, [0x47444] = {0x298c260}, [0x44744] = {0x29cc1a0}, [0x44474] = {0x29d00e0}, [0x44447] = {0x29d0420}, [0x3a220] = {0x258c320}, -- 由于表较大,此处省略中间部分 [0x23a20] = {0x298c260}, [0x223a0] = {0x29cc1a0}, [0x3a204] = {0x258c320}, [0x23a04] = {0x298c260}, [0x3a044] = {0x258c320}, [0x20744] = {0x29cc1a0},}
测试代码
local logic_hupai = require "logic_hupai"logic_hupai:init()logic_hupai:test()
测试数据显示判断胡牌100万次耗时7秒。测试环境为Linux系统,单核CPU,2G内存。
阅读全文
0 0
- 高效查表判断胡牌算法的lua版本
- 带赖子的胡牌算法lua版本
- 高效判断素数的算法
- javascript高效的判断浏览器种类和版本
- javascript高效的判断浏览器种类和版本
- 带癞子麻将查表判断胡牌高效率低内存算法
- 素数判断算法(高效)
- 大素数高效算法判断
- 判断n以内的素数(高效算法)
- lua中高效的HashMap
- 高效的nextPrime算法(参考l链接中的高效的素数判断)
- CString的高效版本
- 素数的高效判断
- 编写高效Lua代码的方法 - 2 - 表相关
- 带赖子的超高效麻将、跑胡子胡牌算法
- 高效质数判断算法及其JS实现
- 计算CRC7表的高效算法
- 判断大小写的高效方式
- 编辑距离问题
- java异常处理
- NEUQ-OJ:1177 亲和数
- 计算机组成原理复习总结
- Android 积累一些RxJava2.0有关的知识
- 高效查表判断胡牌算法的lua版本
- DokuWiki表格项垂直居中的方法
- VC++ 只运行一个程序实例
- centos 7 搭建mysql数据库
- reactjs 编写一个简单的图片轮播图
- R语言绘制ROC曲线如何画在一个图中
- MySQL中单句实现无限层次父子关系查询
- java消息队列ActiveMQ之Comsumer
- Eclipse | Eclipse安装中文版本教程