CS61A 课程项目 Hog, Phase1: Simulator

提示:本文内容来源于UCB CS61A课程,详情请点击CS 61A: Structure and Interpretation of Computer Programs


前言

本文收录在文章CS61A 课程 Project1 The Game of Hog


提示:以下是本篇文章正文内容,下面代码除课程提供外均为本人自主完成,仅供参考

阶段1:模拟器

Problem 0

完成这一部分需要阅读说明和dice.py中的代码

from random import randint

def make_fair_dice(sides):
    """Return a die that returns 1 to SIDES with equal chance."""
    assert type(sides) == int and sides >= 1, 'Illegal value for sides'
    def dice():
        return randint(1,sides)
    return dice

four_sided = make_fair_dice(4)
six_sided = make_fair_dice(6)

def make_test_dice(*outcomes):
    """
    Return a die that cycles deterministically through OUTCOMES.
    This function uses Python syntax/techniques not yet covered in this course.
    The best way to understand it is by reading the documentation and examples.
    """
    assert len(outcomes) > 0, 'You must supply outcomes to make_test_dice'
    for o in outcomes:
        assert type(o) == int and o >= 1, 'Outcome is not a positive integer'
    index = len(outcomes) - 1
    def dice():
        nonlocal index
        index = (index + 1) % len(outcomes)
        return outcomes[index]
    return dice

函数make_fair_dice在传入一个参数sides(骰子的面数)后返回一个sides面骰子,每次投掷等可能生成1-sides之间任意一个数字

函数make_test_dice传入一个整数序列,按顺序循环输出序列中的数字(大致功能为此,依据后续内容,发现该函数用来避免随机性以对其他函数的实现进行测试)

>>> dice = make_test_dice(1, 2, 3)
>>> dice()
1
>>> dice()
2
>>> dice()
3
>>> dice()
1
>>> dice()
2

课程组提供了一个脚本,用于检测学生是否理解了dice.py内函数的作用

$ python3 ok -q 00 -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 0 > Suite 1 > Case 1
(cases remaining: 2)

>>> from hog import *
>>> test_dice = make_test_dice(4, 1, 2)
>>> test_dice()
? 4
-- OK! --

>>> test_dice() # Second call
? 1
-- OK! --

>>> test_dice() # Third call
? 2
-- OK! --

>>> test_dice() # Fourth call
? 4
-- OK! --

---------------------------------------------------------------------
Question 0 > Suite 2 > Case 1
(cases remaining: 1)

Q: Which of the following is the correct way to "roll" a fair, six-sided die?
Choose the number of the correct choice:
0) six_sided()
1) make_fair_dice(6)
2) make_test_dice(6)
3) six_sided
? 0
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 0 unlocked.
关于nonlocal关键字

因为变量index是在函数dice之外make_test_dice之内定义的,因此要修改index的值,需要nonlocal关键字,需要注意的是,make_test_dice返回的函数dice一直持有其父环境(即定义dice函数的环境),因此会记录每一次修改后index的值,从而保证循环依次输出元组*outcomes的中的整数

Problem 01

该环节需要实现hog.py文件中的roll_dice函数

该函数需要两个参数:

  • 一个正数num_rolls,表示该玩家本轮要投掷多少个骰子
  • 一个函数dice,表示投掷何种骰子

该函数的返回值该轮中获得的分数,分数只能是1或者每次投掷结果的和(根据Pig Out规则)

该课程还对函数的实现作出以下要求:

  • 调用dice()可以获得一次投掷的结果,你需要在roll_dice的函数体中确切调用dice()函数num_rolls次

即是投掷结果是1可能会触发Pig Out规则,但仍然需要将所有num_rolls次数投掷完,因为在现实中投掷骰子是一次行将num_rolls全部掷出的,在函数实现中需要正确地模拟这种情况

  • 在函数中不能尝试实现Feral Hogs规则,因为本函数无法知晓前一次投掷结果(该参数没有传入),该功能会在别处实现

课程为确保学生完全理解函数需求,提供了一个检测脚本用于学生自查(只有通过这类检测,脚本的代码检测功能才能正常使用)(挺贴心的)

$ python3 ok -q 01 -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 1 > Suite 1 > Case 1
(cases remaining: 59)

>>> from hog import *
>>> roll_dice(2, make_test_dice(4, 6, 1))
? 10
-- OK! --

---------------------------------------------------------------------
Question 1 > Suite 1 > Case 2
(cases remaining: 58)

>>> from hog import *
>>> roll_dice(3, make_test_dice(4, 6, 1))
? 1
-- OK! --

---------------------------------------------------------------------
Question 1 > Suite 1 > Case 3
(cases remaining: 57)

>>> from hog import *
>>> roll_dice(4, make_test_dice(2, 2, 3))
? 9
-- OK! --

---------------------------------------------------------------------
Question 1 > Suite 1 > Case 4
(cases remaining: 56)

>>> from hog import *
>>> roll_dice(4, make_test_dice(1, 2, 3))
? 1
-- OK! --

---------------------------------------------------------------------
Question 1 > Suite 1 > Case 5
(cases remaining: 55)

>>> from hog import *
>>> counted_dice = make_test_dice(4, 1, 2, 6)
>>> roll_dice(3, counted_dice)
? 1
-- OK! --

>>> # Make sure you call dice exactly num_rolls times!
>>> # If you call it fewer or more than that, it won't be at the right spot in the cycle for the next roll
>>> # Note that a return statement in a for loop ends the loop
>>> roll_dice(1, counted_dice)
? 6
-- OK! --

---------------------------------------------------------------------
Question 1 > Suite 1 > Case 6
(cases remaining: 54)

>>> from hog import *
>>> roll_dice(9, make_test_dice(6))
? 54
-- OK! --

>>> roll_dice(7, make_test_dice(2, 2, 2, 2, 2, 2, 1))
? 1
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 1 unlocked.

下面就可以开始实现掷骰子函数了

def roll_dice(num_rolls, dice=six_sided):
    """Simulate rolling the DICE exactly NUM_ROLLS > 0 times. Return the sum of
    the outcomes unless any of the outcomes is 1. In that case, return 1.

    num_rolls:  The number of dice rolls that will be made.
    dice:       A function that simulates a single dice roll outcome.
    """
    # These assert statements ensure that num_rolls is a positive integer.
    assert type(num_rolls) == int, 'num_rolls must be an integer.'
    assert num_rolls > 0, 'Must roll at least once.'
    # BEGIN PROBLEM 1
    "*** YOUR CODE HERE ***"
    score, i = 0, 1
    pig_out = False
    while i <= num_rolls:
        this_roll = dice()
        score += this_roll
        if this_roll == 1:
            pig_out = True
        i += 1
    return 1 if pig_out else score
    # END PROBLEM 1

由于要将投掷过程模拟出来,所以没有在投掷骰子的循环过程中将得分更改为1,而是选择了设立一个pig_out的flag,当某个骰子(某一侧投掷)的结果为1时,将该flag设为True,然后用这个flag的真值来确定要返回的是1还是score

上述实现的最后一行与以下等效

if pig_out == True:
    return 1
else:
    return score

能通过自动打分脚本的测评

$ python3 ok -q 01
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    59 test cases passed! No cases failed.

Problem 02

该部分要求实现函数free_bacon,即Free Bacon规则

首先脚本检测学生是否完全理解该规则

$ python3 ok -q 02 -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 2 > Suite 1 > Case 1
(cases remaining: 36)

>>> from hog import *
>>> free_bacon(4)
? 6
-- OK! --

---------------------------------------------------------------------
Question 2 > Suite 1 > Case 2
(cases remaining: 35)

>>> from hog import *
>>> free_bacon(1)
? 9
-- OK! --

---------------------------------------------------------------------
Question 2 > Suite 1 > Case 3
(cases remaining: 34)

>>> from hog import *
>>> free_bacon(20)
? 12
-- OK! --

---------------------------------------------------------------------
Question 2 > Suite 1 > Case 4
(cases remaining: 33)

>>> from hog import *
>>> free_bacon(45)
? 9
-- OK! --

---------------------------------------------------------------------
Question 2 > Suite 1 > Case 5
(cases remaining: 32)

>>> from hog import *
>>> free_bacon(15)
? 6
-- OK! --

---------------------------------------------------------------------
Question 2 > Suite 1 > Case 6
(cases remaining: 31)

>>> from hog import *
>>> free_bacon(13)
? 8
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 2 unlocked.

free_bacon函数的实现如下:

def free_bacon(score):
    """Return the points scored from rolling 0 dice (Free Bacon).

    score:  The opponent's current score.
    """
    assert score < 100, 'The game should be over.'
    # BEGIN PROBLEM 2
    "*** YOUR CODE HERE ***"
    tens, ones = score // 10, score % 10
    return 10 - ones + tens
    # END PROBLEM 2

该函数已经由assert检验score为非法值的情况,可以认为score值合法

以上实现满足评分脚本要求

g$ python3 ok -q 02 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    36 test cases passed! No cases failed.

Problem 03

take_turn函数,给定骰子dice与骰子个数num_dice,要求返回得分

实现时尽可能同时调用roll_dice函数和free_bacon函数

课程为确保学生完全理解函数需求,提供了一个检测脚本用于学生自查

$ python3 ok -q 02 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    36 test cases passed! No cases failed.

Cannot backup when running ok with --local.
lyx@Hetu:hog$ python3 ok -q 03 -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 3 > Suite 1 > Case 1
(cases remaining: 10)

>>> from hog import *
>>> take_turn(2, 0, make_test_dice(4, 5, 1))
? 9
-- OK! --

---------------------------------------------------------------------
Question 3 > Suite 1 > Case 2
(cases remaining: 9)

>>> from hog import *
>>> take_turn(3, 0, make_test_dice(4, 6, 1))
? 1
-- OK! --

---------------------------------------------------------------------
Question 3 > Suite 1 > Case 3
(cases remaining: 8)

>>> from hog import *
>>> take_turn(0, 56)
? 9
-- OK! --

---------------------------------------------------------------------
Question 3 > Suite 1 > Case 4
(cases remaining: 7)

>>> from hog import *
>>> take_turn(0, 47)
? 7
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 3 unlocked.

函数实现如下,四个assert语句保证了参数合法,然后根据投掷骰子的个数决定得分

def take_turn(num_rolls, opponent_score, dice=six_sided):
    """Simulate a turn rolling NUM_ROLLS dice, which may be 0 (Free Bacon).
    Return the points scored for the turn by the current player.

    num_rolls:       The number of dice rolls that will be made.
    opponent_score:  The total score of the opponent.
    dice:            A function that simulates a single dice roll outcome.
    """
    # Leave these assert statements here; they help check for errors.
    assert type(num_rolls) == int, 'num_rolls must be an integer.'
    assert num_rolls >= 0, 'Cannot roll a negative number of dice in take_turn.'
    assert num_rolls <= 10, 'Cannot roll more than 10 dice.'
    assert opponent_score < 100, 'The game should be over.'
    # BEGIN PROBLEM 3
    "*** YOUR CODE HERE ***"
    if num_rolls == 0:
        return free_bacon(opponent_score)
    else:
        return roll_dice(num_rolls, dice)
    # END PROBLEM 3

函数的实现满足评分脚本要求

$ python3 ok -q 03 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    10 test cases passed! No cases failed.

Problem 04

实现函数is_swap,对应Swine Swap规则

该函数需要两个参数,当前玩家的得分和对手的得分,返回一个布尔值来表明规则Swine Swap的条件是否被满足

课程为确保学生完全理解函数需求,提供了一个检测脚本用于学生自查

$ python3 ok -q 04 -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 4 > Suite 1 > Case 1
(cases remaining: 107)

>>> from hog import *
>>> is_swap(2, 4)
? False
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 2
(cases remaining: 106)

>>> from hog import *
>>> is_swap(11, 1)
? True
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 3
(cases remaining: 105)

>>> from hog import *
>>> is_swap(1, 0)
? False
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 4
(cases remaining: 104)

>>> from hog import *
>>> is_swap(15, 46)
? False
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 5
(cases remaining: 103)

>>> from hog import *
>>> is_swap(23, 4)
? False
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 6
(cases remaining: 102)

>>> from hog import *
>>> is_swap(15, 23)
? True
-- OK! --

---------------------------------------------------------------------
Question 4 > Suite 1 > Case 7
(cases remaining: 101)

>>> from hog import *
>>> is_swap(92, 3)
? False
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 4 unlocked.
def is_swap(player_score, opponent_score):
    """
    Return whether the two scores should be swapped
    """
    # BEGIN PROBLEM 4
    "*** YOUR CODE HERE ***"
    player_ones, opponent_ones, opponent_tens = player_score % 10, opponent_score % 10, opponent_score // 10
    return abs(player_ones - opponent_ones) == opponent_tens
    # END PROBLEM 4

上述函数实现在使用脚本打分时出现了问题,错误样例如下:

Question 4 > Suite 1 > Case 9

>>> from hog import *
>>> is_swap(960, 144)
False

# Error: expected
#     True
# but got
#     False

Run only this test case with "python3 ok -q 04 --suite 1 --case 9"
---------------------------------------------------------------------
Test summary
    8 test cases passed before encountering first failed test case

当前玩家分数为960,对手分数为144,按照项目要求这两个参数是非法数据,但给出expected True的提示,考虑到在某一方获胜时可能取得大于100分的分数,因此将其视作合法数据(不能用assert隔绝,因为要得到True的结果),只需要修改opponent_tens的计算公式即可,修改如下:

opponent_tens = opponent_score // 10 % 10
# 修改过后满足了评分脚本要求
$ python3 ok -q 04 --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    107 test cases passed! No cases failed.

Problem 05a

该部分要求实现play函数,该函数完整地模拟了Hog游戏

玩家轮流掷骰子,直到其中一名玩家达到目标分数。

要求暂时忽视Feral Hogs规则和feral_hogs参数,这一部分将在05b实现

为决定每轮投掷多少个骰子,每个玩家采取各自的策略(玩家0使用策略0,玩家1使用策略1)

strategy是一个函数,该函数:

  • 以当前玩家分数和对手分数
  • 返回当前玩家在本轮中想要投掷骰子的数量
  • 每个策略函数每轮只被调用一次
  • 策略函数的实现将会在第三阶段进行

游戏结束后,play函数返回两个玩家的最后总分(第一个为玩家0,第二个为玩家1)

提示如下:

  • 要求使用之前已实现的函数,调用函数take_turn时要使用三个参数
  • 每一轮只调用函数take_turn一次
  • 执行除了Feral Hogs之外的所有特殊规则
  • 通过调用提供的函数 other 来获取其他玩家的号码(0 或 1)
  • 忽略参数say,该参数将在第二阶段使用

课程为确保学生完全理解函数需求,提供了一个检测脚本用于学生自查

$ python3 ok -q 05a -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 5a > Suite 1 > Case 1
(cases remaining: 11)

Q: The variables score0 and score1 are the scores for Player 0
and Player 1, respectively. Under what conditions should the
game continue?
Choose the number of the correct choice:
0) While score1 is less than goal
1) While at least one of score0 or score1 is less than goal
2) While score0 and score1 are both less than goal
3) While score0 is less than goal
? 2
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 1 > Case 2
(cases remaining: 10)

Q: What is a strategy in the context of this game?
Choose the number of the correct choice:
0) A player's desired turn outcome
1) A function that returns the number of dice a player will roll
2) The number of dice a player will roll
? 1
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 1 > Case 3
(cases remaining: 9)

Q: If strategy1 is Player 1's strategy function, score0 is
Player 0's current score, and score1 is Player 1's current
score, then which of the following demonstrates correct
usage of strategy1?
Choose the number of the correct choice:
0) strategy1(score1)
1) strategy1(score0, score1)
2) strategy1(score0)
3) strategy1(score1, score0)
? 3
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 2 > Case 1
(cases remaining: 8)

>>> import hog
>>> always_three = hog.make_test_dice(3)
>>> always = hog.always_roll
>>> #
>>> # Play function stops at goal
>>> s0, s1 = hog.play(always(5), always(3), score0=91, score1=10, dice=always_three, feral_hogs=False)
>>> s0
? 106
-- OK! --

>>> s1
? 10
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 2 > Case 2
(cases remaining: 7)

>>> import hog
>>> always_three = hog.make_test_dice(3)
>>> always = hog.always_roll
>>> #
>>> # Goal score is not hardwired
>>> s0, s1 = hog.play(always(5), always(5), goal=10, dice=always_three, feral_hogs=False)
>>> s0
? 15
-- OK! --

>>> s1
? 0
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 2 > Case 3
(cases remaining: 6)

-- Already unlocked --

---------------------------------------------------------------------
Question 5a > Suite 2 > Case 4
(cases remaining: 5)

-- Already unlocked --

---------------------------------------------------------------------
Question 5a > Suite 3 > Case 1
(cases remaining: 4)

>>> import hog
>>> always_three = hog.make_test_dice(3)
>>> always_seven = hog.make_test_dice(7)
>>> #
>>> # Use strategies
>>> # We recommend working this out turn-by-turn on a piece of paper (use Python for difficult calculations).
>>> strat0 = lambda score, opponent: opponent % 10
>>> strat1 = lambda score, opponent: max((score // 10) - 4, 0)
>>> s0, s1 = hog.play(strat0, strat1, score0=71, score1=80, dice=always_seven, feral_hogs=False)
>>> s0
? 89
-- OK! --

>>> s1
? 108
-- OK! --

---------------------------------------------------------------------
Question 5a > Suite 4 > Case 1
(cases remaining: 3)

-- Already unlocked --

---------------------------------------------------------------------
Question 5a > Suite 4 > Case 2
(cases remaining: 2)

-- Already unlocked --

---------------------------------------------------------------------
Question 5a > Suite 4 > Case 3
(cases remaining: 1)

-- Already unlocked --

---------------------------------------------------------------------
OK! All cases for Question 5a unlocked.

函数的实现如下:

def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
         goal=GOAL_SCORE, say=silence, feral_hogs=True):
    """Simulate a game and return the final scores of both players, with Player
    0's score first, and Player 1's score second.

    A strategy is a function that takes two total scores as arguments (the
    current player's score, and the opponent's score), and returns a number of
    dice that the current player will roll this turn.

    strategy0:  The strategy function for Player 0, who plays first.
    strategy1:  The strategy function for Player 1, who plays second.
    score0:     Starting score for Player 0
    score1:     Starting score for Player 1
    dice:       A function of zero arguments that simulates a dice roll.
    goal:       The game ends and someone wins when this score is reached.
    say:        The commentary function to call at the end of the first turn.
    feral_hogs: A boolean indicating whether the feral hogs rule should be active.
    """
    who = 0  # Who is about to take a turn, 0 (first) or 1 (second)
    # BEGIN PROBLEM 5
    "*** YOUR CODE HERE ***"
    while score0 < goal and score1 < goal:
        if who == 0:
            num_rolls = strategy0(score0, score1)
            points = take_turn(num_rolls, score1, dice)
            score0 += points
            if is_swap(score0, score1):
                score0, score1 = score1, score0
        else:
            num_rolls = strategy1(score1, score0)
            points = take_turn(num_rolls, score0, dice)
            score1 += points
            if is_swap(score1, score0):
                score1, score0 = score0, score1
        who = other(who)
    # END PROBLEM 5
    # (note that the indentation for the problem 6 prompt (***YOUR CODE HERE***) might be misleading)
    # BEGIN PROBLEM 6
    "*** YOUR CODE HERE ***"
    # END PROBLEM 6
    return score0, score1

以上函数实现符合评分脚本要求

$ python3 ok -q 05a
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    11 test cases passed! No cases failed.

Problem 05b

本节要求实现Feral Hog规则

play函数被调用时,且其参数feral_hogs被设置为True,则该规则生效。否则忽视该规则

提问脚本如下:

$ python3 ok -q 05b -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 5b > Suite 1 > Case 1
(cases remaining: 103)

>>> import hog
>>> always_one = hog.make_test_dice(1)
>>> always_two = hog.make_test_dice(2)
>>> always_three = hog.make_test_dice(3)
>>> always = hog.always_roll
>>> # example 1
>>> def strat0(s0, s1):
...     if s0 == 0: return 3
...     if s0 == 7: return 5
...     return 8
>>> def strat1(s0, s1):
...     if s0 == 0: return 1
...     if s0 == 4: return 2
...     return 6
>>> s0, s1 = hog.play(
...   strat0, strat1, score0=0, score1=0, goal=21,
...   dice=hog.make_test_dice(2, 2, 3, 4, 2, 2, 2, 2, 2, 3, 5, 2, 2, 2, 2, 2, 2, 2, 6, 1))
>>> s0
? 43
-- OK! --

>>> s1
? 15
-- OK! --

---------------------------------------------------------------------
Question 5b > Suite 1 > Case 2
(cases remaining: 102)

>>> import hog
>>> always_one = hog.make_test_dice(1)
>>> always_two = hog.make_test_dice(2)
>>> always_three = hog.make_test_dice(3)
>>> always = hog.always_roll
>>> # example 2
>>> s0, s1 = hog.play(always(2), always(1), score0=0, score1=0, goal=5, dice=hog.make_test_dice(2, 2))
>>> s0
? 7
-- OK! --

>>> s1
? 0
-- OK! --

---------------------------------------------------------------------
Question 5b > Suite 1 > Case 3
(cases remaining: 101)

>>> import hog
>>> always_one = hog.make_test_dice(1)
>>> always_two = hog.make_test_dice(2)
>>> always_three = hog.make_test_dice(3)
>>> always = hog.always_roll
>>> # swap after feral hogs
>>> s0, s1 = hog.play(always(2), always(1), score0=17, score1=6, goal=21, dice=hog.make_test_dice(1, 2))
>>> s0
? 23
-- Not quite. Try again! --

? 6
-- Not quite. Try again! --

? 18
-- Not quite. Try again! --

? 21
-- OK! --

>>> s1
? 18
-- Not quite. Try again! --

? 104
-- Not quite. Try again! --

? 6
-- OK! --

---------------------------------------------------------------------
OK! All cases for Question 5b unlocked.

最后一种情况是瞎碰的,用自己写的代码跑了一下发现和答案一样,分析之后发现是忘了应用Pig out规则

import hog
always_one = hog.make_test_dice(1)
always_two = hog.make_test_dice(2)
always_three = hog.make_test_dice(3)
always = hog.always_roll
# swap after feral hogs,这一句的意思是交换规则是发生在激励规则之后的
s0, s1 = hog.play(always(2), always(1), score0=17, score1=6, goal=21, dice=hog.make_test_dice(1, 2))
goal=21feral_hogs=Truescore0score1
whonum_rollspointsferal_hog176is_swap
玩家02投掷结果(1, 2),的分为12-0=217+1+3=2166-1!=0,False

函数实现如下,分别在if和else负责的代码块中添加了一部分内容:

def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided,
         goal=GOAL_SCORE, say=silence, feral_hogs=True):
    """Simulate a game and return the final scores of both players, with Player
    0's score first, and Player 1's score second.

    A strategy is a function that takes two total scores as arguments (the
    current player's score, and the opponent's score), and returns a number of
    dice that the current player will roll this turn.

    strategy0:  The strategy function for Player 0, who plays first.
    strategy1:  The strategy function for Player 1, who plays second.
    score0:     Starting score for Player 0
    score1:     Starting score for Player 1
    dice:       A function of zero arguments that simulates a dice roll.
    goal:       The game ends and someone wins when this score is reached.
    say:        The commentary function to call at the end of the first turn.
    feral_hogs: A boolean indicating whether the feral hogs rule should be active.
    """
    who = 0  # Who is about to take a turn, 0 (first) or 1 (second)
    # BEGIN PROBLEM 5
    "*** YOUR CODE HERE ***"
    last_turn_points0, last_turn_points1 = 0, 0 # 初始化上一轮投掷得分为0
    while score0 < goal and score1 < goal:
        if who == 0:
            num_rolls0 = strategy0(score0, score1)
            points0 = take_turn(num_rolls0, score1, dice)
            score0 += points0
            if feral_hogs and abs(num_rolls0 - last_turn_points0) == 2: # 注意只有形参为True是规则才会生效
                score0 += 3
            if is_swap(score0, score1):
                score0, score1 = score1, score0
            last_turn_points0 = points0 # 更新上一轮投掷得分
        else:
            num_rolls1 = strategy1(score1, score0)
            points1 = take_turn(num_rolls1, score0, dice)
            score1 += points1
            if feral_hogs and abs(num_rolls1 - last_turn_points1) == 2: # 注意只有形参为True是规则才会生效
                score1 += 3
            if is_swap(score1, score0):
                score1, score0 = score0, score1
            last_turn_points1 = points1 # 更新上一轮投掷得分
        who = other(who)
    # END PROBLEM 5
    # (note that the indentation for the problem 6 prompt (***YOUR CODE HERE***) might be misleading)
    # BEGIN PROBLEM 6
    "*** YOUR CODE HERE ***"
    # END PROBLEM 6
    return score0, score1

符合自动评分脚本的要求

$ python3 ok -q 05a --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    11 test cases passed! No cases failed.

Cannot backup when running ok with --local.
lyx@Hetu:hog$ python3 ok -q 05b --local
=====================================================================
Assignment: Project 1: Hog
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    103 test cases passed! No cases failed.

以上即为该课设模拟器部分的所有实现

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值