Racket 学习笔记

本文档是Racket编程的学习笔记,从基本的运算、函数和程序设计开始,讲解了如何系统地解决问题并清晰地表达解决方案。内容涵盖数字、字符串、图像的运算,以及函数、程序的定义和组合。此外,还探讨了条件编程、图像处理和数据结构,旨在帮助初学者理解编程的本质,创建可读性强的程序。
摘要由CSDN通过智能技术生成

Prologue: How to Program 前奏: 怎样编程

好的编程不仅仅是学习一门语言的机制。**最重要的是,要记住,程序员创建程序是为了让其他人将来阅读。**一个好的程序反映问题陈述及其重要概念。它有一个简洁的自我描述。简而言之,好的编程就是系统地解决问题,并在代码中传达系统。最重要的是,这种编程方法实际上使每个人都能访问编程—因此它可以共享的(使每个人都看得懂)

这门程序课经审核与K2的高中生又适合于大学一年级的新生。

对于大一新生,前奏:怎样编程(Prologue)我们建议通过create-rocket-scene进入Big-bang程序向学生展示动画是如何工作的。我们将“Big-bang”解释为底层操作系统的一小部分,即负责时钟滴答、击键和其他事情的部分。

一旦涵盖了“Big-bang”,我们将继续以同样的非正式风格讨论基本主题:

数字、布尔值、字符串和图像(运算 Arithmetic);

间隔和枚举(间隔、枚举和分项 (Intervals, Enumerations, and
Itemizations
);

和结构类型(添加结构 Structure)

对于K-12高中生,在此就不再一一叙述了

在定义区 definitions area(上部)(+ 1
1),注意符号与数字之间必须有空格,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tv2jPNpB-1618589248396)(media/fd61b4f9c80da7a6fa6029d489cad95a.png)]

程序由表达式组成。你们见过数学中的表达式。现在,表达式要么是一个普通的数字,要么以左括号“(”开始,以匹配的右括号“)”结束

程序运行的结果在 交互区显示 interactions area.(下部)

注:这本书不会教你Racket,即使编辑器叫DrRacket。请参阅序言,特别是关于DrRacket和教学语言的章节,了解选择发展我们自己的语言的细节。

运算和计算

字符串
string,首先需要知道的是,在BSL中,文本是用双引号(")括起来的任意键盘字符序列。我们称它为字符串。因此,“hello
world”是一个完美的字符串。

(string-length “hello world”) 字符串长度

> (string->number “hello world”)
#false

这个既不是数字也不是字符串,他是一个Boolean(布尔值)

Boolean(布尔值)在逻辑中,真值或逻辑值是指示一个陈述在什么程度上是真的。在计算机编程上多称作布尔值。布尔值是
True 或**“”** False 中的一个。动作脚本也会在适当时将值 True 和 False
转换为 1 和
0。布尔值经常与动作脚本语句中通过比较控制脚本流的逻辑运算符一起使用。

使用
string->number把字符串->数字,但括号内的不是数字,结果:#false

很简单: 如果x和y为真,**(and x
y)为真(#true);如果x或y,或两者都为真,则(or x
y)为真(#true);当x为#false时,(not x)**会精确地为 #true

也可以把数字转化为布尔值

插入图像

DrRacket会对图片进行响应。与许多其他编程语言相比,BSL能够理解图像,并且它支持图像的运算,就像它支持数字或字符串的运算一样。简而言之,您的程序可以使用图像进行计算,您可以在交互区域进行计算。此外,像其他编程语言的程序员一样,BSL程序员创建其他人可能会觉得有用的库。使用这些库就像使用新单词扩展您的词汇表,或者使用新的原语扩展你的编程词汇表。我们称这种图书馆为教学包(
teachpacks),因为它们对教学很有帮助。

在此首先要在定义区输入
(require
2htdp/image)

overlay-覆盖

image-width-图像宽度

以上只是测量图像尺寸

还有两种操作很重要:
empty-scene
(空场景)和place-image放置图像。第一个创建了一个场景,一个特殊的矩形。第二种是将图像放入这样的场景中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxJevYbk-1618589248407)(media/b2fb688aac75e6dea69f30b088719de0.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AJDfzoQE-1618589248409)(media/f82de6aae690b6326e775686ad91f046.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wP7TNoT1-1618589248412)(media/7846585ac5380dfebd52d8abd934f228.png)]

输入和输出

我们考虑程序时,乍一看,函数就像表达式一样,总是在左边有一个y,后面跟着一个=符号和一个表达式。然而,它们不是表达。你在学校里经常看到的函数符号是完全误导人的。在DrRacket中,你写函数的方式有点不同:

(define
(y x)
(*
x x)) 定义y与x的关系为x*x即——y=x*x

定义说“把y看作一个函数”,它像表达式一样计算一个值。然而,一个函数的值取决于一个叫做输入的东西的值,我们用**(y
x)**来表示它,因为我们不知道这个输入是什么,所以我们用一个名字来表示输入。按照数学传统,我们用x代替未知输入;但很快,我们会用到各种各样的名字。

这第二部分意味着你必须提供一个数字——为x,以确定一个特定的y值。当你这样做时,DrRacket将x的值插入到与函数相关的表达式中。这里的表达式是(*
x
x),当x换成一个值,比如1,DrRacket就可以计算出表达式的结果,也叫做函数的输出。

单击RUN并观察没有任何事情发生。在交互区域没有显示任何东西。在DrRacket的其他地方似乎没有什么变化。就好像你什么都没完成似的。但是你做到了。你实际上定义了一个函数并告知DrRacket它的存在。事实上,后者现在已经可以使用该函数了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4pYXayY-1618589248414)(media/477a978f6e49b84a648196df8527214d.png)]

首先:(define
(FunctionName InputName) BodyExpression)

(定义(函数名称 输入名称)表达式))

第二步:(FunctionName ArgumentExpression)

这是一个函数应用程序。第一部分告诉DrRacket你希望使用的函数。第二部分是要应用函数的输入。如果您正在阅读Windows或Mac手册,它可能会告诉您这个表达式“启动”名为FunctionName的“应用程序”,并且它将处理ArgumentExpression作为输入。与所有表达式一样,后者可能是一段普通的数据或一个深度嵌套的表达式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWwyM7ak-1618589248416)(media/0ec03784b78c9d4d71b4e88049130de2.png)]

N种计算方法

你可以用一个条件表达式cond在DrRacket中定义这个函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Smemg9Aa-1618589248417)(media/184f8bf46a903a28cca6557c1e82e2f4.png)]

将cond表达式用于v2火箭:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KWG0duVY-1618589248418)(media/f7232e019fd455aa771b603e56589325.png)]

这可能还是不美观。可以通过找点的方法,设置参数找到对应的表达式:(这就很好看了)

(define (picture-of-rocket.v3 height)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5t6kH6Y-1618589248419)(media/ac47317de7d940543dbef6e0e7dbebb3.png)] (cond

[(<= height (- 60 (/ (image-height
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MQ2azckB-1618589248420)(media/c4e6bcc73e293831cc25731ea4708c9c.png)])
2)))

(place-image
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LGQVWWIF-1618589248421)(media/c4e6bcc73e293831cc25731ea4708c9c.png)]
50 height

(empty-scene 100 60))]

[(> height (- 60 (/ (image-height
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rn2Ih0FA-1618589248422)(media/c4e6bcc73e293831cc25731ea4708c9c.png)])
2)))

(place-image
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eGrfd6tv-1618589248424)(media/c4e6bcc73e293831cc25731ea4708c9c.png)]
50 (- 60 (/ (image-height
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6BEJqt22-1618589248425)(media/c4e6bcc73e293831cc25731ea4708c9c.png)])
2))

(empty-scene 100 60))]))

程序中很多的火箭,显得很乱,是否应该改正呢?看看后面的……

一种程序不同表达

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oiGLvjy6-1618589248426)(media/d86b06594c06ff0ed8a959b2aaf4f008.png)]

这就好了许多。

在理想的程序中,一个小请求(比如更改画布的大小),应该需要同样小的更改方式。使用BSL定义,实现这种简单性的工具。除了定义函数之外,还可以引入常量定义,它们为常量指定一些名称。常数定义的一般形状很简单:(define
Name Expression)

因此,如果键入:(define
HEIGHT 60)

在你的程序中,你说高度(HIGHT)总是代表数字60。这样一个定义的意义是你所期望的。每当DrRacket在计算过程中遇到高度时,它就用60代替。

另外,注意上图的程序由四个定义组成:一个函数定义和三个常量定义。数字100和60只出现两次——一次作为宽度的值,一次作为高度的值。您可能还注意到,对于photo
-of- rocketl
.v4的函数参数,它使用h而不是height。严格来说,这个变化是没有必要的,因为DrRacket没有把高度和高度搞混,但是我们这样做是为了避免把你搞混。(还要注意大小写)

当DrRacket计算(animate
picture-of-rocket.v4)时,它将高度替换为60,宽度替换为100,每次遇到这些名称时,将火箭替换为图像。要体验真正程序员的乐趣,将高度旁边的60换成400,然后单击RUN。你可以在一个100
* 400的场景中看到火箭下降和降落。一个小小的改变就能改变一切。

用现代的说法,您刚刚经历了第一次程序重构。每当您重新组织您的程序以为将来可能的变更请求做准备时,您就重构您的程序。把它写进你的简历。这听起来不错,你未来的雇主可能会喜欢读这样的流行语,即使它不能让你成为一个好的程序员。然而,一个好的程序员永远不会接受的是,让一个程序包含三次相同的表达式:

(-
HEIGHT
(/
(image-height
ROCKET) 2))

每次你的朋友和同事读这个程序的时候,他们需要理解这个表达式计算的内容,也就是,画布顶部和停留在地面上的火箭中心点之间的距离。DrRacket每次计算表达式的值都要执行三个步骤:(1)确定图像的高度;(2)除以2;然后(3)用高度减去结果。每一次,它都得到相同的数字。

这一观察结果需要再引入一个定义:

(define
ROCKET-CENTER-TO-TOP

(-
HEIGHT
(/
(image-height
ROCKET) 2)))

现在用ROCKET- center - to - top替换程序其余部分中的表达式(- HEIGHT (/
(image-height ROCKET)
2)。您可能想知道这个定义应该放在高度定义的上面还是下面。更一般地,您应该想知道定义的顺序是否重要。**对于常数定义,顺序很重要;对于函数定义,它不需要。**一旦DrRacket遇到一个常量定义,它就会确定表达式的值,然后把这个名字和这个值联系起来。例如:

(define HEIGHT (* 2 CENTER))

(define CENTER 100)

当遇到高度的定义时,引起DrRacket抱怨说“中心在它的定义之前就用过了”。相比之下:

像预期的那样。首先是DrRacket会把CENTER与100联系起来。其次,它计算(* 2
CENTER),结果是200。最后,DrRacket把200和HEIGHT联系起来。

虽然常量定义的顺序很重要,但常量定义相对于函数定义的位置并不重要。实际上,如果您的程序包含许多函数定义,它们的顺序也不重要,尽管最好先介绍所有常量定义,然后按照重要性的递减顺序介绍函数的定义。当您开始编写自己的多定义程序时,您就会明白为什么这种顺序很重要。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hejRbcrK-1618589248427)(media/486da076164c5aa6cef507cd5b0f4d7d.png)]

神奇数字:再看看下图,因为我们消去了所有重复的表达式,除了一个数,其它的都从函数定义中消失了。在编程的世界里,这些数字被称为魔术数字,没有人喜欢它们。在你意识到这一点之前,你就忘记了数字所起的作用,以及什么变化是合法的。最好在定义中命名这些数字

这里我们实际上知道50是火箭的x坐标的选择。尽管50看起来不像一个表达式,但它实际上也是一个重复的表达式。因此,我们有两个理由从函数定义中删除50,我们把它留给您去做。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LloHE8CZ-1618589248428)(media/7b53452f0ac632c35109fc1335dc07c8.png)]

  • How would you change the program to create a 200-by-400 scene?

  • How would you change the program so that it depicts the landing of a green
    UFO (unidentified flying object)? Drawing the UFO is easy:

(overlay (circle 10 “solid” “green”)
(rectangle 40 4 “solid” “green”))
  • How would you change the program so that the background is always blue?

  • How would you change the program so that the rocket lands on a flat rock bed
    that is 10 pixels higher than the bottom of the scene? Don’t forget to
    change the scenery, too.

    又一个定义

    回想一下,animate实际上是将其函数应用于自第一次调用它以来经过的时钟滴滴涕的次数。也就是说,关于火箭图片的自变量不是高度,而是时间。我们以前对火箭图的定义使用了错误的名称作为函数的参数;h是height的缩写,而应该用t表示时间:

(define (picture-of-rocket t)
(cond
[(<= t ROCKET-CENTER-TO-TOP)
(place-image ROCKET 50 t MTSCN)]
[(> t ROCKET-CENTER-TO-TOP)
(place-image ROCKET
50 ROCKET-CENTER-TO-TOP MTSCN)]))

这个对定义的小改变立刻澄清了这个程序使用时间就好像它是一个距离。真是个坏主意。

即使你从未上过物理课,你也知道时间不是距离。所以我们的程序是偶然运行的。别担心,虽然;这一切都很容易解决。你所需要知道的只是一些深奥的科学,我们称之为物理学。

物理? !
?好吧,也许你已经忘记了在那门课上学到的东西。又或者你从来没有上过物理课,因为你太年轻或太温柔了。不用担心。这种情况经常发生在最好的程序员身上,因为他们需要帮助人们解决音乐、经济、摄影、护理和其他各种学科的问题。显然,即使是程序员也不是什么都知道。所以他们查找他们需要知道的东西。或者他们和合适的人交谈。如果你和物理学家交谈,你会发现,行走的距离与时间成正比

d=v×t

也就是说,如果一个物体的速度是v,那么这个物体在t秒内移动了d英里(米或像素)

当然,老师应该给你一个正确的函数定义:(这部分内容扩展很多,可以细读)

d(t)= v×t

因为这马上告诉大家d的计算依赖于t
v是一个常数。程序员则更进一步,使用有意义的名字来表示这些单字母缩写:

(define V 3)
(define (distance t)
(* V t))

这个程序片段由两个定义组成:一个函数距离,计算物体以恒定速度移动的距离,和一个常数V,描述速度。

你可能想知道为什么这里V是3。没有什么特别的原因。我们认为每个时钟3个像素是一个很好的速度。你也许并不会注意到这一点。使用这个数字,看看动画会发生什么。

现在我们可以再次修复picture-of-rocket了。函数可以使用(distance
t)来计算火箭下落的距离,而不是将t与高度进行比较。最后的程序如下图所示。它由两个函数定义组成:picture-of-rocket.v6和distance(距离)。剩余常数定义函数定义可读和可修改性。一如既往,你可以运行这个程序与animate(动画):>
(animate
picture-of-rocket.v6)

与以前版本的picture-of-rocket相比,这个版本显示了一个程序可以由几个相互引用的函数定义组成。而且,即使是第一个版本使用+和/
——只是你认为它们是内置在BSL。

当您成为一名真正的程序员时,您会发现程序由许多函数定义和许多常量定义组成。您还将看到函数之间一直相互引用。你真正需要练习的是组织它们,这样你就可以轻松地阅读它们,即使是在完成几个月之后。毕竟,老版本的你或其他人会想要对这些程序进行更改;如果您不能理解程序的组织,那么即使是最小的任务,您也会困难重重。否则,你基本上知道该知道的事情。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HarOxY8Y-1618589248430)(media/2dca7b717927ac12131e6e54fb9b39f7.png)]

您可能认为自己还没有掌握足够的知识来编写对击键、鼠标点击等作出反应的程序。事实证明,你有。除了animate函数之外,2htdp/universe库还提供了其他函数,这些函数将程序连接到计算机中的键盘、鼠标、时钟和其他移动部件上。事实上,它甚至支持编写程序,连接您的计算机与世界上任何其他人的计算机。所以这不是问题。

简而言之,您已经了解了将程序组合在一起的几乎所有机制。如果你了解了所有可用的函数,你就可以编写程序来玩有趣的电脑游戏,运行模拟,或者跟踪商业账户。问题是这是否真的意味着你是一个程序员。对吗?

I Fixed-Size Data

我们把“组织思想”等同于设计,这本书的第一部分向你介绍了设计程序的系统方法。

(快速浏览第一章,跳到第二章,当你遇到你不认识的“算术”时,再回到这里。)

本书的第一部分(I)介绍了BSL的运算,就是在序言中使用的编程语言。

Arithmetic 运算

提醒一下,这里有一个原始表达:我们用 == 表示“根据计算定律等于”

(+ 1 2)
==
3

本章的其余部分将介绍BSL的四种形式的原子数据:数字、字符串、图像和布尔值。

布尔值(Boolean):在逻辑中,真值或逻辑值是指示一个陈述在什么程度上是真的,即逻辑运算。在计算机编程上多称作布尔值。布尔值是“真”
True 或“假” False 中的一个。动作脚本也会在适当时将值 True 和 False 转换为 1
和 0。

我们在这里用“原子(atomic)”这个词来比喻物理学。您无法窥视原子数据的内部,但是您可以使用一些函数将多个原子数据合并到另一个原子数据中,检索这些原子数据的“属性”,等等。本章的部分将介绍其中的一些函数,也称为原语操作(primitive
operations
)或预定义操作(pre-defined
operations
)。你可以在DrRacket附带的BSL文档中找到其他的文件。下一卷《如何设计组件》将解释如何设计原子数据。

1.1 数字运算

大多数人听到“算术”时想到的是“数字”和“对数字的运算”。“数的运算”是指两个数相加,得到第三个数,减去另一个数,确定两个数的最大公约数,以及更多类似的事情。如果我们不按字面意思来计算,我们甚至可以包括角的正弦值,将实数四舍五入到最接近的整数,等等。

BSL语言支持数字及其运算。如在序言中所讨论的,运算操作如+是这样使用的:(+
3 4)也就是前缀表示法。下面是我们的语言提供的一些对数字的操作:
+,
-,
*,
/,
abs,
add1,
ceiling,
denominator,
exact->inexact,
expt,
floor,
gcd,
log,
max,
numerator,
quotient,
random,
remainder,
sqr,

tan.
我们通过字母表选择我们的方式只是为了展示操作的多样性。探索他们计算的东西,然后找出还有多少。

“数(Number)”一词是指各种各样的数字,包括计算数字、整数、有理数、实数,甚至复数。在大多数情况下,您可以放心地将Number与小学时的数轴等同起来,尽管这种翻译有时过于不精确。如果我们想要精确,我们可以使用适当的词:整数、有理数等等。我们甚至可以使用诸如正整数、非负整数、负整数等标准术语来改进这些概念。

Exercise 1. Add the following definitions for x and y to DrRacket’s
definitions area:

(define x 3)
(define y 4)

Now imagine that x and y are the coordinates of a Cartesian (笛卡儿坐标)point.
Write down an expression that computes the distance of this point to the origin,
that is, a point with the coordinates (0,0).

The expected result for these values is 5, but your expression should produce
the correct result even after you change these definitions.

Just in case you have not taken geometry courses or in case you forgot the
formula that you encountered there, the point (x,y) has the distance

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiRfl2cW-1618589248431)(media/5ebe7bd2d18da4e5457aaf3df295520d.png)]

from the origin. After all, we are teaching you how to design programs, not how
to be a geometer.

To develop the desired expression, it is best to click RUN and to experiment
in the interactions area. The RUN action tells DrRacket what the current
values of x and y are so that you can experiment with expressions that involve x
and y:

> x
3
> y
4
> (+ x 10)
13
> (* x y)
12

Once you have the expression that produces the correct result, copy it from the
interactions area to the definitions area.

To confirm that the expression

answer

(define x 12)

(define y 5)

(sqrt (+ (* x x) (* y y)))

1.2 字符串运算 The Arithmetic of Strings

大多数编程语言至少提供一种处理这种符号信息的数据。现在,我们使用BSL的字符串。一般来说,字符串是可以在键盘上输入的字符序列,加上一些我们不关心的字符,这些字符用双引号括起来。在Prologue:
How to
Program
,我们已经看到了一些BSL字符串:
“hello”, “world”,“blue”,
"red"和其他。前两个词可能会出现在对话或信件中;其他的是我们可能希望使用的颜色名称。

BSL包含一个专门使用和生成字符串的操作:string-append,正如我们在Prologue:
How to
Program
中看到的,它将两个给定的字符串连接成一个字符串。可以将string-append看作类似于+的操作。后者消耗两个(或更多)数字并生成一个新数字,前者消耗两个或更多字符串并生成一个新字符串:

> (string-append "what a " “lovely " “day” " 4 BSL”)
“what a lovely day 4 BSL”

当将给定的数字加起来时,没有任何变化;当string-append将给定的字符串连接成一个大字符串时,没有任何变化。如果你想对这样的表达式求值,你只需要想想string-append的明显规律,类似于+:

Exercise 2. Add the following two lines to the definitions area:

(define prefix “hello”)
(define suffix “world”)

Then use string primitives to create an expression that concatenates prefix and
suffix and adds “_” between them. When you run this program, you will see
“hello_world” in the interactions area.

See
exercise 1
for how to create expressions using DrRacket.

Answer

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vBjLl66i-1618589248432)(media/d4dd7779f6ab441855414cce75135bd1.png)]

1.3 混合Mixing It Up

与字符串相关的所有其他操作(在BSL中)使用或生成字符串以外的数据。下面是一些例子:

string-length测量字符串的长度,空格算一个字符

string-ith 摘取字符串s和第i个字母,>(string-ith s
i),i是第n+1位,空格也算一个字符

number->string
使用一个数字并生成一个字符串。

substring
摘录字符串 >(substring s i
j)摘录字符串第i到j字符,位数从0开始,如果没有j,就从i到结束

Exercise 3. Add the following two lines to the definitions area:

(define str “helloworld”)
(define i 5)

Then create an expression using string primitives that adds “_” at position i.
In general this means the resulting string is longer than the original one; here
the expected result is “hello_world”.

Position means i characters from the left of the string, but programmers
start counting at 0. Thus, the 5th letter in this example is “w”, because the
0th letter is “h”. Hint When you encounter such “counting problems” you may
wish to add a string of digits below str to help with counting:

(define str “helloworld”)
(define ind “0123456789”)
(define i 5)

Answer

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d18fLJAG-1618589248433)(media/327d9ed5771277bed6ffb966b0c9db5c.png)]

Exercise 4. Use the same setup as in
exercise 3
to create an expression that deletes the ith position from str. Clearly this
expression creates a shorter string than the given one. Which values for i are
legitimate?

Answer:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IKTUjWL6-1618589248434)(media/39eced10ab053915d8792acc3c9e7660.png)]

1.4 图像运算 The Arithmetic of Images

!要在前面输入:(require 2htdp/image)

图像是可视的、矩形的数据块,例如,一张照片或一个几何图形及其框架。你可以在任何你可以写下表达式的地方插入图像,因为图像就是值,就像数字和字符串一样。

您的程序还可以使用原始操作操作图像。这些基本操作有三种形式。第一种是关于基本形象的创作:

  • circle
    用半径、模式串和颜色串产生圆图像;

  • ellipse
    用两种直径、一种模态字符串和一种颜色字符串产生一个椭圆;

  • line
    用两个点和一个颜色字符串生成一条线;

  • rectangle 用宽度、高度、模式字符串和颜色字符串生成矩形;

  • text
    用字符串、字体大小和颜色字符串生成文本图像;

  • triangle
    用一个大小、一个模态字符串和一个颜色字符串生成一个向上的等边三角形。

    这些操作的名称主要解释了它们创建的图像的类型。你所必须知道的是,模式字符串的意思是“实体”"solid"或“轮廓”
    “outline”,,而颜色字符串是诸如“橙色”“orange”、 “黑色”,
    “black”、之类的字符串。

> (circle 10 “solid” “green”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EjNVeZnn-1618589251959)(media/8b4a3445bb01b28c71bcf8e6db5a0baf.png)]
> (rectangle 10 20 “solid” “blue”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TRcEQV16-1618589251962)(media/57ac028b6ec1f5e38c49d36dedfc026f.png)]
> (star 12 “solid” “gray”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Xm2eNff-1618589251964)(media/126d3d3b4a118f25c04559f5d3a2bf19.png)]

第二类函数涉及图像的图像属性:

> (image-width (circle 10 “solid” “red”))
20
> (image-height (rectangle 10 20 “solid” “blue”))
20

要正确理解第三种构图原语,需要引入一个新概念:定位点(anchor
point
)。一幅图像不仅仅是一个像素,它由许多像素组成。具体来说,每个图像都像一张照片,即像素的矩形。其中一个像素是一个隐式锚点。当你使用一个图像原语来组成两个图像时,这个组合是相对于定位点发生的,除非你明确指定其他点:

  • overlay
    使用中心作为锚点,将它应用到的所有图像放置在彼此之上;

  • overlay/xy
    就像
    overlay
    但是在两个图像参数之间接受两个数字x和y。它将第二幅图像向右移动x个像素,向下移动y个像素——都相对于第一幅图像的左上角移不出所料,负的x使图像向左平移,负的y向上平移;

  • overlay/align
    就像
    overlay但是接受两个将锚点移动到矩形的其他部分的字符串。总共有九个不同的方位,尝试所有的可能性!

    2htdp/image图像库还提供了许多用于组合图像的其他基本函数。当您熟悉图像处理时,您将需要阅读这些内容。现在,我们将介绍另外三种,因为它们对于创建游戏的动画场景和图像非常重要:

  • empty-scene
    创建具有一定宽度和高度的矩形;

  • place-image
    将图像置于场景中的指定位置。如果图像不适合给定的场景,它会被适当地裁剪;

  • scene+line
    使用一个场景、四个数字和一种颜色在给定图像中绘制一条线。用它做实验,看看它是如何工作的。

数字运算 图像运算
(+ 1 1) == 2 (overlay (square 4 “solid” “orange”)
(circle 6 “solid” “yellow”))
==
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B9LztIya-1618589251967)(media/5e0cb172f4614bdef4d887ac007243d8.png)]

(+
1 2) == 3

(underlay (circle 6 “solid” “yellow”)
(square 4 “solid” “orange”))
==
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tP1FttI6-1618589251969)(media/5e0cb172f4614bdef4d887ac007243d8.png)]

(+
2 2) == 4

(place-image (circle 6 “solid” “yellow”)
10 10
(empty-scene 20 20))
==
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PH7SDdlV-1618589251971)(media/4761e4f35f24a38d20b155c5c49d436d.png)]

图 14: 图像创建规律

图像的运算法则与数字的运算法则相似;参见图14以获得一些示例以及与数值算法的比较。同样,没有图像被破坏或改变。像+
一样,这些原语只是组成新的图像,以某种方式结合给定的图像。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值