《Design of Computer Programs》学习笔记(1

编程入门 行业动态 更新时间:2024-10-08 13:35:31

《Design of Computer Programs》<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记(1"/>

《Design of Computer Programs》学习笔记(1

Winning Poker Hands

Lesson 1

视频链接:
Lesson 1 - Udacity

1. Welcome

2. About the class

3. Outlining the problem

一个一般设计过程的例子

从一个模糊的理解开始,提炼我们的理解,形成对问题规范的描述,然后变换成可以代码化的东西,最后我们就得到了可运行的代码了。

一句话:
从模糊的理解,到problem,到spec,到code。

扑克牌的游戏规则
一手牌的概念

举例:
一手牌 a hand 【JJ225】
一张牌 a card【红桃J】【黑桃J】
一张牌有大小(rank)和花色(suit,例如红桃、黑桃)
方片五,大小是5,花色是方片。
the 5 of diamonds,the rank is 5 and the suit is diamonds。
待定义的主程序,我们称之为“poker”。输入一系列的手牌,输出最大的手牌。

规则:
【JJ225】有两个对(2 pair),一对J、一对2和一张5。

手牌大小的概念

一样大小(数字)的牌,称为“条”(kind)。
n张一样大小的牌称为两条、三条 或 四条。
n of a kind:2 of a kind、3 of a kind、4 of a kind。n - kind
【JJ225】中,有2个两条
【56789】是顺子(straight)。(5张连续的牌)。
同花(flush):例如【方片2457十】

补充材料:

List of poker hands - 维基百科

4. 练习:Representing Hands

以下哪几项可以合理地表示一手牌:

■ ['JS', 'JD', '2S', '2C', '7H']
■ [(11, 'S'), (11, 'D'), (2, 'S'), (7,'H')]
□ set(['JS', '5D', '2S', '2C', '7H'])
□ "JS JD 2S 2C 7H"

解释:

关于第3个选项:一般的一副牌52张,可以用集合表示。因为一副牌52张中,没有重复的牌。而集合这种数据结构,里面没有重复的元素。但是,如果有2副牌,可能一手牌中,会有重复的元素,所以不能用集合这种数据结构。

关于第4个选项:
字符串包含了所有的元素,但某些情况下,你要把它分拆成5张牌,而一开始时就分开会更好,就不需要多余的操作了。

5. 练习:Poker Function

def poker(hands):"Return the best hand: poker([hand, ...]) => hand"return max"max函数把列表作为输入,返回最大值。"

6. 练习:Understanding Max

def poker(hands):"Return the best hand: poker([hand, ...]) => hand"return maxprint max([3, 4, 5, 0]), max([3, 4, -5, 0], key=abs)

7. 练习:Using Max

def poker(hands):"Return the best hand: poker([hand, ...]) => hand"return max(hands, key=hand_rank)"根据输入的几手牌hands,按照hand_rank函数的排序规则,返回其中的最大值。"def hand_rank():"现在假设我们定义了一个叫hand_rank的函数,把一手牌作为输入,返回某种排名"return None # we will be changing this later.

如果能够清楚正确地给出hand_rank函数,那就八九不离十了。

8. 练习:Testing

但在定义复杂的hand_rank函数之前,我们来考虑下这个函数怎么用,并写一些测试用例。

def poker(hands):"Return the best hand: poker([hand, ...]) => hand"return max(hands, key=hand_rank)def test():"Test cases for the functions in poker program."sf = "6C 7C 8C 9C TC".split()# 这里的T应该是10,6、7、8、9、T是顺子 straight;# 全为C,则花色相同 flush;# 总而言之,是同花顺。# sf 应该是 straight flush (同花顺)的简写。fk = "9D 9H 9S 9C 7D".split()# fk:four of a kind,4张大小一样的牌# 4个9fh = "TD TC TH 7C 7D".split()# fh:full house,3带2# 3个(条,kind)10,2个7。assert poker([sf, fk, fh]) == sf# 上一行必须为真,如果不为真,程序就会停止。assert poker([fk, fh]) == fkassert poker([fh, fh]) == fh# Add 2 new assert statements here. The first # should check that when fk plays fh, fk # is the winner. The second should confirm that# fh playing against fh returns fh.return "tests pass"

补充:
手牌排序类别

详情请查看:
维基百科 - List of poker hands - Hand-ranking categories

9. 练习:Extreme Values

测试的一个重要原则

测试极限值。例如,assert poker([fh, fh]) == fh,是极限值的一种。
考虑传递给poker(hands)中的hands,只有1项、0项或者100项。
poker通常不是单人游戏(solitaire)。所以只有1项,通常不会有太大的意义。但是说明书里面,没有把这个规则定出来。所以增加一个测试,检查当1手牌时,1手牌是胜者。
0手牌时。说明书没有说,但是,poker(hands)函数应该返回1手牌。如果我们传递一个空的列表给poker(hands),就会没有手牌(hand)用于返回。所以最好澄清这个问题,那就是,当我们传递0手牌,这是一个错误(error)。当然,也可以返回None.
100个人同时打牌。如果hands是100种不同的hands的列表。我们想允许那种情况。我们会需要很多卡,500张卡。所以,写测试用例,测试1手牌和100手牌。

# -----------
# User Instructions
# 
# Modify the test() function to include two new test cases:
# 1) A single hand.
# 2) 100 hands.
#
# Since the program is still incomplete, clicking RUN won't do 
# anything, but clicking SUBMIT will let you know if you
# have gotten the problem right. def poker(hands):"Return the best hand: poker([hand,...]) => hand"return max(hands, key=hand_rank)def test():"Test cases for the functions in poker program"sf = "6C 7C 8C 9C TC".split() fk = "9D 9H 9S 9C 7D".split() fh = "TD TC TH 7C 7D".split()assert poker([sf, fk, fh]) == sfassert poker([fk, fh]) == fkassert poker([fh, fh]) == fh# Add 2 new assert statements here. The first # should assert that when poker is called with a# single hand, it returns that hand. The second # should check for the case of 100 hands.assert poker([sf]) == sf# 当玩单人游戏时,它就赢了。assert poker([sf] + [fk] * 99)    return 'tests pass'

以上的内容,离完整的测试用例集合很远。我们真的想要更完整的测试的覆盖。但是也可以开始了。

10. 练习:Hand Rank Attempt

请注意一个前提,ranks是从高到低排列的。
现在是回到hand_rank的好时机了,这是我们将要处理的最复杂的函数。
hand_rank将一手牌(a hand)作为一个输入,但是return什么呢?

# Return a value indicating the ranking of a hand.
# 返回一个值,标明一手牌的顺序(大小)。

但是我们不确定,那个值value,是多少。value必须是可以被max比较大小的某种东西。可以试试数字(数,number)。

参照维基百科 - List of poker hands Hand-ranking categories这张图,和本博文的【手牌排序类别】图。有10种类型的手牌(hands)。(Udacity的视频里面说的是9种,这里我有点疑惑。暂时,我的猜测是,没有讨论5张一样的牌的情况,例如维基百科中的,4个A和1个王组成的5张一样的牌。)

从以上,可知,有9中不同类型的手牌。从顶部最大的同花顺(sf straight flush),到底部最小。我们可以用数字标记,从8到0。8属于同花顺straight flush。然后,我们可以得到解决办法的一个框架:

def hand_rank(hand):"Return a value indicating the ranking of a hand."# 排序大小是最重要的,我们可以先用我们的card_ranks函数,获取排序大小。ranks = card_ranks(hand)# 首先,我们想检查是否有同花顺(straight flush)if straight(ranks) and flush(hand):return 8# 如果有一个4条(Four of a kind)# 在kind()函数里面,我们只需要大小点数rank。elif kind(4, ranks):return 7elif ...

现在有一个问题:

这是否起作用,可以工作?

答案:

部分情况下,可以工作。例如3带一对(full house,对应6)大于顺子(straight,对应4)。
但是,并非所有情况下,都能正常工作。
例如,【1对10+3张其他的牌】【1对9+3张其他的牌】,这两个对应的value,都是1,大小相同。

11. 练习:Representing Rank

请注意一个前提,ranks是从高到低排列的。
表示不同的牌的顺序大小,以下哪几个可以正常工作?哪一个最好?

□ int 70905 70302
□ 小数 7.0905 7.0302
■ 元组 (7, 9, 5) (7, 3, 2)

以上全都可以正常工作,元组最好。因为元组不需要进行复杂的运算,可以直接比较大小。

12. Wild West Poker

用代码表示一手牌(the hand)

同花顺(rank 8,Staight flush)
举例:【同花顺 梅花 7/8/9/10/J】
表示为(8, 11)。解释:同花顺的排序大小最大,为8。上面这手牌中,J最大。(8, 11)完整地描述这手牌(the hand)。

4带1(rank 7,Four of a kind)
举例:【4个A+1个Q】(花色是乱的)
表示为(7, 14, 12)。解释:这手牌中,4个A是主要的rank,为7。A的数大小是14。Q是card rank number 12。

3带1对(rank 6,Full House)
举例:【3个8+1对K】(花色是乱的)
表示为(6, 8, 13)。解释:尽管K比8大,但是8的个数比K多。3个8为full house,value是6。K是13。这个3元素的元组(6, 8, 13)完整地描述了这手牌(hand)。

同花(rank 5,Flush)
举例:【同花(Flush) 方片 10+8+7+5+3】
表示为(5, [10, 8, 7, 5, 3])。解释:同花 Flush 的排序 ranked 大小是5。并且,为了更具体地表示这手牌,我们把所有的牌的数都放进来了。

顺子(rank 4,Straight)
举例:【顺子(Straight) J/10/9/8/7】(花色是乱的)
表示为(4, 11)。解释:4意思是Straight 顺子,11意思是J。

3带2张不一样的(rank 3,Three of a kind)
举例:【3个7+5+2】(花色是乱的)
表示为(3, 7, [7, 7, 7, 5, 2])。解释:通常,只用描述3个7,就可以表示1手牌,但是如果我们真的需要具体地表示(英文为break the ties),我们需要看着下一个最大的牌。

2个对子(rank 2,Two Pair)
举例:【2个J+2个3+K】(花色是乱的)
表示为(2, 11, 3, [13, 11, 11, 3, 3]):。解释:“1对J和1对3”可以描述这手牌的绝大部分,但是我们也需要比较所有的卡牌(cards)。2个对子对应的rank是2,J是11,3是3,最后列出5张card,可以完全地消除这手牌的歧义。

只有1个对子(rank 1,One pair)
举例:【2个2+J+6+3】(花色是乱的)
表示为(1, 2, [11, 6, 3, 2, 2])。解释:“1对2,J最大”,但是,还是有些部分没有描述到。1个对子的ranking是1,2代表2本身的大小,然后把所有的cards写进元组。

啥好牌都没有(rank 0,High Card)
举例:【7/5/4/3/2】(花色是乱的)
表示为(0, 7, 5, 4, 3, 2)。解释:“7/5/4/3/2”这手牌,没有对子、顺子、炸弹,rank是0。

13. Back To Hand Rank

def poker(hands):"Return the best hand: poker([hand,...]) => hand"return max(hands, key=hand_rank)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)) # 2 3 4 5 6 (8, 6) 6 7 8 9 T (8, 10)elif kind(4, ranks):return (7, kind(4, ranks), kind(1, ranks)) # 9 9 9 9 3 (7, 9, 3)elif ...def test

更多推荐

《Design of Computer Programs》学习笔记(1

本文发布于:2024-03-14 05:51:29,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1735775.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   Design   Computer   Programs

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!