Python海龟绘图第12题:从零画出钝角三角形,角度推导与代码详解

发布时间:2026/9/5 21:23:59
Python海龟绘图第12题:从零画出钝角三角形,角度推导与代码详解 1. 从一道绘图题出发绘制钝角三角形海龟绘图是 Python 内置模块turtle提供的经典入门玩法很多初学者第一周接触 Python 就会用它画出五角星、樱花树、螺旋线。把海龟绘图拆成 100 道练习题来训练是一种很高效的刻意练习方式因为它把数学概念、坐标方向、循环结构、函数封装揉在了一起。第 12 题很常见绘制一个钝角三角形。要求一般是这样使用海龟绘图画一个钝角三角形三角形中必须有一个角大于 90 度且小于 180 度程序运行后能看到清晰、完整的三角形轮廓。这道题看起来比画等边三角形难一点但又不至于难到需要引入复杂几何算法。它真正考察的是两个核心点你是否真的理解海龟的“转向角度”和“三角形内角”之间的关系你是否能把“已知角度画三角形”这类问题做成一个通用的函数而不是每次手动硬编码。很多学员画钝角三角形时照着网上的代码抄了一遍能画出图形但问一句“为什么转向150度而不是30度”就答不上来。本文就把这个问题一次讲清楚并提供可直接运行的代码、逐步推导过程、常见踩坑点。2. 环境准备与版本说明开始写代码之前先确认基础环境。这里以最常见的 Python 3 环境为例。操作系统Windows 10/11、macOS、Linux 均可Python 版本Python 3.8 及以上使用 3.10 体验更好开发工具IDLE、VS Code、PyCharm 都可以依赖模块turtlePython 标准库无需pip install。turtle模块是 Python 自带的标准库也就是说安装好 Python 就自动拥有它。如果你还不知道本机是否具备条件打开终端或命令提示符输入下面的命令检查python --version如果显示类似Python 3.10.7就说明 Python 环境可用。接着输入python -c import turtle; print(turtle ok)如果输出turtle ok那就可以直接进入代码阶段了。如果这段命令报错ModuleNotFoundError说明 Python 安装异常或被精简过建议重新安装完整版 Python。有一点要提醒新手当你用 VS Code 或 PyCharm 运行海龟绘图程序时程序通常会打开一个独立的图形窗口。如果你的电脑上报错No module named tkinter说明 Python 缺少 Tk 图形支持这在 Windows 官方安装包中默认自带但在部分 Linux 精简环境中可能需要额外安装python3-tk。3. 海龟绘图的基本逻辑3.1 海龟模型是什么海龟绘图可以这样理解画布上有一支“画笔”这支画笔带着一个小海龟图标。你可以命令小海龟前进、后退、左转、右转它移动的轨迹就形成了图形。常见指令如下import turtle t turtle.Turtle() t.forward(100) # 前进 100 像素 t.left(90) # 左转 90 度 t.right(30) # 右转 30 度 t.backward(50) # 后退 50 像素小海龟的初始方向是水平向右也就是屏幕右边。结合这一点就能理解后面角度计算的方向问题。3.2 画三角形的最小代码用海龟画一个等边三角形非常简单import turtle t turtle.Turtle() for _ in range(3): t.forward(100) t.left(120) turtle.done()为什么循环里是left(120)因为等边三角形的每个内角都是 60 度但海龟转向时转的是外角也就是前进方向与下一段前进方向之间的夹角。三角形外角与内角互补外角 180 - 内角所以等边三角形的转向角度是180 - 60 120。这个关系是解决第 12 题的关键。很多人画钝角三角形出错大概率是直接在代码里写了钝角的度数而没有先换算成外角。4. 钝角三角形的内角与外角关系4.1 什么是钝角三角形三角形中有一个角大于 90 度且小于 180 度就称为钝角三角形。例如下面几个度数都可以构成钝角三角形角 A 120 度角 B 30 度角 C 30 度 角 A 100 度角 B 40 度角 C 40 度 角 A 110 度角 B 40 度角 C 30 度三角形的内角和恒等于 180 度所以只要一个角大于 90 度另外两个角的和就会小于 90 度。4.2 为什么绘制时要转外角假设有一个三角形 ABC角 A 120 度 角 B 30 度 角 C 30 度现在小海龟从 A 点出发先沿 AB 方向前进到达 B 点后它需要转向 BC 方向。注意小海龟当前朝向是“从 A 指向 B”也就是沿着 AB 线段的方向。如果想让海龟沿着 BC 方向走它转过的角度其实是从 AB 方向转向 BC 方向的那一个夹角也就是 B 点处的外角而不是三角形内部的角度。B 点内角是 30 度所以转向角度是180 - 30 150 度同理到达 C 点后C 点内角也是 30 度转向150度。最后从 C 点回到 A 点A 点内角是 120 度转向角度是180 - 120 60 度把三个转向角度加在一起150 150 60 360 度这符合“海龟绕封闭图形一周总旋转角度为 360 度”的规律也是一个非常好的自检标准。5. 第 12 题的第一种实现直接绘制明确了内角与外角的关系就可以直接写第一版代码。import turtle # 创建画笔 t turtle.Turtle() t.speed(3) t.pensize(2) # 绘制钝角三角形 # 三个内角A 120 度, B 30 度, C 30 度 side_ab 200 side_bc 200 # 从 A 点出发水平向右画 AB t.forward(side_ab) # 到达 B 点转向角度 180 - 30 150 t.left(150) # 画 BC t.forward(side_bc) # 到达 C 点转向角度 180 - 30 150 t.left(150) # 画 CA t.forward(200) turtle.done()5.1 代码逐行解析创建一个海龟对象t并设置速度与画笔粗细。t.forward(side_ab)小海龟从 A 点向右画一条长为 200 像素的线段 AB。因为默认方向是朝右所以 AB 是水平线。到达 B 点后执行t.left(150)小海龟原本朝向右边现在向左旋转 150 度。有同学会好奇如果我在 B 点画一条辅助线把 AB 延长过去小海龟转的角度正好是 AB 延长线与 BC 的夹角这确实就是 B 点的外角。外角等于内角补角所以是180 - 30 150。注意这里用的是left。因为我们希望路径走向左上方。如果你用right(150)图形会往右下方偏画出来的是镜像对称但同样钝角的三角形这不会报错只是位置看起来不同。接着t.forward(side_bc) t.left(150)在 C 点再次左转 150 度方向转向 A 点。最后t.forward(200)回到 A 点图形闭合。5.2 运行结果运行上面的代码你会看到一个类似下图效果的三角形轮廓A / \ / \ / \ / \ B---------CA点在上方B点在左侧C点在右侧角 A是顶部的钝角角 B和角 C是底部的两个锐角。这种写法的缺点是边长、角度都写死了如果题目要求你修改角度就要改好几处而且容易改乱。6. 第二种实现使用函数封装实际练习时我更推荐你把绘制过程封装成函数这样后续会遇到类似的“画任意三角形”题目时直接复用。先定义一个有实际意义的通用函数import turtle def draw_obtuse_triangle(t, angle_a, angle_b, side_ab): 根据两个角和一条边绘制一个钝角三角形 :param t: turtle 对象 :param angle_a: 第一个角 A 的度数 :param angle_b: 第二个角 B 的度数 :param side_ab: AB 边的长度像素 # 由三角形内角和为 180 度求出第三个角 C angle_c 180 - angle_a - angle_b # 海龟画 AB 边 t.forward(side_ab) # 在 B 点转向转向的是外角所以是 180 - angle_b t.left(180 - angle_b) # 根据正弦定理计算第二条边的长度 import math # 这里的比例是 BC / sin(angle_a) AB / sin(angle_c) side_bc side_ab * math.sin(math.radians(angle_a)) / math.sin(math.radians(angle_c)) t.forward(side_bc) # 在 C 点转向转向角度是 180 - angle_c t.left(180 - angle_c) # 最后画 CA 边长度不一定要计算清楚回到起点即可 t.forward(side_ab) # 使用示例 t turtle.Turtle() t.speed(3) t.pensize(2) # 钝角三角形角A 120角B 30角C 30 draw_obtuse_triangle(t, angle_a120, angle_b30, side_ab200) turtle.done()6.1 为什么用正弦定理计算边长如果三角形三个角分别是 A、B、C分别对应的边是 a、b、c那么正弦定理告诉我们a / sin(A) b / sin(B) c / sin(C)在这段代码中已知 AB 边的长度为side_ab。AB 边对着角 CBC 边对着角 A因此AB / sin(C) BC / sin(A)所以BC AB * sin(A) / sin(C)代码中用math.radians()把角度转为弧度因为 Python 的math.sin()默认接收弧度值。上面的实现比较接近真实编程场景写函数时考虑通用性而不是只为一次运行服务。当然回到第 12 题本身题目一般没有要求计算第三边。实际上按照“从 A 出发画完两条边后最后回到 A”的思路第三边并不需要知道精确长度因为最后一段forward会把小海龟带回原 A 点。上面代码最后一行的t.forward(side_ab)其实只有在 C 点转向正确的前提下才刚好回到 A 点。7. 第三种实现用循环结构绘制为了养成好习惯可以把重复三次的动作用循环表达出来import turtle # 定义三角形的三个内角 angles [120, 30, 30] # 定义三条边的长度这里选用两边相等的等腰钝角三角形 sides [200, 200, 200] t turtle.Turtle() t.speed(3) t.pensize(2) for i in range(3): t.forward(sides[i]) t.left(180 - angles[i]) turtle.done()这种写法更接近“算法题”的思路把三角形的三个顶点信息分别用列表存储再通过一次循环完成绘制。但这里有一个小坑边长列表与角度列表的对应关系。在顶点 A 处画边 AB 后顶点 A 处转向的角度是180 - 角A然后画边 BC在顶点 B 处转向180 - 角B最后画边 CA在顶点 C 处转向180 - 角C。所以循环里角度顺序是 A、B、C对应的是在哪个顶点发生转向。如果你给出的角度和边长不能构成一个真正的闭合三角形这个简单的循环画出来的图形可能不会回到起点。因此如果要通用循环可以使用上面“正弦定理算边长”的方式。8. 运行效果与程序结构对比为了让运行效果更直观可以把三种实现的效果合并来看实现方式代码量可读性扩展性推荐程度直接顺序代码短一般差入门理解函数封装中等好好练习必备循环列表短较好中算法练习在实际的“海龟绘图 100 题”学习中我建议你至少掌握函数封装这种写法因为后续很多题目菱形、多边形、复合图形都要求把画出某个几何形状封装成可复用函数。9. 常见问题与排查思路9.1 画出来的不是三角形而是不闭合折线现象图形看起来像是在走折线最后没有回到起点。可能原因某个转向角度错误导致后续路径偏离。排查步骤检查三个内角之和是否为 180 度确认每个转向角度都用180 - 内角计算把代码中的长度改短到 100配合print输出当前海龟坐标方便观察。解决方案print(t.position())你可以在每条边绘制后打印海龟坐标观察最后是否回到起点。9.2 图形方向反了现象画出的三角形是向下的或者向内凹陷。可能原因某次转向用了right而应该用left或者反了过来。解决方法想一想你的海龟当前朝向是哪个方向。想让它往左上方走就left想让它在某些对称场景中往右下走就right。两者都能画出钝角三角形只是镜像方向不同。9.3 窗口一闪而过现象运行程序后图形窗口立即关闭。原因程序执行完所有绘图语句后直接退出。解决方案在代码末尾加turtle.done()如果使用 PyCharm有时还需要在运行配置中勾选“Emulate terminal in output console”。9.4 想要固定画布尺寸在绘制一些复杂图形时画布默认大小是 800×600 像素。如果图形较大或者希望画面居中可以使用turtle.setup(800, 600) turtle.screensize(800, 600)也可以使用turtle.setworldcoordinates(-400, -300, 400, 300)调整坐标系。不过对于第 12 题这种简单图形默认画布通常够用。下表整理了高频报错场景问题现象常见原因解决思路图形未闭合转向角度错或边长不合理核对内角/外角打印坐标图形方向相反left和right用混明确当前朝向再选择方向窗口闪退缺少turtle.done()在末尾添加turtle.done()画笔线太粗/太细pensize设置不当调整t.pensize()程序卡住不动可能是死循环或窗口阻塞检查循环次数按 Esc 可退出10. 从一题到一类海龟绘图中角度计算的通用思维第 12 题虽然只是画一个钝角三角形但它背后的思维可以扩展到很多图形10.1 正多边形画正 n 边形时每个外角是 360 / n例如import turtle def draw_polygon(t, n, side): for _ in range(n): t.forward(side) t.left(360 / n) t turtle.Turtle() draw_polygon(t, 6, 100) # 正六边形 turtle.done()10.2 任意三角形如果已知三个内角 A、B、C 和一条边 a可以用正弦定理计算另外两条边再配合转向角度绘制。import turtle import math def draw_triangle(t, angle_a, angle_b, angle_c, side_a): 绘制一个已知三内角和一条边的三角形 # 对应关系a 边对着角 Ab 边对着角 Bc 边对着角 C angle_a_rad math.radians(angle_a) angle_b_rad math.radians(angle_b) angle_c_rad math.radians(angle_c) side_b side_a * math.sin(angle_b_rad) / math.sin(angle_a_rad) side_c side_a * math.sin(angle_c_rad) / math.sin(angle_a_rad) # 画 a 边 t.forward(side_a) # 在 B 点转向 t.left(180 - angle_b) # 画 b 边 t.forward(side_b) # 在 C 点转向 t.left(180 - angle_c) # 画 c 边 t.forward(side_c)这样的函数对绘制任意三角形都适用。10.3 复合图形海龟绘图中经常出现“多个三角形拼在一起”的题目。比如一个菱形可以由两个等边三角形组成一个五角星可以由五个钝角等腰三角形组成。明白了“在哪个顶点转多少度”之后拆解复合图形就不再困难。11. 让钝角三角形变得更好看11.1 填充颜色题目如果要求填充颜色可以用begin_fill()和end_fill()import turtle t turtle.Turtle() t.speed(3) # 设置填充颜色 t.fillcolor(sky blue) t.begin_fill() angles [120, 30, 30] sides [200, 200, 200] for i in range(3): t.forward(sides[i]) t.left(180 - angles[i]) t.end_fill() turtle.done()这样绘制出的钝角三角形内部会填充上淡蓝色视觉效果好很多。11.2 标注顶点文字使用t.write()可以在画布上写文字。例如在顶点 A、B、C 处标注字母import turtle t turtle.Turtle() t.speed(3) # 画 AB 边 t.forward(200) t.write(B, font(Arial, 16, normal)) # 转向并画 BC t.left(150) t.forward(200) t.write(C, font(Arial, 16, normal)) # 转向并画 CA t.left(150) t.forward(200) t.write(A, font(Arial, 16, normal)) turtle.done()这样图形更直观适合课堂演示。11.3 让图形定位到画布中心默认海龟从画布中央开始所以直接画即可。如果图形需要偏移到某个位置使用penup()和goto()t.penup() t.goto(-100, -100) t.pendown()这个组合在画多个图形的题目中非常常用。12. 代码风格与工程建议12.1 命名要清晰海龟绘图的代码虽然短但仍然要有命名的好习惯# 不推荐 t.forward(200) t.left(150) t.forward(200) # 推荐 side_length 200 turtle_turn_angle 150 t.forward(side_length) t.left(turtle_turn_angle)12.2 函数单一职责一个函数只做一件事。画三角形的函数就不要同时负责设置画布、填充颜色和写文字。后面这些功能用单独的函数处理代码结构更清晰。12.3 使用常量代替魔法数字代码中直接出现的数值常被称为“魔法数字”阅读时很难快速理解含义。可以把这三个直角数值抽成变量ANGLE_A 120 ANGLE_B 30 ANGLE_C 30 turn_at_a 180 - ANGLE_A turn_at_b 180 - ANGLE_B turn_at_c 180 - ANGLE_C12.4 保留推导注释海龟绘图题目很容易忘记角度计算公式建议在关键位置添加注释方便日后回顾# 在某个顶点转向时需要转 180 - 该点内角这种注释不是废话而是记录了数学推导过程对后续做复杂的正多边形、星星、分形图形很有帮助。13. 课后思考与练习第 12 题画钝角三角形可做的扩展方向很多。建议你完成后继续挑战画一个钝角为 100 度的钝角三角形要求另两个角不相等例如角 B 50 度角 C 30 度看看应该怎么设置边长和转角画两个大小不同的钝角三角形其中小三角形内嵌在大三角形内部形成“嵌套三角形”效果利用random模块随机生成一个钝角三角形的角度组合然后绘制出来观察图形变化把钝角三角形的画法封装成draw_obtuse_triangle(t, angle_a, side_ab)类函数其中自动补全另外两个角画一个由 5 个钝角三角形拼接而成的图案例如类似“五角星”的形状。每一道练习题都在反复强化同一个结论海龟转向角度 180 度 - 内角。你可以在自己的代码中做一个快速验证把三个顶点转向角度相加如果是 360 度说明三角形的外角方向逻辑正确如果相加结果不是 360 度图形大概率不会闭合。这种验证方式不仅适用于三角形也适用于任意多边形。掌握它以后“用海龟画多边形”这类问题基本就稳了。