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

-
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值