你很德布罗意的技术博客

德州扑克牌型算法-Lua代码实现

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

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

main.lua

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
-- 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

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
-- 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

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
-- 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

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-- 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

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-- 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

专题:

本文发表于 2017-06-15,最后修改于 2020-10-19。

本站永久域名www.namidame.tech,也可搜索「 你很德布罗意的技术博客 」找到我。

欢迎关注我的 微博 ,查看最近的文章和动态。


上一篇 « Cocos2dx-Lua 3.10 + Sublime Text3开发环境搭建 下一篇 » Android友盟SDK微信授权登录接入

赞赏支持

客官,打赏一个呗~

i ali

支付宝

i wechat

微信

推荐阅读

Big Image