温馨提示
本教程素材已更新至公众号菜单栏【素材】
如果文章对您有一点点帮助,点
、点
,万分感谢
找茬游戏大家都玩过,两张几乎一样的图,找出几处不同。今天用 Python 的 turtle 库把它做出来——上下各一张图,鼠标点哪里,程序自动判断对不对,点对了画黄圈,点错了画红圈。
【点击视频预览程序效果】
整个程序不到50行,但涉及的东西挺有意思:图片加载、坐标记录、鼠标事件、范围判断。
三支画笔各司其职
程序里创建了三个 turtle 对象:
p1 = Turtle() # 显示上方图片p2 = Turtle() # 显示下方图片p3 = Turtle() # 画圆圈标记
分开用的原因很直接:p1 和 p2 只负责显示图片,不画线,所以要 penup();p3 专门画圆圈,不需要显示箭头,所以 hideturtle()。三支画笔互不干扰。
加载图片有个坑
turtle 显示图片不能直接用,要先注册:
list1 = ['003_1 9.gif', '003_2 9.gif']for i in list1: register_shape(i)p1.goto(0, 180)p1.shape(list1[0])p2.goto(0, -180)p2.shape(list1[1])
register_shape 这步不能省,turtle 默认只认识箭头、圆形这几种内置形状,外部图片必须先注册才能用 shape() 显示出来。跳过这步,图片不会报错,但只会显示一个箭头。
图片只支持 gif 格式,png 和 jpg 不行,这是 turtle 的限制。
茬点坐标怎么来的
程序里有一个列表,存着每处差异的坐标:
list_pos = [(-267.0, 54.0), (-173.0, 264.0), (-107.0, 38.0), (34.0, 153.0), ...]
这些坐标不是手量的,是"点出来的"。dr 函数里有一行 print(x, y),运行程序后,先把 list_pos 设为空列表,然后逐一点击图片上每处差异,控制台会打印出坐标,记录下来填进去就行了。
核心:点击判断
点击屏幕后,dr(x, y) 被自动调用,x 和 y 是点击位置的坐标。
y 坐标要换算
这是整段代码里最绕的地方。turtle 把 gif 图片当"造型"显示时,图片内部的坐标和屏幕坐标之间有一个偏移,大约是图片高度的一半(360像素)。点击上图时要减去这个偏移,点击下图时要加上去:
if y > 0: # 点的是上图 y1 = y + r y2 = y + r - 360else: # 点的是下图 y1 = y + r + 360 y2 = y + r
换算完之后,y1 是上图对应的坐标,y2 是下图对应的坐标。无论点哪张图,程序都会在上下两张图的对应位置各画一个圆圈,方便对比。
命中判断
for i in list_pos: if (i[0]-r) <= x <= (i[0]+r) and (i[1]-r) <= (y1-r) <= (i[1]+r): co = 'yellow' break else: co = 'red'
遍历所有茬点,判断点击位置是否在某个茬点的 ±15 像素范围内。命中就变黄色,break 退出循环;遍历完都没命中就是红色。
画圆圈
p3.goto(x, y1)p3.pendown()p3.circle(-r)p3.goto(x, y2)p3.pendown()p3.circle(-r)
在上下两张图的对应位置各画一个圆,circle(-r) 里的负号让圆以 goto 的位置为圆心,正好圈住点击的地方。
最后两行
w1 = Screen()w1.onclick(dr)done()
w1.onclick(dr) 把鼠标点击绑定到 dr 函数,点击时自动把坐标传进去。done() 让窗口保持打开,不加的话程序跑完窗口直接关了。
换关卡只改一行
list1 = ['003_1 9.gif', '003_2 9.gif']
把文件名换成另一对图片,再重新采集一遍坐标填入 list_pos,新关卡就做好了。图片素材只要是 gif 格式、内容相近有差异,都可以用这套框架。详细讲义如下
