我有一个代表扑克牌的元组列表:hand = [('A', '♣'), ('A', '♠'), ('A', '♦'), ('A', '♥'), ('K', '♠')]
我想检查是否有同花顺。
我想过使用all(h[1] == '♠' for h in hand)
并且它似乎运作良好(False
在这种情况下,但True
在其他情况下,它应该在哪里。当然我'我需要检查所有4件套装...... ),但我想知道这是否是正确/最佳方式
答案 0 :(得分:1)
你可以:
any(all(h[1] == suit for h in hand) for suit in ('♣','♠','♦','♥'))
在我看来,这不是非常有效但非常易读,或者你可以按照@Ev的建议去做。 Kounis在评论中,这是一个更有效的解决方案,但不是很可读。由于这个游戏每张牌只有52张牌,4套西装,13套和每张5张牌,所以数字不是很大,以至于他们需要任何特殊的处理来提高效率,所以我会选择这个解决方案。
答案 1 :(得分:0)
要添加到Ofer Sadans的答案,我建议使用标志来表示卡片,因为计算机更容易通过bitwise operators
来计算整数而不是unicode string manipulation。
此解决方案需要从元组类型到整数表示的某种转换,但可以使用简单的lambda函数。
card = ('K','\u2660') # for example. K ♠
card_pack = lambda c: (ord(c[0])<<16)+ord(c[1]) #c for card
# where you have now 32 bit integer that contains all your values
# 00000000-01001011|00100110-01100000 == 4 925 024
# KING | SPADE
使用这个版本你可以(只要你手中有一定数量的牌)制作一只手long integer
并检查一只手。使用预制masks
,您可以使用单个==
逻辑运算符轻松检查所有套牌和值。
hand = [('A', u'\u2663'), ('A', u'\u2660'), ('A', u'\u2666'), ('A', u'\u2665'), ('K', u'\u2660')]
hand_i = map( card_pack, hand )
hand_i = sum( [ val<<( shift*32 ) shift,val in enumerate(hand_i) ] )
然后,如果您需要,可以使用unpacking
功能解压每张卡片:
card_unpack = lambda ci: ( (ci>>16)&0xffff, ci&0xffff) #ci for card integer
unpack_2_individual_cards = lambda hand_i,_i: (hand_i>>(32*_i))&0xffffffff
# then you just need to do similar function as summing for hand_i but inverse to get each card individual and use unichr/chr to represent values after that.
hand = [ unpack_2_individual_cards(hand_i, i ) for i in range(5) ]
然后对手的力量或手的类型进行测试将很容易:
STRAIGHT = 1675898824200706064573121072408259537242498659
if hand_i&STRAIGHT==STRAIGHT: print('you have straight')
if hand_i < STRAIGHT: print('straight wins!!')
请记住,任何逻辑操作(使用all
和any
)都会使用相同的方法来查找元素之间的逻辑关系。只是这种方法的水平很低,以至于它在表面之下。我们比较的数据类型对我们来说是程序员,但对于计算机而言,只要我们告诉它在哪里找到它,它们都是一样的。
您可以使用struct
模块打包和解包数据,而不是那些 lambdas
,您可以使用简单的{{{}屏蔽检查特定的套牌类型。 1}}和0x00ff00ff00ff00ff00ff
手中的值,因为所有卡都由0xff00ff00ff00ff00ff00
打包。