目录
1算法分析 2
1.1发牌 2
1.1.1随机发牌 2
1.1.2指定手牌 2
1.2搜索可以出的手牌组合 2
1.3搜索可以最快出完所有牌的出牌策略 3
1.4按照最优 score 搜索出牌策略 3
1.5 1v1 对战 4
2UI 界面 4
3总结 9
1算法分析
1.1发牌
1.1.1随机发牌
首先生成一个从 1∼54 按顺序排列的数组,再利用 random.shuffle 将其打乱顺序,根据输入的牌的数量 pokerCnt,截取前 pokerCnt 个元素作为手牌,利用扑克牌类 Poker 生成一个扑克牌数组, 利用 sort 函数将手牌从小到大进行排序,存入初始节点中作为初始状态。
1.1.2指定手牌
输入一个扑克牌数组,其中每个元素为包含扑克牌的点数和花色的元组,利用该数组生成初始手牌。
1.2搜索可以出的手牌组合
对于每个节点,在构造函数中首先遍历存入的扑克牌状态数组,得到每个点数的牌的数量,存在一个字典 pokerCtn 中,再利用 OrderedDict 生成一个可以出的扑克牌组合的字典 possibleStep, 字典的键从三顺子到单牌依次添加,这样在后续迭代搜索中可以按照需要的优先级顺序进行遍历。
首先根据根据每个点数扑克牌的数量添加可以出的单牌,添加的顺序按照扑克牌数量从小到大进行添加,这样可以减少拆牌的可能性,每种点数的牌只添加一张牌。对子牌、三张牌和炸弹也按照这种方式进行添加,为了便于后续的计算,火箭也算作对子牌进行添加。
之后搜索三带一、三带二的牌的组合,依次对得到的三张牌的列表和单牌的列表进行遍历,遍历过程中注意判断三张牌和单排是否为同一点数,由于单牌再搜索时按照扑克牌数量进行添加,可以保证三带一带走的单牌优先为一张单牌。三带二的搜索也同理,我在搜索中认为火箭不算对子牌。
搜索四带二、四带二对和上述的方法类似,遍历四张牌的列表和单牌的列表,如果单牌和四张牌点数不同,再对单牌列表中该单牌后续的牌进行遍历搜索,这样可以避免重复,我在作业中认为对子牌也可以认为是两张单牌,因此四带二搜索过程中除了搜索四带两张不同的单牌外还需搜索四带一对。四带二对的搜索过程类似,注意火箭不算对子牌。
搜索顺子牌时,遍历 pokerCnt 中的元素,得到当前牌的点数,如果该点数牌的数量满足要求, 就将其存入一个临时列表中,并利用 Poker 中的 get_next_poker_num 的函数得到下一个需要的点数,如果下一个需要的点数的牌的数量同样满足要求,就将其 append 入列表,直到对应后续点数牌的数量不满足要求,或者搜索到 2 或双王为止。如果该临时列表的长度满足顺子的要求,就将该临时列表存入 possibleStep 中,并不断去除该列表的最后一个元素,如果新的临时列表满足长度要求,就把去除最后一个元素后的列表存入 possibleStep 中,重复上述步骤直到长度不满足要求为止。