提示:本文内容来源于UCB CS61A课程,详情请点击CS 61A: Structure and Interpretation of Computer Programs
前言
本文收录在文章CS61A 课程 Project1 The Game of Hog
提示:以下是本篇文章正文内容,下面代码除课程提供外均为本人自主完成,仅供参考
Phase2 Commentary
本阶段需要完成一个函数,该函数会在每位玩家每轮结束后对其作出注释,如
"22 points! That's the biggest gain yet for Player 1."
一个注释函数需要两个参数,玩家0的当前分数和玩家1的当前分数
其作用是打印分数中的任意一个或者两个,也可以打印其父环境中其他信息
由于分数的不同,每一轮的注释函数会有所差异,所以一个注释函数会返回下一轮将要调用的注释函数(注释函数的唯一副作用为打印信息)
课程提供了一个注释函数的样例say_scores
,此函数单纯打印了两位玩家的分数,同时将自身作为返回值(作为下一轮的注释函数)
def say_scores(score0, score1):
"""A commentary function that announces the score for each player."""
print("Player 0 now has", score0, "and Player 1 now has", score1)
return say_scores
课程还提供了announce_lead_changes
函数,该函数是一个高阶函数,其返回值可以追踪领先玩家,使得每轮游戏都会调用不同的评论性函数
def announce_lead_changes(last_leader=None):
"""Return a commentary function that announces lead changes.
>>> f0 = announce_lead_changes()
>>> f1 = f0(5, 0)
Player 0 takes the lead by 5
>>> f2 = f1(5, 12)
Player 1 takes the lead by 7
>>> f3 = f2(8, 12)
>>> f4 = f3(8, 13)
>>> f5 = f4(15, 13)
Player 0 takes the lead by 2
"""
def say(score0, score1):
if score0 > score1:
leader = 0
elif score1 > score0:
leader = 1
else:
leader = None
if leader != None and leader != last_leader:
print('Player', leader, 'takes the lead by', abs(score0 - score1))
return announce
除上述两个函数之外,还提供了一个函数both
,该函数的两个参数f
,g
均为注释函数,该函数的返回值为一个新的注释函数,被返回的函数又会返回另一个注释函数,该函数按顺序依次调用f
和g
返回的函数
函数如下
def both(f, g):
"""Return a commentary function that says what f says, then what g says.
>>> h0 = both(say_scores, announce_lead_changes())
>>> h1 = h0(10, 0)
Player 0 now has 10 and Player 1 now has 0
Player 0 takes the lead by 10
>>> h2 = h1(10, 6)
Player 0 now has 10 and Player 1 now has 6
>>> h3 = h2(6, 17)
Player 0 now has 6 and Player 1 now has 17
Player 1 takes the lead by 11
NOTE: the following game is not possible under the rules, it's just
an example for the sake of the doctest
"""
def say(score0, score1):
return both(f(score0, score1), g(score0, score1))
return say
关于嵌套含数的调用请参照1.2.5 Evaluating Nested Expressions的内容
Problem 06
本节要求更新play
函数的内容,使得注释函数可以在每轮游戏中被调用,而注释函数得返回值同时是下一轮游戏得注释函数
课程提供了提问脚本用于确保学生完全理解函数的要求
$ python3 ok -q 06 -u --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests
At each "? ", type what you would expect the output to be.
Type exit() to quit
---------------------------------------------------------------------
Question 6 > Suite 1 > Case 1
(cases remaining: 7)
Q: What does a commentary function return?
Choose the number of the correct choice:
0) An integer representing the score.
1) None.
2) Another commentary function.
? 2
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 2 > Case 1
(cases remaining: 6)
>>> from hog import play, always_roll
>>> from dice import make_test_dice
>>> #
>>> def echo(s0, s1):
... print(s0, s1)
... return echo
>>> s0, s1 = play(always_roll(1), always_roll(1), dice=make_test_dice(3), goal=5, say=echo)
(line 1)? 3 0
(line 2)? 3 3
(line 3)? 9 3
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 2 > Case 2
(cases remaining: 5)
>>> from hog import play, always_roll
>>> from dice import make_test_dice
>>> #
>>> def count(n):
... def say(s0, s1):
... print(n, s0)
... return count(n + 1)
... return say
>>> s0, s1 = play(always_roll(1), always_roll(1), dice=make_test_dice(3), goal=10, say=count(1))
(line 1)? 1 3
(line 2)? 2 3
(line 3)? 3 9
(line 4)? 4 9
(line 5)? 5 15
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 2 > Case 3
(cases remaining: 4)
>>> from hog import play, always_roll
>>> from dice import make_test_dice
>>> #
>>> def echo(s0, s1):
... print(s0, s1)
... return echo
>>> strat0 = lambda score, opponent: 1 - opponent // 10
>>> strat1 = always_roll(3)
>>> s0, s1 = play(strat0, strat1, dice=make_test_dice(4, 2, 6), goal=15, say=echo)
(line 1)? 4 0
(line 2)? 4 12
(line 3)? 12 13
(line 4)? 12 25
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 2 > Case 4
(cases remaining: 3)
>>> from hog import play, always_roll
>>> from dice import make_test_dice
>>> #
>>> # Ensure that say is properly updated within the body of play.
>>> def total(s0, s1):
... print(s0 + s1)
... return echo
>>> def echo(s0, s1):
... print(s0, s1)
... return total
>>> s0, s1 = play(always_roll(1), always_roll(1), dice=make_test_dice(2, 3), goal=15, say=echo)
(line 1)? 2 0
(line 2)? 5
(line 3)? 4 3
(line 4)? 13
(line 5)? 6 9
(line 6)? 21
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 3 > Case 1
(cases remaining: 2)
>>> from hog import play, always_roll, both, announce_lead_changes, say_scores
>>> from dice import make_test_dice
>>> #
>>> def echo_0(s0, s1):
... print('*', s0)
... return echo_0
>>> def echo_1(s0, s1):
... print('**', s1)
... return echo_1
>>> s0, s1 = play(always_roll(1), always_roll(1), dice=make_test_dice(2), goal=3, say=both(echo_0, echo_1))
(line 1)? * 2
(line 2)? ** 0
(line 3)? * 2
(line 4)? ** 2
(line 5)? * 4
(line 6)? ** 2
-- OK! --
---------------------------------------------------------------------
Question 6 > Suite 3 > Case 2
(cases remaining: 1)
-- Already unlocked --
---------------------------------------------------------------------
OK! All cases for Question 6 unlocked.
函数得实现只需要在if和else得语句块末尾分别添加以下表达式即可
say = say(score0, score1)
可以通过脚本得检测
$ python3 ok -q 06 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests
---------------------------------------------------------------------
Test summary
7 test cases passed! No cases failed.
Problem 07
该部分要求实现announce_highest
函数,该函数为一个返回值为注释函数得高阶函数
该注释函数只有在某个特定玩家在某一轮游戏中获得比以往更多的分数时才会打印信息
例如,announce_highest(1) 及其返回值完全忽略玩家0,只打印有关玩家1的信息。
要计算得分,必须目标玩家将上一回合的得分与本回合的得分进行比较(目标玩家由参数who
指定)
除此之外,该函数须跟踪玩家到目前为止的最高得分
课程提供提问脚本以确保学生完全理解函数的需求
$ python3 ok -q 07 -u
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlocking tests
At each "? ", type what you would expect the output to be.
Type exit() to quit
---------------------------------------------------------------------
Question 7 > Suite 1 > Case 1
(cases remaining: 5)
Q: What does announce_highest return?
Choose the number of the correct choice:
0) A string containing the largest point increase for the
current player.
1) The current largest point increase between both
players.
2) A commentary function that prints information about the
biggest point increase for the current player.
? 2
-- OK! --
---------------------------------------------------------------------
Question 7 > Suite 1 > Case 2
(cases remaining: 4)
Q: When does the commentary function returned by announce_highest
print something out?
Choose the number of the correct choice:
0) After each turn.
1) When the current player, given by the parameter `who`,
earns the biggest point increase yet between both
players in the game.
2) When the current player, given by the parameter `who`,
earns their biggest point increase yet in the game.
? 2
-- OK! --
---------------------------------------------------------------------
Question 7 > Suite 1 > Case 3
(cases remaining: 3)
Q: What does the parameter last_score represent?
Choose the number of the correct choice:
0) The current player's score before this turn.
1) The opponent's score before this turn.
2) The last highest gain for the current player.
? 0
-- OK! --
---------------------------------------------------------------------
OK! All cases for Question 7 unlocked.
函数的实现如下:
def announce_highest(who, last_score=0, running_high=0):
"""Return a commentary function that announces when WHO's score
increases by more than ever before in the game.
NOTE: the following game is not possible under the rules, it's just
an example for the sake of the doctest
>>> f0 = announce_highest(1) # Only announce Player 1 score gains
>>> f1 = f0(12, 0)
>>> f2 = f1(12, 11)
11 point(s)! That's the biggest gain yet for Player 1
>>> f3 = f2(20, 11)
>>> f4 = f3(13, 20)
>>> f5 = f4(20, 35)
15 point(s)! That's the biggest gain yet for Player 1
>>> f6 = f5(20, 47) # Player 1 gets 12 points; not enough for a new high
>>> f7 = f6(21, 47)
>>> f8 = f7(21, 77)
30 point(s)! That's the biggest gain yet for Player 1
>>> f9 = f8(77, 22) # Swap!
>>> f10 = f9(33, 77) # Swap!
55 point(s)! That's the biggest gain yet for Player 1
"""
assert who == 0 or who == 1, 'The who argument should indicate a player.'
# BEGIN PROBLEM 7
"*** YOUR CODE HERE ***"
def track_highest(score0, score1, highest=running_high):
if who == 0:
this_score = score0
else:
this_score = score1
gain = this_score - last_score
if gain > highest:
print(gain, "point(s)! That's the biggest gain yet for Player", who)
highest = gain
return announce_highest(who, this_score, highest)
return track_highest
# END PROBLEM 7
该函数的实现满足评分脚本要求
$ python3 ok -q 07 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests
---------------------------------------------------------------------
Test summary
5 test cases passed! No cases failed.