当前位置:首页|资讯

自学CS61A Project1 Hog(策略篇)(第一期)

作者:翻车水王汪轓发布时间:2024-10-17

前言

我是愚谷ノ園みら,简称愚園みら,本账号的使用者之一的负责分享学习笔记的oc。啊,我不会干涉各位号主们的其他事物,只会默默在专栏文件夹里发CS/AI相关的学习笔记。


总之,みら最近开始学习CS61A。打算记一点笔记激励自己学下去!


这才第一个项目,已经有点想放弃了……


啊,忘了说的CS61A是一门CS相关的课?总之是UC Berkeley的CS入门课。嘛反正点开这篇文章的人应该不需要我来介绍CS61A是什么了(大概……)


以下部分都是基于已经装完环境,下载了相关课件,并且会使用ok进行评分的假设。

其实我也没怎么认真看课和课件,英语让人头大。


我也是初学者,请多包涵~如有错误,敬请斧正!


总之是正文

因为很懒,我将会把这一段东西再重新,呃,再复制粘贴第二遍。

CS61A的第一个project是要制作一个叫hog的小游戏。以下是一些关于这个project的一些碎碎念,希望能帮到有需要的同学们。

详情请参考:https://cs61a.org/proj/hog/

这是Hog项目的主要网站(作业要求),本文之后的内容将会围绕这里的题目。

以及课程课本的翻译件:https://composingprograms.netlify.app/

非常好课本,使我的理解加深十倍甚至九倍。


如果把Hog的规则和追加规则也写进来的话,太长了,恕我贴一下第一篇的链接,请诸君自己看一看~

第一期

本篇内容是在理解规则,并且写完了游戏模拟器(核心?)部分的基础上!

第三期

如果还记得在这里“策略”是什么意思就更好了!虽说接下来马上就会又提到的。


回顾:策略是什么?

策略(strategy)是一个函数。

在自己的回合中,策略函数需要输入自己和对手的分数。

而策略函数的返回值,是这回合自己打算投的骰子数量。

理解这点之后,就可以解决之后的问题了。


本篇基本上都是和固定投掷几个骰子的策略相关。


第六题:`always_roll(n)`

`always_roll(n)`策略,顾名思义,就是无论什么情况,都只投n个骰子。


但是!`always_roll()`这个函数,它的返回值是一个策略。也就是说它是个高阶函数。


或许可以复习一下这个:

https://composingprograms.netlify.app/1/6


在本系列的第一篇中也出现过高阶函数。


于是我们需要在`always_roll`里定义一个叫做strategy的函数然后返回它。

strategy的输出一直是n就可以了。


这次的代码如下。


第七题:`is_always_roll`函数

我们需要在这里测试:一个策略是否是`always_roll`。

我想到的做法只有一个:用for循环把所有可能性全列一遍。


我们对0~goal的所有己方分数循环,每个循环中,再对0~goal的所有对手分数循环。

两层循环中,用if判定strategy(i,j)是否等于strategy(0,0)。只要有一种不相等,就return False

所有循环都走完,还没有不相等,那就return True。


是举反例证伪的思路呢。


还是附一下代码吧。


第八题:`make_averaged`函数

这个高阶函数的作用是:重复调用times_called遍original_function(两者皆为此函数的输入参数),后取均值。


在这里我们来回答一些OK评分器的问题:


Q:为什么这个函数是个高阶函数?(原因之一)

A:它以函数作为输入参数!(至少我是这么回答的,它算我对)


Q:传入make_averaged这个函数的函数,有多少参数?

A:任意数量皆可。因此我们需要用*args来调用它。


为了理解这个问题(意思:我看的时候没懂),现在容我把OK里的题目贴出来:

最后的输出应该是多少呢?


首先dice是一个骰子函数,每次执行都会输出数字。这里是固定为3 1 6 5循环的顺序。


roll_dice是什么呢?是第一题(请见第二篇文章)要求写的函数,是包含了Sow Sad规则的记分函数。


也就是说,我们这次要make_average的对象,是算分。

averaged_roll_dice是一个函数,它的作用是,执行1000次计算roll_dice(...),并计均分。


最后,到执行averaged_roll_dice(2, dice)的时候,就很明确了:这里的两个参数是给roll_dice(...)的。


所以,这段代码的含义是:每次roll两下dice,计算均分。


第一回投出3分和1分,计为1分(触发Sow Sad),第二回投出5分和6分,计为11分。


因此,均分是:6.0分!(因为要求写成float)


上面的例子里也提到了:make_averaged(...)的输出结果是个函数,因此我们在这个函数里要做的事情是,定义一个新的函数,然后输出它。


在这个函数内部,我们需要计算执行多次某函数之后的均值。


代码如下:


补充说明:如果用lambda+list/tuple,似乎可以一行写完,但是没必要吧!


第九题:`max_scoring_num_rolls`函数


我们要通过暴力测试模拟出一直投几个骰子的收益最大。


这个函数的输入是固定的:骰子函数(默认六面)与测试次数(默认1000)。


输出则是对于这款骰子的最佳投掷个数。


作业要求我们从1开始试到10。(为什么不试0?因为0本来就不适合当作策略。)


这里考查的依然是求最大值。


先把max_score和max_num_rolls设为0,然后从1~10循环,通过调用make_averaged计算均分。若均分大于最大分max_score,则记录当前的max_score和max_num_rolls。


最后输出max_num_rolls。


代码如下:


根据以上模拟,我们得出结论:对于六面骰子,每次投掷6个骰子,得到的均分最高。



Copyright © 2024 aigcdaily.cn  北京智识时代科技有限公司  版权所有  京ICP备2023006237号-1