第一讲主要是做一个扑克牌游戏,主要是扑克牌规则的设计。复用了max函数。涉及到了重构和测试的概念,以及在程序编写过程中需要注意Correctness,effeciency, feature和elegance四方面。以下是较完整代码:
import random
def poker(hands):
"""Return a list of winning hands: poker([hand,...]) => [hand,...]"""
return allmax(hands, key=hand_rank)
def allmax(iterable, key=None):
"""Return a list of all items equal to the max of the iterable."""
# maxv = hand_rank(max(iterable, key=key))
# maxl = []
# for item in iterable:
# if hand_rank(item) == maxv:
# maxl.append(item)
# return maxl if len(maxl) > 0 else None
result, maxval = [], None
key = key or (lambda x: x)
for x in iterable:
xval = key(x)
if not result or xval>maxval:
result, maxval = [x], xval
elif xval == maxval:
result.append(x)
return result
def hand_rank(hand):
"Return a value indicating the ranking of a hand."
ranks = card_ranks(hand)
if straight(ranks) and flush(hand):
return (8, max(ranks))
elif kind(4, ranks):
return (7, kind(4, ranks), kind(1, ranks))
elif kind(3, ranks) and kind(2, ranks):
return (6, kind(3, ranks), kind(2, ranks))
elif flush(hand):
return (5, ranks)
elif straight(ranks):
return (4, max(ranks))
elif kind(3, ranks):
return (3, kind(3, ranks), ranks)
elif two_pair(ranks):
return (2, two_pair(ranks), ranks)
elif kind(2, ranks):
return (1, kind(2, ranks), ranks)
else:
return (0, ranks)
def card_ranks(hand):
"Return a list of the ranks, sorted with higher first."
ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
ranks.sort(reverse = True)
return [5, 4, 3, 2, 1] if (ranks == [14, 5, 4, 3, 2]) else ranks
def flush(hand):
"Return True if all the cards have the same suit."
suits = [s for r,s in hand]
return len(set(suits)) == 1
def straight(ranks):
"Return True if the ordered ranks form a 5-card straight."
return (max(ranks)-min(ranks) == 4) and len(set(ranks)) == 5
def kind(n, ranks):
"""Return the first rank that this hand has exactly n-of-a-kind of.
Return None if there is no n-of-a-kind in the hand."""
for r in ranks:
if ranks.count(r) == n: return r
return None
def two_pair(ranks):
"If there are two pair here, return the two ranks of the two pairs, else None."
pair = kind(2, ranks)
lowpair = kind(2, list(reversed(ranks)))
if pair and lowpair != pair:
return (pair, lowpair)
else:
return None
def test():
"Test cases for the functions in poker program."
sf1 = "6C 7C 8C 9C TC".split() # Straight Flush
sf2 = "6D 7D 8D 9D TD".split() # Straight Flush
fk = "9D 9H 9S 9C 7D".split() # Four of a Kind
fh = "TD TC TH 7C 7D".split() # Full House
assert poker([sf1, sf2, fk, fh]) == [sf1, sf2]
# print(hand_rank(max([sf1, sf2], key=hand_rank)))
print('tests pass')
mydeck = [r+s for r in '23456789TJQKA' for s in 'SHDC']
def deal(numhands, n=5, deck=mydeck):
"""发牌"""
# hands = []
# for handindex in range(numhands):
# hand = []
# for i in range(n):
# temp = random.choice(deck)
# hand.append(temp)
# deck.remove(temp)
# hands.append(hand)
# return hands
random.shuffle(deck)
return [deck[n*i:n*(i+1)] for i in range(numhands)]
Knuth's Algorithm P.
import random
def shuffle(deck):
"""Knuth's Algorithm P."""
n = len(deck)
for i in range(n-1):
swap(deck, i, random.randrange(i, n))
def swap(deck, i, j):
"""Swap elements i and j of a collection"""
deck[i], deck[j] = deck[j], deck[i]
此部分在最后讲了纯函数的概念,纯函数是做计算(computing)的函数,返回计算结果,便于测试。而另一类函数是Doing类,表示一些过程指令,无返回值,所以难于测试。(是不是类似函数式编程中的纯函数?)