在编程中发现数学之美——使用Python小龟绘制多边形

在使用数学知识画出很酷的各种图形之前,你需要先学习Python编程语言的基础知识。本文将会带你熟悉以下编程概念:循环、变量、函数、使用小龟模块绘制图像。本文假设你已经安装了Python,如果没有,欢迎你访问我在B站的视频课程,你可以在编程入门—使用python语言开发游戏课程中学习下载Python并安装以及Python的基础操作。本文是在Python编程中发现数学之美的第一章内容,视频内容在这儿,其余内容会陆续发布在我的B站专栏中,欢迎关注。

小龟模块

Python的小龟模块来源于Logo语言。Logo语言发明于1960年代,目的是使所有人都能够学习编程。Logo语言有可供人机交互的图形界面。Python的设计者对Logo语言的小龟模块如此喜欢,以至于他们也在Python中设计了小龟模块。

在Python的小龟模块中,你可以控制类似小龟的图像,像在游戏中控制一个角色。你需要给小龟清晰明确的指令,指导小龟在屏幕上的动作。因为小龟的运动会留下轨迹,我们可以通过控制小龟运动画出各种图形。

导入小龟模块

打开IDLE,新建文件,保存为myturtle.py。使用小龟模块,你需要首先引入它的函数。在Python中,函数是指完成某一功能的可重复使用的一段代码。Python中有许多内置函数,当然你也可以创建自己的函数,我们称之为自定义函数。本章中你就将写自己的自定义函数。

模块在Python中指一个文件,这个文件中含有预定义的函数和定义,这些函数和定义你可以在其他程序中使用。小龟模块在你安装Python的时候已经自动安装了。

Python中引入模块的方法有许多,我们使用简单的一种,在myturtle.py中,输入以下语句:

from turtle import *

from表示我们将从外部的文件中导入某些内容。我们在from后输入要导入的模块,这里是turtle。我们用import获取欲导入的内容,这里的通配符*表示我们将turtle的内容全部引入到当前的程序。

移动小龟

现在你已经引入了小龟模块,你可以输入指令输入指令移动小龟了。我们将使用foreward()函数(缩写为fd)来命令小龟移动一段距离并在后面留下轨迹。注意,forward()是我们从turtle小龟模块中引入函数中的其中一个。使小龟移动:

foreward(100)

这里,括号中的100表示小龟移动的步数。在编程语言中,100是传递给foreward函数的参数。当然,你也可以将100改成其它任何值。保存,运行程序,一个新窗口会打开,窗口中心有一个箭头。

正如你所见,小龟起点为窗口正中,向右移动了100步(100个像素)。注意,默认的形状是一个箭头,不是乌龟。输入以下指令变为乌龟的形状:

from turtle import *
forward(100)
shape('turtle')

或许你已经猜到了,shape()是小龟模块中定义的另一个函数。这个函数让你可以定义默认的箭头为其他形状,如圆、方块。这里,shape()函数的参数是字符串'turtle',不是数字。保存并运行,你会看到箭头的形状已经变成了小龟。

改变方向

小龟只能在它的方向上向前走。改变方向,你首先必须使用right()left()函数让小龟转一定的角度。修改程序如下:

from turtle import *
forward(100)
shape('turtle')
right(45)
forward(150)

你会发现,小龟从窗口中心开始,向前走100步,右转45度,然后向前走了150步。

练习1-1:修改代码,使小龟的轨迹画一个正方形。

循环执行代码

每一种编程语言都有自动重复执行一定次数的方法。这个功能很重要,因为重复执行避免了你一遍又一遍输入相同内容代码的麻烦。它还可以帮你避免输入错误,从而保证程序正常运行。

for循环

Python语言中使用for执行循环代码。我们用range指明循环次数。打开IDLE,新建文件for_loop.py,输入:

for i in range(2):
    print('hello')

这里,range()函数为每一个循环i创建了一个迭代器。迭代器每次使用会依顺序产生新值。括号中的2是传递给range()函数的参数,与前面传递给forward()right()参数类似。

这个例子中,range(2)创建了一个包括两个值:0和1的序列。对两个值中的每一个,for分别执行冒号之后的代码,在这儿是执行打印hello

记住,在所有需要循环执行的代码(冒号之后的)前按TAB键(或4个空格),以使这些代码有相同的缩进。缩进告诉Python哪些代码行在循环内容需要for循环执行。别忘了for语句最后的冒号,它告诉Python下面的代码是需要循环执行的。保存、运行以上代码,你会看到输出两行hello

打印两行hello是因为range(2)创建了包含两个数字0和1的序列。这表示for指令逐个访问序列中的0和1,每次访问打印hello。我们可以对代码做如下修改:

for i in range(10):
    print(i)

保存并运行,结果是打印了从0到9的10个数字。

你注意到了吗?range()函数的序列是从0开始,到参数的前一个数字结束(这里是9)。上面的代码的作用可简述为“对从0到9范围中的每一个值,打印当前的数字。”for循环重复执行代码,直到超出数字范围。下面我们在小龟程序中使用for循环。

使用for循环画正方形

上面的练习1-1中,你面临的挑战是使用forward()right()画正方形。完成这个任务,你不得不重复forward(100)right(90)四次。这不但需要输入许多代码,而且输入过程中还往往出错。

现在我们有了for循环,就可以省去重复输入相同代码的麻烦了。下面的myturtle.py程序,使用for代替了重复的forward()right()语句:

from turtle import *
shape('turtle')
for i in range(4):
    forward(100)
    right(90)

注意,shape('turtle')语句应该在import语句后面其他绘画代码的前面。for循环内部的两行代码告诉小龟,向前100步然后右转90度(想想对小龟来说哪边是左哪边是右)。由于正方形有四条边,我们使用range(4)让代码循环四次,运行代码的结果会如下面的图片:

1_squares.gif

小龟向前100步然后右转,重复了四次,最终回到原来出发的点。恭喜你,你使用for循环画出了正方形。

创建自定义函数

我们写了画正方形的代码,我们可以使用个小魔术将代码保存起来,以后需要画正方形的时候随时调用。每种变成语言都有实现这个功能的方法,在Python里它被成为函数,函数在编程中非常重要。函数使代码精巧并易于维护修改,将复杂问题化解为若干函数的过程中,也有助于你找到解决问题的最佳方法。在前面的代码中你已经使用过Python语言内置的函数,现在我们将学习怎么创建我们自己的函数。

定义函数你需要为它取个名字,可以取任何名字,记住不要与Python语言的关键字相同,如list,range,等等。为函数命名的时候,最后取个有意义的名字,这样你调用的时候能够方便的想起来。这里我们为我们画正方向的函数命名为square(),因为我们这个函数的作用是画正方形,修改刚才的程序mytutle.py,增加下面内容:

def square():
    for i in range(4):
        forward(100)
        right(90)

def关键字告诉Python我们正定义一个函数,后面的将会是函数名字,这儿是square()。别忘了square后面的两个括号!Python中它们的出现表示现在要处理的是函数。后面我们将在括号中放数值,但即使没有任何数值,括号也必须要有以让Python知道这是个函数。另外,不要忘记函数定义语句末尾的冒号。注意,函数内容部分的代码都有向右4个空格的缩进,这是告诉Python哪些代码是函数内部的语句。

如果现在运行,什么也不会出现。你定义了函数,但还没有运行它。要运行函数你需要调用它,对代码继续修改,修改后的代码如下:

from turtle import *
shape('turtle')
def square():
    for i in range(4):
        forward(100)
        right(90)
square()

保存,运行。程序的最后一行,通过square()调用了函数。现在你可以在程序任何位置调用square()函数来方便地绘制四方形了。

你还可以将这个函数放在循环中,来绘出更复杂的图形。例如,画一个正方形,右转一定角度,画另一个正方形,继续右转...这样循环若干次。

下面的练习将绘制一个由正方形组成的有趣的图形。要画出这个图形,需要你的小龟忙活一会儿,所以你可以通过调用speed()函数控制小龟的速度。在shape('turtule')语句后面插入一行speed(0),使小龟移动的速度达到最快(speed(1)使小龟速度最慢)。当然你可以调整speed()的参数。

练习1-2:正方形组成的圆。写程序,这个程序将画60个正方形,每画一个正方形后右转5度。程序中要使用循环语句。运行结果如图:
circle of squares

使用变量绘制图形

现在为止我们的正方形大小都相同。想要不同大小的正方形,要改变小龟前进的距离。要通过每次修改函数获得不同的距离,那太麻烦了。我们用变量来解决这个问题,变量在Python中表示可以改变的值。变量与数学函数表达式中的x相似。

数学中的变量名字是一个字母,编程中你可以给变量取任何名字。类似与函数,我建议你的变量名称应该是有意义的,便于记忆和理解。

函数中使用变量

定义函数的时候,可以将变量作为传递给函数的参数。例如,可以修改square()的定义,来画不同尺寸的正方形,对myturtle.py修改如下:

def square(sidelength):
    for i in range(4):
        forward(sidelength)
        right(90)

这里我们在函数定义中增加了sidelength。现在你调用这个函数的时候,要在括号间传递一个值给函数,这个值我们称之为参数。传递的任何值都将作为sidelength的数值。例如,调用square(50)square(80)将分别绘制边长为50和80的正方形。

变量错误

调用函数的时候,如果函数定义中有参数,而调用时未指明参数,Python会报错。如调用上面的函数square(),IDLE中会出现以下错误提示:

TypeError: square() missing 1 required positional argument: 'sidelength'

这个错误提示我们缺少了一个需要的参数(这儿是sidelength)。怎样避免出现这种错误呢?我们可以在定义函数时给参数赋一个默认值,例如这样:

def square(sidelength=100):

这里,我们给sidelength赋值100。现在我们调用square时如果填写了参数,会绘制边长为我们填写数值的正方形,如果我们没有填写,也不会报错,会绘制边长为100的正方形。我们可以这样调用函数:

square(30)
square(50)
squre()

运行结果会是这样:


1_func_params.gif

给函数参数设置缺省值,我们可以不同担心调用时忘记填写参数了。在编程中,我们称之为让程序变得健壮

练习1-3:绘制三角形。写triangle()函数,函数功能为绘制给定变长的三角形。

等边三角形

多边形是有多个边的图形。等边三角形是多边形的一种,有三条边且变长相等。

triangle

等边三角形有3个都为60度的内角,你的数学老师肯定告诉过你,三角形内角和为180度。

写绘制三角形的函数

现在,让我们用目前学到的知识画出一个等边三角形。因为每个内角都是60度,我们可以将right()参数修改为60度,像下面这样修改myturtle.py

def triangle(sidelength=100):
    for i in range(3):
        forward(sidelength)
        right(60)
triangle()

保存,运行。你看到了什么?


triangle

我们没看到三角形,看起来画的好像是六边形的一半。想想为什么?如果你是图上的小龟,站在它的位置,向右转60度,循环3次……是不是也会走出上图的路径。你应该想到了,向右转,不应该转60度,而应该转180-60=120度。

练习1-4:写绘制多边形的函数。函数名字为polygon,参数为一个整数,函数功能是绘制多边形,边的条数为参数值。

改变变量的值

我们可以这样改变变量的值:在每一个循环中让变量的值递增,结果是每次循环所画的正方形比上一次大一些。例如我们使用length变量,我们用这个变量的值作为变长画正方形,下一个循环中为length增加5:

length = length + 5

这是一个赋值语句,length变量被赋予length原来的值加上5。打开IDLE,输入以下语句:

>>> radius = 10

上面我们创建了一个变量,其名字是radius,其值为10。任何时候你都可以重新给这个变量赋一个新值:

>>> radius = 20

现在,变量radius中的值为20了。

练习1-5:创建一个函数,函数的功能为画60个正方形,每画一个正方形后旋转5度,且边长增加。初始边长为5,每次增加5。结果应该如图所示:

总结

本文我们学习了使用Python的小龟模块turtle和它的内置函数forward()right()。我们探索了使用这个两个函数绘制复杂有趣的图形。turtle是Python其中一个包,你可以访问Python的官方网站https://python.org/,上面有turtle更全面的介绍。

本文我们还学校了如何定义自己的函数,自定义函数可以让我们实现代码复用。我们还学习了for循环。

练习1-6:星星的诞生。首先你要写一个名为star的函数,函数功能是绘制一个五角星,如图:

star

,接下来,你需要写另一个starSpiral()函数,函数的作用是绘制旋转的五角星,结果如下图:
stars spiral

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1u784oq3iz7tj

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335