ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python海龟绘图:钝角三角形的角度陷阱与绘制方法

2026/9/4 12:37:16 拓冰建站 浏览量
Python海龟绘图:钝角三角形的角度陷阱与绘制方法 如果你跟着“Python 海龟绘图 100 题”练到第 12 题大概率会遇到一个很现实的问题画正三角形很简单for i in range(3)加left(120)就出来了但换成“钝角三角形”很多人的第一版代码画出来的根本不是钝角甚至图形都不闭合。原因不复杂海龟绘图里真正转的角度是“外角”不是三角形内角。钝角三角形的内角大于 90°外角反而小于 90°所以直觉很可能会骗你一次。这篇文章就以“第 12 题 钝角三角形”为例子把完整代码、几何原理、批量绘制和常见报错一次讲清楚。读完你可以直接跑通这道题也能顺手把这个思路用到后面的任意多边形题目里。先给结论这道题不需要安装任何第三方库Python 3 自带的turtle模块就够了普通办公电脑都能运行。核心任务是画一个有一个内角大于 90° 的封闭三角形并且要能稳定复现、能调整边长、能批量画出多个不同钝角三角形。下面直接开始。1. 核心能力速览能力项说明题目编号Python 海龟绘图 100 题第 12 题编程语言Python 3.x依赖模块标准库turtle不需要第三方库核心知识点三角形内角与外角关系、海龟转向、坐标闭合、函数封装硬件要求无特殊要求普通电脑即可运行支持平台Windows / macOS / Linux启动方式Python 脚本运行或 IDLE / VS Code / PyCharm 直接运行结果验证画布中出现一个内角大于 90° 的封闭三角形扩展能力函数封装后支持传入不同角度批量绘图适合读者Python 初学者、中小学生编程练习、准备带课的老师这道题的“技术门槛”很低但它非常适合用来验证一个关键概念**海龟每次left()转过的角度不是图形内角而是沿着前进方向需要改变的方向角。**当你把这一点理解清楚后面画平行四边形、五角星、任意多边形都会顺畅很多。2. 适用学习场景与使用边界钝角三角形这道题最适合三类人刚开始学习 Python 循环和函数的初学者需要一个能立刻看到反馈的小项目。正在带 Python 入门课的教师可以用它讲“外角”而不是空背公式。刷海龟绘图 100 题、想逐步积累图形代码的练习者。它能够解决的问题很明确让学习者通过图形验证角度计算是否正确。比如你写left(150)、left(60)还是left(30)画面会直接告诉你答案。但也要清楚它的边界。turtle是教学绘图工具不是 CAD不适合用来做精确机械制图或复杂几何渲染。它一次只能在一个窗口里顺序绘制也没办法像图像处理库那样批量导出 PNG 文件。如果后续要做大量几何图形、自定义导出图片应该转向matplotlib或Pillow。另外如果你是在整理题库或者把别人的题目做成教程记得保留原题库名称和出处并在自己的示例代码里写明这是练习用途不涉及版权素材和隐私数据。3. Python 海龟绘图环境准备与前置条件海龟绘图的运行环境要求非常简单下面是通用前置检查清单。3.1 确认 Python 已安装在终端或命令行里执行python --version如果提示Python 3.10.x之类的版本号说明 Python 已安装。如果提示找不到命令Windows 用户在安装 Python 时一定要勾选Add python.exe to PATHLinux 用户通常会安装python3。python3 --version3.2 确认 turtle 模块可用turtle是 Python 标准库正常安装的 Python 都自带不需要pip install。可以执行这一条进行验证python -c import turtle; print(turtle.__name__)只要能输出turtle说明模块可用。3.3 文件命名避免冲突有一个初学者很容易踩的坑把自己的脚本命名为turtle.py。这样程序在导入时可能优先找到自己写的文件导致报错。建议项目目录结构如下turtle-lessons/ └── 12_obtuse_triangle.py文件名不要叫turtle.py也不要在同一目录下创建turtle.py文件。3.4 编辑器选择IDLEPython 自带打开脚本后直接按F5运行。VS Code安装 Python 扩展后右上角点运行按钮。PyCharm新建 Python 文件直接运行即可。4. Python 海龟绘图安装部署与启动方式海龟绘图不需要所谓“安装部署”更准确的说法是“创建脚本并启动运行”。下面用最直接的方式实现第 12 题。4.1 新建脚本文件新建12_obtuse_triangle.py写入以下完整代码import turtle def draw_obtuse_triangle( ab100, bc80, obtuse_angle120, start_x-80, start_y0 ): t turtle.Turtle() t.speed(5) t.pensize(2) t.color(black, lightblue) # 把海龟移动到起点 A t.penup() t.goto(start_x, start_y) t.pendown() # 开填充 t.begin_fill() # 画第一条边 AB水平朝右 t.setheading(0) t.forward(ab) # 在 B 点转向。这里 obtuse_angle 取的是内角 # 海龟实际转过的角度是 180 - obtuse_angle t.left(180 - obtuse_angle) t.forward(bc) # 画第三条边 CA让图形闭合 t.goto(start_x, start_y) t.end_fill() # 进入消息循环窗口不会闪退 turtle.done() if __name__ __main__: draw_obtuse_triangle()4.2 命令行运行打开终端进入脚本所在目录然后执行python 12_obtuse_triangle.py运行后会出现一个海龟绘图窗口里面画出一个带浅蓝色填充的三角形。关闭窗口后程序结束。4.3 IDLE 运行在 IDLE 中打开脚本按F5运行。运行后同样会弹出绘图窗口。4.4 判断是否启动成功正常现象是终端不报错。自动弹出标题为Python Turtle Graphics的窗口。能看到海龟从起点画出一条水平线然后左转、继续画线最后回到起点。三角形内部出现浅蓝色填充。如果双击脚本后窗口一闪而过最常见原因是代码末尾没有turtle.done()。turtle.done()会启动事件循环让绘图窗口保持打开等待用户点击关闭。5. 钝角三角形几何原理为什么画钝角反而转小角这道题最容易卡住的地方在这里。先看画等边三角形的经典写法import turtle t turtle.Turtle() for _ in range(3): t.forward(100) t.left(120) turtle.done()等边三角形每个内角是 60°代码里转的却是 120°。为什么因为海龟从一个边转到下一条边时改变的是“行进方向”而“行进方向”与“三角形内角”是互补关系也就是海龟转向角 180° - 内角等边三角形内角 60°所以转 120°。这个 120° 叫外角。第 12 题要求画钝角三角形也就是有一个内角大于 90° 且小于 180°。这里以“顶角为 120°”的钝角三角形为例内角 120° 转向角 180° - 120° 60°关键在于**内角是 120°海龟实际只转 60°。**很多初学者会把钝角三角形写成left(120)结果画出的图形反而是一个锐角很大的锐角三角形原因就是弄反了内外角关系。再看上面完整代码里的画法从起点 A 水平向右画AB长度 100。海龟到达 B 点此时朝向仍然向右。left(180 - 120)转为左转 60°。再前进 80到达 C 点。用goto(start_x, start_y)直接连接 C 到 A完成闭合。其中 B 点处的内角就是 120°因为从 B 点看 A 点方向是水平向左从 B 点看 C 点方向是与水平方向成 60°两者夹角正好是 120°。补充一点上面代码只在 B 点做了一次“外角转向”第三条边是通过goto坐标闭合的。这样做的好处是不需要预先计算出第三条边的长度只需画两条边再用直线连接起点图形一定闭合。实际绘图中不一定要严格“转三次”才能画出三角形“走两条边再回到起点”同样能形成封闭三角形而且代码更直观。6. Python 海龟绘图第 12 题功能测试与效果验证代码写完要做的不是只看一眼“画出来了”而是按功能点验证。6.1 测试 1基本钝角图形执行默认参数draw_obtuse_triangle()预期结果绘制出一个封闭三角形。图形上方有一个明显大于 90° 的钝角。三角形填充为浅蓝色。画布可以正常关闭无异常输出。判断是否成功的标准是从 B 点向两条边的延长方向观察能看到内侧夹角大于 90°。如果你不确定可以把obtuse_angle改为 120这是最容易识别的钝角之一。6.2 测试 2改变钝角大小draw_obtuse_triangle(ab120, bc80, obtuse_angle150)预期结果三角形比默认版本更扁。B 点处内角接近 180°但仍然是封闭三角形。图形横向跨度更大但不会超出默认画布范围。判断标准内角为 150° 时海龟转向角是 30°所以图形会非常扁平。如果你把obtuse_angle设置成 95°仍然可以得到一个钝角很小的三角形适合做对比实验。6.3 测试 3验证图形闭合在函数内部加入验证点 C 位置的打印import turtle t turtle.Turtle() t.speed(5) start_x, start_y -80, 0 ab, bc, obtuse_angle 100, 80, 120 t.penup() t.goto(start_x, start_y) t.pendown() t.setheading(0) t.forward(ab) t.left(180 - obtuse_angle) t.forward(bc) print(C点坐标, t.pos()) t.goto(start_x, start_y) print(回到起点坐标, t.pos()) turtle.done()预期结果C点坐标 (20.00, 69.28) 回到起点坐标 (-80.00, 0.00)C 点坐标接近(20, 69.28)说明两条边长度和转向角度符合预期。如果 C 点坐标和起点坐标重合说明最后的goto成功闭合。6.4 测试 4修改画笔和填充参数把代码里t.color(black, lightblue)改成t.color(black, pink)或者加一行t.hideturtle()预期结果海龟箭头隐藏图形填充颜色变化。这说明turtle.Turtle()实例的属性可以像普通 Python 对象一样修改。7. Python 海龟绘图参数化函数与批量绘制前面的代码已经把“画一个钝角三角形”封装成了函数这就为批量绘图打下了基础。所谓批量任务在这里就是传入多组起点坐标和角度参数循环画多个钝角三角形。下面是一套适合课堂演示和数量测试的批量代码import turtle def draw_one_obtuse_triangle( pen, start_x, start_y, ab, bc, obtuse_angle ): pen.penup() pen.goto(start_x, start_y) pen.pendown() pen.setheading(0) pen.forward(ab) pen.left(180 - obtuse_angle) pen.forward(bc) pen.goto(start_x, start_y) def main(): screen turtle.Screen() screen.setup(900, 500) screen.bgcolor(white) pen turtle.Turtle() pen.speed(3) pen.pensize(2) pen.color(black, orange) cases [ # start_x, start_y, ab, bc, obtuse_angle (-300, 0, 100, 80, 100), (-30, 0, 100, 80, 120), (240, 0, 100, 80, 150), ] for case in cases: start_x, start_y, ab, bc, obtuse_angle case # 每组画之前可以换填充色方便区分 pen.color(black, orange) pen.begin_fill() draw_one_obtuse_triangle(pen, start_x, start_y, ab, bc, obtuse_angle) pen.end_fill() turtle.done() if __name__ __main__: main()运行效果是在同一张画布上画出三个并列的钝角三角形内角分别是 100°、120°、150°。这三个图形横向排列每一个都是封闭的可以直接比出“钝角越大图形越扁”的视觉效果。批量绘制时还有几个工程化建议把起点坐标、边长、角度集中放到cases列表里后续增加图形不需要改动绘图函数。每个图形开始绘制之前先penup()再goto()能避免海龟移动时留下多余线条。绘制前设置好画笔颜色和填充色每个图形独立使用begin_fill()和end_fill()。图形较多时把海龟速度调成0这是最快绘制模式。这里的批量循环虽然简单但已经具备“任务配置列表 循环执行 图形绘制”的基本形态。如果后面要画 100 个题目里的复杂图形可以把每个图形封装成一个独立函数再用主函数统一调度。8. Python 海龟绘图运行状态与资源观察海龟绘图不是重计算任务一般不需要关注显卡、显存这类指标。值得观察的主要是绘制状态和窗口生命周期。8.1 绘制速度t.speed(5)表示中速绘制。speed参数可以取1到10数值越大越快。0表示最快但并不是立刻完成只是关闭了动画延迟。批量画 3 个三角形时肉眼几乎不需要等待如果要画几十个可以把速度调高。8.2 绘图窗口占用海龟绘图窗口正常会占用屏幕中央区域默认大小约几百像素宽。在批量绘制多个图形时建议先调用screen turtle.Screen() screen.setup(900, 500)这样可以避免图形因为画布太小而被截断。这里使用900x500的逻辑像素在不同显示器上可以按实际需求调整。8.3 CPU 与内存表现在普通配置的电脑上绘制几十个三角形不会产生明显负载。真正需要留意的是程序运行到turtle.done()后会进入事件循环终端不会自动返回。如果你在自动化脚本里执行完绘图后还想做后续处理可以改用turtle.exitonclick()让用户点击画布后退出。turtle.exitonclick()这样程序会在用户点击窗口时结束适合需要等待用户查看结果的场景。8.4 常见运行状态说明状态表现说明正常绘制出现窗口海龟动起来代码进入主循环窗口保持绘制完成后窗口不关闭有turtle.done()点击退出点击窗口后程序结束使用turtle.exitonclick()终端不返回命令执行后没有退出提示仍在事件循环中属正常状态9. Python 海龟绘图常见问题与排查方法问题现象可能原因排查方式解决方案双击脚本后窗口一闪而过缺少事件循环看代码末尾是否有turtle.done()或turtle.exitonclick()在文件末尾添加对应调用提示No module named turtlePython 环境异常或文件命名冲突执行python -c import turtle不要将脚本命名为turtle.py如果环境精简重装完整 Python画出来是锐角而不是钝角把内角和外角搞混检查obtuse_angle是否大于 90°把obtuse_angle设置为 90 到 170 之间的值图形没有闭合缺少回到起点的操作检查是否有goto(start_x, start_y)画完第二条边后回到起点三角形被截断在画布外起点坐标或边长超出画布范围打印起点和终点坐标调小边长或使用screen.setup()调大窗口填充颜色不是预期颜色填充模式开始/结束位置不对检查begin_fill()和end_fill()是否配对保持路径连续不要中途penup()图形位置偏到角落起点没有计算好观察起点坐标把start_x、start_y设置在0附近海龟箭头留在图形上没有隐藏海龟检查是否调用turtle.hideturtle()在画完后调用t.hideturtle()窗口标题不是默认英文不同系统显示不同确认窗口图标使用screen.title(第12题 钝角三角形)自定义标题如果代码报错信息指向某一行优先检查这一行的缩进。Python 中函数内部的代码必须有统一的缩进否则会出现IndentationError。10. Python 海龟绘图最佳实践与使用建议第 12 题做出来后我建议你把代码做一次“工程化整理”而不是停留在“能运行”。第一把边长和角度作为函数参数。不要写死成一堆魔法数字。这样后续改一个数值就能得到新的三角形不需要改动绘图逻辑。draw_obtuse_triangle(ab100, bc80, obtuse_angle120)第二每次画图前先确认起点。海龟绘图默认从(0, 0)开始如果你的图形边长很大起点位置会影响图形显示范围。一个稳妥的做法是所有函数都支持传入start_x和start_y。第三给代码加上必要的打印或坐标记录。比如在画完第二条边之后用t.pos()记录 C 点坐标再用数学公式判断夹角是否为钝角。这比单纯肉眼观察更可靠也方便别人复现你的结果。第四批量绘图时建立可维护的任务列表。也就是第 7 节里cases列表的写法。后续如果想画更多三角形只需要在列表里加一行数据不需要复制粘贴一大段函数代码。第五代码注释写清楚“这里为什么转 60°”。代码可以写十年不坏但如果不记录设计思路一个月后再看自己也会忘。注释尽量保留公式来源和设计依据。# 内角为 obtuse_angle 时海龟转向角度为 180 - obtuse_angle第六如果要发布到博客或课堂讲义可以顺手做一个小版本记录题目第 12 题 钝角三角形 实现语言Python 3 使用模块turtle 参数默认值ab100, bc80, obtuse_angle120这类信息以后整理题库时非常有用。11. 总结与下一步第 12 题“钝角三角形”本身不难但它把 Python 海龟绘图里最容易忽略的“外角”问题暴露出来了。画等边三角形时left(120)能成立不是因为你记错了 60°而是因为海龟转的一直是外角。这道题用 120° 钝角反向推出来转向角是 60°刚好和等边三角形相反是很好的辨错训练。建议你本地先跑一遍最小代码确认能画出封闭钝角三角形再试试修改obtuse_angle为 100、150观察图形变化。最容易踩的坑就三个忘记turtle.done()导致窗口闪退、把钝角设成 60°、以及没有回到起点导致图形不闭合。下一步可以继续刷后面的题目了。下一次画四边形或五角星时记得继续用“海龟转向角 180° - 内角”这个规则去推导很多多边形题目的角度问题都能用这一个思路解决。