-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathhole_cards.cc
2072 lines (1908 loc) · 67.6 KB
/
hole_cards.cc
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
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "card.h"
#include "hole_cards.h"
#include "community_cards.h"
#include "card_statistics.h"
#include "card_analysis.h"
#include "card_find.h"
HoleCards::HoleCards()
{
ghost_face = 0;
landlord_seat = -1;
table_type = -1;
seatid = -1;
pre_play_seat = -1;
}
void HoleCards::add_card(Card card)
{
cards[card.value] = card;
}
void HoleCards::copy_cards(std::vector<Card> *v)
{
std::map<int, Card>::iterator it;
for (it = cards.begin(); it != cards.end(); it++)
{
v->push_back(it->second);
}
}
void HoleCards::copy_cards(std::vector<int> *v)
{
std::map<int, Card>::iterator it;
for (it = cards.begin(); it != cards.end(); it++)
{
Card &card = it->second;
v->push_back(card.value);
}
}
/*
@brief 获取手上最小的牌
@param includeGhostFace:为false时,表示不找鬼牌
为true时,表示找鬼牌
*/
int HoleCards::get_one_little_card(bool includeGhostFace)
{
std::vector<Card> v;
std::map<int, Card>::iterator it;
for (it = cards.begin(); it != cards.end(); it++)
{
v.push_back(it->second);
}
Card::sort_by_ascending(v);
Card card;
if (includeGhostFace == false)
{
for (unsigned int i = 0; i < v.size(); ++i)
{
if (v[i].face != ghost_face) //除去鬼牌找最大的牌
{
card = v[i];
return card.value;
}
}
}
if (card.value == 0 && v.size() >0)
{
card = v.front();
}
// cards.erase(card.value);
return card.value;
}
/*
@brief 获取手上最大的牌
@param includeGhostFace:为false时,表示不找鬼牌
为true时,表示找鬼牌
*/
int HoleCards::get_one_max_card(bool includeGhostFace)
{
std::vector<Card> v;
std::map<int, Card>::iterator it;
for (it = cards.begin(); it != cards.end(); it++)
{
v.push_back(it->second);
}
Card::sort_by_descending(v);
Card card;
if (includeGhostFace == false)
{
for (unsigned int i = 0; i < v.size(); ++i)
{
if (v[i].face != ghost_face) //除去鬼牌找最大的牌
{
card = v[i];
return card.value;
}
}
}
if (card.value == 0 && v.size() >0)
{
card = v.front();
}
// cards.erase(card.value);
return card.value;
}
void HoleCards::remove(std::vector<Card> &v)
{
for (unsigned int i = 0; i < v.size(); i++)
{
cards.erase(v[i].value);
}
}
void HoleCards::remove(std::vector<int> &v)
{
for (unsigned int i = 0; i < v.size(); i++)
{
cards.erase(v[i]);
}
}
int HoleCards::size()
{
return (int)(cards.size());
}
void HoleCards::debug()
{
Card::dump_cards(cards);
}
/*
@brief 设置other_player_info中某个玩家剩余的牌数
@param seatid[in] 设置的玩家坐位号
@param left_num[in] 该玩家剩余的牌数
@ref 玩家出牌后,服务器会广播出牌玩家剩余牌的数量,机器人调用这个函数记录这个出牌玩家的牌数
*/
void HoleCards::set_left_num_of(int seatid, int left_num)
{
for (unsigned int i = 0; i< other_player_info.size(); ++i)
{
if (other_player_info[i].seatid == seatid)
{
other_player_info[i].cards_left_num = left_num;
return;
}
}
}
/*
@brief 记录其它玩家的一些信息到other_player_info中,用于判断之后如何的出牌
@param seatVec[in] 需要记录玩家的坐位号
@param cardLeft[in] 玩家的剩余牌数
@ref 用于游戏一开始,记录其它玩家的初始信息,目前只记录了坐位号和对应的剩余牌数
*/
void HoleCards::set_other_player_info(vector<int> &seatVec, vector<int> &cardLeft)
{
other_player_info.clear();
for (unsigned i = 0; i < seatVec.size(); ++i)
{
SeatInfo si;
si.seatid = seatVec[i];
si.cards_left_num = cardLeft[i];
other_player_info.push_back(si);
}
}
/**************************机器人相关方法*******************************************/
/****************拆牌的相关方法*************/
/***
* 拆分手上的牌
1. 先确定火箭:判断是否有大小王。
2. 再确定炸弹:判明是否有四头。
3. 再确定三顺:,应该使三顺的数量尽可能大。即如果有444555666,则将其合成一个三顺,而不是分成444555一个三顺和666一个三条。
4. 再确定单顺:判断单顺时必须去除四个2以外的所有炸弹。首先判断是否存在除了三条牌(这里的三条是指所有的三条)以外的连牌,如果有,则将其提取出来。其 次,将剩余的牌与每一个三条(不包含三顺)进行试组合,如果能够重新组成单顺和对子,则将原有的三条取消,重新组合成连牌和单顺(例子4566678重新 组成45678和66)。最后,将已知的连牌、三条(不包含三顺)和剩下的牌张再试组合,将所有如45678(已知的连牌)999(三条)10J(单 牌),重新组合成45678910J和99。通过以上的方法,就能将连牌和三条很好地重新组合。
5. 再确定三条:找不到三顺,则在除了炸弹以外的牌中判断是否包含三条。
6. 再确定双顺:首先,如果两单顺牌完全重合,则将其重新组合成双顺。其次,在除炸弹、三顺、三条、单顺以外的牌中检测是否包含双顺。如果有,将其提取出来。
7. 再确定对子:在炸弹、三顺、三条、连牌、双顺以外的牌中检测是否存在对子,如果存在将其提取出来。
8. 再确定单牌:除了炸弹、三顺、三条、连牌、双顺、对子以外的所有牌张都是单牌。
***/
void HoleCards::split_cards()
{
splitedCards.clear();
splitedTypes.clear();
vector<Card> splits;
copy_cards(&splits);
// cout << "hole_cards.";
// Card::dump_cards(splits, "splits");
split_rocket(splits);
split_bomb(splits);
split_threeline(splits);
split_oneline(splits);
split_three(splits);
split_twoline(splits);
split_two(splits);
split_one(splits);
}
/****拆牌的工具方法****/
void HoleCards::split_rocket(vector<Card> &splits)
{
if (splits.size() < 2) return;
//这里不用card_statistics是怕影响效率
vector<Card>::iterator ite;
vector<Card>::iterator ite2;
ite = find(splits.begin(), splits.end(), Card(14));
ite2 = find(splits.begin(), splits.end(), Card(15));
if (ite != splits.end() &&
ite2 != splits.end())
{
vector<Card> cards;
cards.push_back(*ite);
cards.push_back(*ite2);
ite2 = splits.erase(ite);
splits.erase(ite2);
splitedCards.push_back(cards);
splitedTypes.push_back(CARD_TYPE_ROCKET);
// cout << "split_rocket.";
// Card::dump_cards(splits, "splits");
}
}
void HoleCards::split_bomb(vector<Card> &splits)
{
if (splits.size() < 4) return;
CardFind cf;
vector<Card> compareCard;
compareCard.resize(1);
cf.find(compareCard, splits, CARD_TYPE_ONE, Card::Big, ghost_face);
vector<Card>::iterator ite;
int gret = cf.has_bomb_type_of(CARD_TYPE_GHOSTBOMB);
if (gret >= 0)
{
vector<Card> cards;
for( unsigned i = 0; i<cf.results[gret].size(); ++i )
{
ite = find(splits.begin(), splits.end(), cf.results[gret][i]);
cards.push_back(*ite);
splits.erase(ite);
}
splitedCards.push_back(cards);
splitedTypes.push_back(CARD_TYPE_GHOSTBOMB);
// cout << "split_ghostbomb.";
// Card::dump_cards(splits, "splits");
}
int ret = cf.has_bomb_type_of(CARD_TYPE_BOMB);
while (ret >= 0)
{
vector<Card> cards;
for( unsigned i = 0; i<cf.results[ret].size(); ++i )
{
ite = find(splits.begin(), splits.end(), cf.results[ret][i]);
cards.push_back(*ite);
splits.erase(ite);
}
splitedCards.push_back(cards);
splitedTypes.push_back(CARD_TYPE_BOMB);
// cout << "split_bomb.";
// Card::dump_cards(splits, "splits");
if (splits.size() < 4) return;
cf.find(compareCard, splits, CARD_TYPE_ONE, Card::Big, ghost_face);
ret =cf.has_bomb_type_of(CARD_TYPE_BOMB);
}
ret = cf.has_bomb_type_of(CARD_TYPE_SOFTBOMB);
while (ret >= 0 && gret == -1)
{
vector<Card> cards;
for( unsigned i = 0; i<cf.results[ret].size(); ++i )
{
ite = find(splits.begin(), splits.end(), cf.results[ret][i]);
cards.push_back(*ite);
splits.erase(ite);
}
splitedCards.push_back(cards);
splitedTypes.push_back(CARD_TYPE_SOFTBOMB);
// cout << "split_softbomb.";
// Card::dump_cards(splits, "splits");
if (splits.size() < 4) return;
cf.find(compareCard, splits, CARD_TYPE_ONE, Card::Big, ghost_face);
ret =cf.has_bomb_type_of(CARD_TYPE_SOFTBOMB);
}
}
void HoleCards::split_threeline(vector<Card> &splits)
{
while (find_max_len_threeline(splits))
{
// cout << "split_threeline.";
// Card::dump_cards(splits, "splits");
}
}
void HoleCards::split_three(vector<Card> &splits)
{
while (find_splite_three(splits))
{
// cout << "split_three.";
// Card::dump_cards(splits, "splits");
if (splits.size() < 3) return;
}
}
void HoleCards::split_oneline(vector<Card> &splits)
{
int lineCnt = 0;
while (find_max_len_oneline(splits))
{
++lineCnt;
// cout << "split_oneline.";
// Card::dump_cards(splits, "splits");
}
//合并相同的单顺
int index = splitedCards.size() - lineCnt;
for (unsigned nindex = index + 1; nindex < splitedCards.size(); ++index, ++nindex)
{
if (splitedCards[index] == splitedCards[nindex])
{
std::copy(splitedCards[nindex].begin(), splitedCards[nindex].end(), back_inserter(splitedCards[index]));
std::sort(splitedCards[index].begin(), splitedCards[index].end());
splitedTypes[index] = CARD_TYPE_TWOLINE;
splitedTypes[nindex] = -1;
splitedCards[nindex].resize(0);
}
}
//删除合并的单顺
vector<vector<Card> >::iterator ite = splitedCards.begin();
for(; ite != splitedCards.end();)
{
if (ite->size() == 0)
ite = splitedCards.erase(ite);
else
++ite;
}
//删除合并的单顺记录的类型
vector<int>::iterator ite2 = splitedTypes.begin();
for(; ite2 != splitedTypes.end();)
{
if (*ite2 == -1)
ite2 = splitedTypes.erase(ite2);
else
++ite2;
}
}
void HoleCards::split_twoline(vector<Card> &splits)
{
while (find_max_len_twoline(splits))
{
// cout << "split_twoline.";
// Card::dump_cards(splits, "splits");
}
}
void HoleCards::split_two(vector<Card> &splits)
{
if (splits.size() < 2 ) return;
CardStatistics splits_stat(splits, ghost_face);
Card::sort_by_descending(splits_stat.card2);
for (unsigned i = 0; i < splits_stat.card2.size(); i += 2)
{
vector<Card> cards;
cards.push_back(splits_stat.card2[i]);
cards.push_back(splits_stat.card2[i+1]);
delete_cards_from_splits(splits, cards, CARD_TYPE_TWO);
// cout << "split_two. ";
// Card::dump_cards(splits, "splits");
}
if (splits_stat.ghost_cards.size() == 2)
{
vector<Card> cards;
cards.push_back(splits_stat.ghost_cards[0]);
cards.push_back(splits_stat.ghost_cards[1]);
delete_cards_from_splits(splits, cards, CARD_TYPE_TWO);
// cout << "split_two. ";
// Card::dump_cards(splits, "splits");
}
}
void HoleCards::split_one(vector<Card> &splits)
{
if (splits.size() == 0) return;
vector<Card>::iterator ite;
Card::sort_by_descending(splits);
for(ite = splits.begin(); ite != splits.end();)
{
vector<Card> cards;
cards.push_back(*ite);
splitedCards.push_back(cards);
splitedTypes.push_back(CARD_TYPE_ONE);
ite = splits.erase(ite);
// cout << "split_one. ";
// Card::dump_cards(splits, "splites");
}
}
//计算三顺最大的牌面值个数
int HoleCards::calc_max_line_cnt_of(const CardStatistics &my_card_stat)
{
int max_cnt = my_card_stat.line3.size() / 3;
int diceCnt = my_card_stat.ghost_cards.size();
int card2Size = my_card_stat.card2.size();
int card1Size = my_card_stat.card1.size();
if (diceCnt > 0)
{
if (diceCnt >card2Size)
{
max_cnt += card2Size;
diceCnt -= card2Size;
if (diceCnt > card1Size*2)
{
max_cnt += card1Size;
diceCnt -= card1Size * 2;
}
else
{
max_cnt += diceCnt / 2;
}
}
else
{
max_cnt += diceCnt;
}
}
return max_cnt;
}
//找长度最大的三顺,如果找到,则从splits中删除,加到splitedCards中
bool HoleCards::find_max_len_threeline(vector<Card> &splits)
{
if (splits.size() < 6) return false;
CardStatistics my_card_stat(splits, ghost_face);
vector<Card> cards;
std::merge(my_card_stat.card1.begin(), my_card_stat.card1.end(),
my_card_stat.card2.begin(), my_card_stat.card2.end(), back_inserter(cards)); //merge合并后依然是有序的,不用排序
std::copy(my_card_stat.line3.begin(), my_card_stat.line3.end(), back_inserter(cards));
std::sort(cards.begin(), cards.end());
CardAnalysis cardAna;
int max_cnt = calc_max_line_cnt_of(my_card_stat);
for (unsigned cnt = max_cnt; cnt >= 2; --cnt)
{//从可能最长的三顺开始找
int diff = my_card_stat.len - cnt * 3;
for (int index = 0; index <= diff; ++index)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (unsigned i = anaCards.size(), j = 0; i < static_cast<unsigned>(cnt * 3); ++i, ++j)
{ //加入其它牌
anaCards.push_back(cards[index + j]);
}
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_THREELINE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_THREELINE);
return true;
}
}
}
return false;
}
//找长度最大的双顺,如果找到,则从splits中删除,加到splitedCards中
bool HoleCards::find_max_len_twoline(vector<Card> &splits)
{
if (splits.size() < 6 && splits.size() % 2 == 0)
return false;
CardStatistics my_card_stat(splits, ghost_face);
vector<Card> cards;
std::copy(my_card_stat.line2.begin() ,my_card_stat.line2.end(), back_inserter(cards));
CardAnalysis cardAna;
for (unsigned i = 0; i < cards.size(); i+=2)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (unsigned j = i; j < cards.size(); ++j)
{ //加入其它牌
anaCards.push_back(cards[j]);
}
if (anaCards.size() < 6)
break;
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_TWOLINE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_TWOLINE);
return true;
}
}
for (int i = cards.size() - 1; i >= 0; i-=2)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (int j = 0; j <= i; ++j)
{ //加入其它牌
anaCards.push_back(cards[j]);
}
if (anaCards.size() < 6)
break;
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_TWOLINE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_TWOLINE);
return true;
}
}
return false;
}
//找长度最大的顺子,如果找到,则从splits中删除,加到splitedCards中
bool HoleCards::find_max_len_oneline(vector<Card> &splits)
{
if (splits.size() < 5)
return false;
CardStatistics my_card_stat(splits, ghost_face);
vector<Card> cards;
std::copy(my_card_stat.line1.begin() ,my_card_stat.line1.end(), back_inserter(cards));
CardAnalysis cardAna;
for (unsigned i = 0; i < cards.size(); ++i)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (unsigned j = i; j < cards.size(); ++j)
{ //加入其它牌
anaCards.push_back(cards[j]);
}
if (anaCards.size() < 5)
break;
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_ONELINE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_ONELINE);
return true;
}
}
for (int i = cards.size() - 1; i >= 0; --i)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (int j = 0; j <= i; ++j)
{ //加入其它牌
anaCards.push_back(cards[j]);
}
if (anaCards.size() < 5)
break;
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_ONELINE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_ONELINE);
return true;
}
}
return false;
}
//找三张,如果找到,则从splits中删除,加到splitedCards中
bool HoleCards::find_splite_three(vector<Card> &splits)
{
if (splits.size() < 3)
return false;
CardStatistics my_card_stat(splits, ghost_face);
vector<Card> cards;
std::merge(my_card_stat.card1.begin(), my_card_stat.card1.end(),
my_card_stat.card2.begin(), my_card_stat.card2.end(), back_inserter(cards)); //merge合并后依然是有序的,不用排序
std::copy(my_card_stat.line3.begin(), my_card_stat.line3.end(), back_inserter(cards));
std::sort(cards.begin(), cards.end());
CardAnalysis cardAna;
int diff = my_card_stat.len - 3;
for (int index = 0; index <= diff; ++index)
{
vector<Card> anaCards = my_card_stat.ghost_cards;
for (unsigned i = anaCards.size(), j = 0; i < 3; ++i, ++j)
{ //加入其它牌
anaCards.push_back(cards[index + j]);
}
cardAna.analysis(anaCards, ghost_face);
if (cardAna.get_card_face_of_type(CARD_TYPE_THREE) != 0)
{
delete_cards_from_splits(splits, anaCards, CARD_TYPE_THREE);
return true;
}
}
return false;
}
//从splits中删除anaCards的牌
void HoleCards::delete_cards_from_splits(vector<Card> &splits, const vector<Card> &anaCards, int splitType)
{
vector<Card>::iterator ite;
vector<Card> cards;
for(unsigned i = 0 ; i < anaCards.size(); ++i)
{
// ite = std::find(splits.begin(), splits.end(), anaCards[i]);
unsigned j = 0;
for(; j < splits.size(); ++j)
{
if (splits[j].value == anaCards[i].value)
break;
}
cards.push_back(*(splits.begin() + j));
splits.erase(splits.begin() + j);
}
splitedCards.push_back(cards);
splitedTypes.push_back(splitType);
}
/****************robot的相关方法*************/
/*
@brief 玩家从手牌中选则一个合理的牌打出。
@param v[out] 返回应该打出去的牌
*/
void HoleCards::robot(std::vector<Card> &v)
{
int ret = check_three_with_other();
int ret_type = 0;
if (ret > 0)
{
bool has_bao_dan = false; //记录非队友是否有报单的
bool has_bao_shuang = false; //记录非队友是否有报双
get_dan_shuang(has_bao_dan, has_bao_shuang);
//出单牌
if (!has_bao_dan)
{ //敌家没报单,尝试出单牌
ret = get_smallest_type_of(CARD_TYPE_ONE);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_ONE;
}
}
else if (has_bao_dan && (splitedTypes.size() - count_type_of(CARD_TYPE_ONE) == 0))
{ //敌家报单,玩家只有单牌可出
//计算庄家是否为下家
bool next_seat_is_zhuang = ((landlord_seat - seatid) % 3 == 1);
if (landlord_seat == seatid || next_seat_is_zhuang)
{ //自己是庄家,或下家就是庄家,则出最大的
Card max_card(get_one_max_card());
if (max_card.face > 0)
{
v.pop_back();
v.push_back(max_card);
}
}
else
{ //下家是友军,庄家报单,出最小的单牌没事,有下家可以罩着。
ret = get_smallest_type_of(CARD_TYPE_ONE);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_ONE;
}
}
}
//出对子
else if (!has_bao_shuang) //敌家没报双,尝试出对子
{
ret = get_smallest_type_of(CARD_TYPE_TWO);
if (ret >=0 )
{
v = splitedCards[ret];
ret_type = CARD_TYPE_TWO;
}
}
else if (has_bao_dan && (splitedTypes.size() - count_type_of(CARD_TYPE_TWO) == 0))
{ //敌家报双,玩家只有对子可出
Card max_card(get_one_little_card(false));
if (max_card.face > 0) //找一个最小的牌打出去,拆他人的对子
{
v.clear();
v.push_back(max_card);
}
}
//如果只有对子和单牌,且敌家即有报双,又有报单的情况
else if (has_bao_dan && has_bao_shuang &&
(static_cast<int>(splitedTypes.size()) == count_type_of(CARD_TYPE_ONE) + count_type_of(CARD_TYPE_TWO)))
{
Card max_card(get_one_max_card(true));
if (max_card.face > 0) //找一个最大的牌打出去
{
v.clear();
v.push_back(max_card);
}
}
}
else
{
switch(0)
{
case 0: //双顺
ret = get_smallest_type_of(CARD_TYPE_TWOLINE);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_TWOLINE;
break;
}
case 1://连牌
ret = get_smallest_type_of(CARD_TYPE_ONELINE);
if (ret >=0 )
{
v = splitedCards[ret];
ret_type = CARD_TYPE_ONELINE;
break;
}
case 2: //出三顺
ret = get_smallest_type_of(CARD_TYPE_THREELINE);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = calc_with_cards(v);
break;
}
case 3: //出三条
ret = get_smallest_type_of(CARD_TYPE_THREE);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = calc_with_cards(v);
break;
}
case 4: //炸弹
ret = get_smallest_type_of(CARD_TYPE_SOFTBOMB);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_SOFTBOMB;
break;
}
case 5:
ret = get_smallest_type_of(CARD_TYPE_BOMB);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_BOMB;
break;
}
case 6:
ret = get_smallest_type_of(CARD_TYPE_GHOSTBOMB);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_GHOSTBOMB;
break;
}
case 7: //火箭
ret = get_smallest_type_of(CARD_TYPE_ROCKET);
if (ret >= 0)
{
v = splitedCards[ret];
ret_type = CARD_TYPE_ROCKET;
break;
}
}
}
if (ret_type == 0) return ;
//特殊处理
special_condition_check(v, ret_type, false);
}
/***robot的工具方法****/
//检测单牌和对子与三条,三顺组合,是否还有多余的单牌和顺子
int HoleCards::check_three_with_other()
{
int threeCnt = count_threeline_three() + count_type_of(CARD_TYPE_THREE);
//首先与对子组合
int twoCnt = count_type_of(CARD_TYPE_TWO);
if (twoCnt - threeCnt > 0)
return twoCnt - threeCnt;
//与单牌组合
int oneCnt = count_type_of(CARD_TYPE_ONE);
oneCnt += twoCnt; //对子可拆,看成两个单牌
return oneCnt - threeCnt;
}
//计算三顺中三个的个数
int HoleCards::count_threeline_three()
{
int cnt = 0;
for (unsigned i = 0; i < splitedTypes.size(); ++i)
{
if(splitedTypes[i] == CARD_TYPE_THREELINE)
{
cnt += splitedCards[i].size() / 3;
}
}
return cnt;
}
//计算type拆出的个数
int HoleCards::count_type_of(int type)
{
int cnt = 0;
vector<int>::iterator ite = splitedTypes.begin();
for(; ite != splitedTypes.end(); ++ite)
{
if (*ite == type)
{
++cnt;
}
}
return cnt;
}
//获取手牌中炸弹的个数,包括火箭
int HoleCards::get_bomb_size()
{
int cnt = 0;
for(int i = splitedTypes.size() -1; i >= 0; --i)
{
if(splitedTypes[i] >= CARD_TYPE_SOFTBOMB)
{
++cnt;
}
}
return cnt;
}
//获取type类型中最小的那个,并返回最小的在splitedCards中的下标
int HoleCards::get_smallest_type_of(int type)
{
for(int i = splitedTypes.size() -1; i >= 0; --i)
{
if(splitedTypes[i] == type)
{
return i;
}
}
return -1;
}
//计算三带多时,需要带什么牌
int HoleCards::calc_with_cards(vector<Card> &v)
{
//与单牌组合
int threeLineCnt = count_threeline_three();
if (threeLineCnt == 0) //说明没有三顺,只有三张
{
if (count_type_of(CARD_TYPE_THREE) == 0)
return 0; //三张都没有,这个函数就不应该被调用
threeLineCnt = 1;
}
const int oneCnt = count_type_of(CARD_TYPE_ONE);
const int twoCnt = count_type_of(CARD_TYPE_TWO);
// const int threeCnt = count_type_of(CARD_TYPE_THREE);
if (threeLineCnt > oneCnt + twoCnt *2 /*+ threeCnt *3*/)
{
int lessCard = threeLineCnt - (oneCnt + twoCnt *2); //带的牌不够,减去lessCard的数量的三张
if (lessCard == threeLineCnt) //没有带的牌, 直接出三连
{
if (v.size() == 3)
return CARD_TYPE_THREE;
return CARD_TYPE_THREELINE;
}
for(int i = 0; i< lessCard; ++i)
{
v.pop_back();
v.pop_back();
v.pop_back();
}
threeLineCnt = oneCnt + twoCnt *2;
}
int leftOne = oneCnt - threeLineCnt;
bool oneBiggerThenK = false; //是否要带出A和2
vector<Card> oneOut;
vector<Card> oneBigOut;
// if (leftOne >= 0) //单牌足够
// {
int cnt = 0;
for(int i = splitedTypes.size() -1; i >= 0; --i)
{
if(splitedTypes[i] == CARD_TYPE_ONE)
{
++cnt;
if (splitedCards[i][0].face > Card::King)
{
oneBiggerThenK = true;
oneBigOut.push_back(splitedCards[i][0]);
}
else
{
oneOut.push_back(splitedCards[i][0]);
}
if (cnt == threeLineCnt)
break;
}
}
//单牌够,且面值都小于A,则带出,否则在双牌也不够的时候拆小的对子
if (leftOne >= 0 && oneBiggerThenK == false)
{
std::copy(oneOut.begin(), oneOut.end(), back_inserter(v));
if (v.size() == 4)
return CARD_TYPE_THREEWITHONE;
return CARD_TYPE_PLANEWITHONE;
}
// }
//与对子组合
int leftTwo = twoCnt - threeLineCnt;
bool pairBiggerThenK = false; //是否要带出AA和22
vector<Card> twoOut;
vector<Card> twoBigOut;
// if (leftTwo >= 0) //对子足够
// {
cnt = 0;
for(int i = splitedTypes.size() -1; i >= 0; --i)
{
if(splitedTypes[i] == CARD_TYPE_TWO)
{
++cnt;
if (splitedCards[i][0].face > Card::King)
{
pairBiggerThenK = true;
twoBigOut.push_back(splitedCards[i][0]);
twoBigOut.push_back(splitedCards[i][1]);
}
else
{
twoOut.push_back(splitedCards[i][0]);
twoOut.push_back(splitedCards[i][1]);
}
if (cnt == threeLineCnt)
break;
}
}
//双牌够,且面值都小于A,则带出
if (leftTwo >= 0 && pairBiggerThenK == false)
{
std::copy(twoOut.begin(), twoOut.end(), back_inserter(v));
if (v.size() == 5)
return CARD_TYPE_THREEWITHTWO;
return CARD_TYPE_PLANEWITHWING;
}
// }
//带A以下的单牌,然后拆对子。
std::copy(oneOut.begin(), oneOut.end(), back_inserter(v));
int left = threeLineCnt - oneOut.size(); //还拆的个数
if (left % 2 == 1 && oneBigOut.size() > 0)
{//成单,少拆对子
v.push_back(oneBigOut[0]);
oneBigOut.erase(oneBigOut.begin());
--left;
}
if (left <= static_cast<int>(twoOut.size()))
{ //小的对子够,拆小的对子
for(int i = 0; i<left; ++i)
{
v.push_back(twoOut[i]);
}
if (v.size() == 4)
return CARD_TYPE_THREEWITHONE;
return CARD_TYPE_PLANEWITHONE;
}
else
{ //小的不够,算上所有小的对子
std::copy(twoOut.begin(), twoOut.end(), back_inserter(v));
left -= twoOut.size();
if (static_cast<int>(oneBigOut.size()) <= left )
{ //将大单牌也算上
std::copy(oneBigOut.begin(), oneBigOut.end(), back_inserter(v));
left -= oneBigOut.size();
}
if (left > 0 && static_cast<int>(twoBigOut.size()) >= left)
{ //拆大的对子
for(int i =0; i<left; ++i)
{
v.push_back(twoBigOut[i]);
}