当前位置:   article > 正文

【神奇的Turtle库】海龟在手—天下我有:这款秘制“海龟闯关”小游戏值得拥有,强烈推荐哦~_好玩的turtle

好玩的turtle

导语

哈喽!大家好!我是木木子~

纵观之前的文章——我发现了一个特点,很多小伙伴儿都喜欢学习Turtle或游戏代码,没错吧~

那今天这篇文章就是为这2方面的小伙伴儿精心准备滴!Turtle+游戏一起安排一波啦!

从Turtle开始介绍—基础知识到实践案例这篇文章都写到了嘞!不要以为是单单一个项目哦,想学

Turtle的必学篇,不要错过啦~

之前小编也写过很多Turtle的代码正在学的小伙伴儿等下文末有汇总文章,可以挑自己喜欢的文章

观看哈!

最后今天小编会带大家写一个利用Turtle的一款海龟闯关的三大迷宫哦!这工程量还是挺大的!都

是绘制下来的话代码量比较多了撒,400行代码才完成这款“海龟闯关走迷宫的”小游戏!

正文

一、简介

1) 什么是Turtle?

Turtle英译过来为乌龟,不过我们介绍的不是这种动物,而是以此命名的一个绘图软件。

在python文档中介绍了Turtle本身是一款简单、易上手的绘图软件,非常适合新手进入编程的世界。

海龟绘图Turtle是Python内置模块,总之是非常简单好玩的一个库。

其动作主要有:抬笔,此后的动作只是移动画笔,画布上不会留下痕迹;落笔,只要移动画笔,画

布上就会留下痕迹。

画笔动作只绝对移动、相对移动、向前(后)移动、转向(绝对角度、相对角度)、圆或圆弧、点(实心

圆),故画不了椭圆,绘制函数曲线困难!

2)怎么玩转Turtle?

当然在这里需要进入python编程环境,然后在这个python文件中就可以开始动手写有关turtle的代码。

Turtle是python安装时自带的内置模块,调用该模块非常简单,直接使用import方式加载:

import turtle 或 from turtle import *

这也是程序的第一行代码,用于准备好使用turtle这个模块。

3)画布的设置

1.1设置画布大小

turtle.screensize()       # 返回默认大小(400, 300)

1.2以默认绘图窗口大小显示窗口,窗口居屏幕中心。

turtle.screensize(width, hight[, bg])

其中:width——表示画布宽度(单位像素);Hight——表示画布高度(单位像素);bg——画布背景颜

色,该参数可缺省,缺省时为白色背景

1.3案例

如:

turtle.screensize(800, 600, "green"),表示画布大小为800×600,绿色画布。
turtle.setup(width, hight[, x, y])

其中:width, height——表示画布宽和高。当为整数时表示像素;为小数时则表示占据计算机屏幕

的比例

4)设置背景/画布颜色

turtle.bgcolor()

二、Turtle的画笔设置

turtle.pensize(size)

其中:size——画笔粗细,用像素表示。

1)turtle绘图的基本方法

导入turtle库绘图模块后,就可以实现绘图,基本操作是向前(后)画直线,旋转(向左向右改变方

向),画圆(圆弧)等。

这里介绍几个最常用的命令。

1.1设置画笔的属性

  1. 命令 说明
  2. turtle.pensize(width) 用于设置画笔的宽度(即粗细),width越大越粗
  3. turtle.pencolor(color) 用于设置画笔的颜色,color参数可以是字符串如"green","red",也可以是
  4. RGB三元组。
  5. turtle.shape(shape) 用于设置画笔的形状,shape参数为字符串,主要包含
  6. “turtle”乌龟形状,“square”正方形形状等
  7. turtle.speed(speed) 用于设置画笔的移动速度。speed参数可以是字符串如“fast”,"slow"等,
  8. 也可以是010间的整数

1.2画笔绘图的命令

  1. 命令 说明
  2. turtle.fd(dis) 沿当前画笔方向向前移动dist像素长度
  3. turtle.bk(dist) 沿当前画笔相反方向移动dist像素长度
  4. turtle.right(degree) 沿当前画笔方向向右转degree°
  5. turtle.left(degree) 沿当前画笔方向向左转degree°
  6. turtle.down() 将画笔放下,开始画图
  7. turtle.up() 提起笔移动,不绘制图形
  8. turtle.circle() 画圆,半径为正(负),表示圆心在画笔的左边(右边)画圆
  9. setx( ) 将当前x轴移动到指定位置
  10. sety( ) 将当前y轴移动到指定位置
  11. setheading(degree) 用于设置画笔的方向,参数degree为画笔方向与海龟坐标系x轴正向的
  12. 夹角度数
  13. ht() 用于将画笔隐藏

三、最后的案例Turtle小游戏

1)设计思路游戏规则

这个海龟闯关的小迷宫游戏是设计了三个关卡,运行代码之后会有相应的关卡弹窗设置,想完那关

可以直接玩那关, 也可以按照顺序闯关。

特别注意:

很多人担心过不了关?没关系,小编给大家开了一个挂,这个挂就是按住F1就出现了迷宫的

路线图哦!按住F2就是出现了一个海龟到起点自己走路线哈!

2)准备环节

小编用的Python3、Pycharm2021、Turtle模块导入即可。

然后相应的图片素材:

3)正式敲代码

  1. # -*- coding: UTF-8 -*-
  2. """
  3. 源码基地:#806965976#
  4. csdn账号:顾木子吖
  5. 海龟迷宫闯关游戏
  6. """
  7. import turtle # 导入海龟绘图模块
  8. import random # 导入随机数模块
  9. game_title = '小海龟大迷宫闯关小游戏' # 游戏名字
  10. level = 0 # 关卡
  11. '''绘制地图用的全局变量'''
  12. txt_path = 'map/map1.txt' # 地图信息文本文件路径及名称
  13. road_color = (191, 217, 225) # 迷宫通道的颜色
  14. R, C = 0, 0 # 迷宫地图的总行数R、总列数C
  15. cell_size = 20 # 一个格子的尺寸
  16. area_sign = {} # 记录入口和出口索引位置
  17. mazeList = [] # 地图列表
  18. '''海龟对象'''
  19. map_t = turtle.Turtle() # 绘制地图的海龟
  20. map_t.speed(0) # 设置绘图速度最快(地图绘制)
  21. sign_t = turtle.Turtle() # 绘制入口和出口标记的海龟
  22. auto_t = turtle.Turtle() # 自动走迷宫的海龟
  23. auto_t.pensize(5) # 画笔粗细(自动)
  24. auto_t.speed(0) # 设置绘图速度最快(手动)
  25. auto_t.ht() # 隐藏海龟光标
  26. manual_t = turtle.Turtle() # 手动走迷宫的海龟
  27. manual_t.pensize(5) # 画笔粗细(手动)
  28. manual_t.speed(0) # 设置绘图速度最快(手动)
  29. manual_t.shape('turtle') # 设置海龟光标为小海龟(手动)
  30. manual_t.ht() # 隐藏手动走迷宫所用的海龟光标(手动)
  31. # 要探索4个方向对应索引的变化规则
  32. direction = [
  33. (1, 0), # 右
  34. (-1, 0), # 左
  35. (0, 1), # 上
  36. (0, -1) # 下
  37. ]
  38. def imoveto(ci, ri):
  39. """
  40. 功能:根据索引位置移动海龟(不画线)
  41. :param ci: 列索引
  42. :param ri: 行索引
  43. :return:
  44. """
  45. auto_t.penup() # 抬笔
  46. cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置
  47. auto_t.goto(cx, cy) # 移动到指定位置
  48. auto_t.pendown() # 落笔
  49. auto_t.shape('turtle') # 设置海龟光标的形状
  50. auto_t.color('red') # 设置画笔颜色为红色
  51. auto_t.st() # 显示海龟光标
  52. def c_move_to(t, ctuple): # 移动到指定位置
  53. """
  54. 功能:根据坐标位置移动到指定位置(不画线)
  55. :param t: 海龟对象
  56. :param ctuple: 记录坐标位置的元组
  57. :return:
  58. """
  59. t.ht() # 隐藏海龟光标
  60. t.penup() # 抬笔
  61. t.goto(ctuple[0], ctuple[1]) # 移动到坐标指定的位置
  62. t.pendown() # 落笔
  63. def itoc(ituple):
  64. """
  65. 将索引位置转换为实际坐标位置
  66. :param ituple: 行、列索引组成的元组
  67. :return: 实际坐标位置
  68. """
  69. ci = ituple[0]
  70. ri = ituple[1]
  71. tx = ci * cell_size - C * cell_size / 2 # 根据索引值计算每个正方形的起点(x坐标)
  72. ty = R * cell_size / 2 - ri * cell_size # 根据索引值计算每个正方形的起点(y坐标)
  73. cx = tx + cell_size / 2 # 正方形中心的x坐标
  74. cy = ty - cell_size / 2 # 正方形中心的y坐标
  75. return (cx, cy)
  76. def ctoi(cx, cy):
  77. """
  78. 根据cx和cy求在列表中对应的索引
  79. :param cx: x轴坐标
  80. :param cy: y轴坐标
  81. :return: 元组,(ci,ri)
  82. """
  83. ci = ((C - 1) * cell_size / 2 + cx) / cell_size # 计算列索引
  84. ri = ((R - 1) * cell_size / 2 - cy) / cell_size # 计算行索引
  85. return (int(ri), int(ci)) # 返回行列索引的元组
  86. def get_map(filename):
  87. """
  88. 功能:读取保存地图的文本文件内容到列表
  89. :param filename: 地图文件名
  90. :return: 地图列表
  91. """
  92. with open(filename, 'r') as f: # 打开文件
  93. fl = f.readlines() # 读取全部行
  94. maze_list = [] # 保存地图的列表
  95. for line in fl: # 将读取的内容以空格分割为二维列表
  96. line = line.strip() # 去掉空格
  97. line_list = line.split(" ") # 以空格进行分割为列表
  98. maze_list.append(line_list) # 将分割后的列表添加到地图列表中
  99. return maze_list # 返回地图列表
  100. def draw_square(ci, ri, colorsign):
  101. """
  102. 功能:绘制组成地图的小正方形
  103. :param ci: 列索引
  104. :param ri: 行索引
  105. :param colorsign: 填充颜色
  106. :return:
  107. """
  108. tx = ci * cell_size - C * cell_size / 2 # 根据索引值计算每个正方形的起点(x坐标)
  109. ty = R * cell_size / 2 - ri * cell_size # 根据索引值计算每个正方形的起点(y坐标)
  110. map_t.penup() # 抬笔
  111. map_t.goto(tx, ty) # 移动到绘图起点(正方形的左上角)
  112. if colorsign == '1': # 判断是否为墙(如果为墙,则随机生成填充颜色)
  113. r = random.randint(100, 130) # 红色值
  114. g = random.randint(150, 180) # 绿色值
  115. map_t.color(r, g, 200) # 指定颜色为随机生成的颜色
  116. else:
  117. map_t.color(colorsign) # 设置为指定的通道颜色
  118. map_t.pendown() # 落笔
  119. map_t.begin_fill() # 填充开始
  120. for i in range(4): # 绘制正方形
  121. map_t.fd(cell_size)
  122. map_t.right(90)
  123. map_t.end_fill() # 填充结束
  124. map_t.ht() # 隐藏海龟光标
  125. def draw_map(mazelist):
  126. """
  127. 功能:遍历地图列表绘制迷宫地图
  128. :param mazelist: 保存地图数据的列表
  129. :return:
  130. """
  131. turtle.tracer(0) # 隐藏动画效果
  132. global area_sign # 全局变量,记录入口和出口索引位置
  133. for ri in range(R): # 遍历行
  134. for ci in range(C): # 遍历列
  135. item = mazelist[ri][ci]
  136. if item in ['1']: # 判断墙
  137. draw_square(ci, ri, '1') # 绘制墙
  138. elif item == "S": # 判断入口
  139. draw_square(ci, ri, road_color) # 绘制通道
  140. draw_sign(ci - 1, ri, '入口') # 标记入口
  141. area_sign['entry_i'] = (ci, ri) # 保存入口索引
  142. elif item == "E": # 判断出口
  143. draw_square(ci, ri, road_color) # 绘制通道
  144. draw_sign(ci - 1, ri, '出口') # 标记出口
  145. area_sign['exit_i'] = (ci, ri) # 保存出口索引
  146. else:
  147. draw_square(ci, ri, road_color) # 绘制通道
  148. turtle.tracer(1) # 显示动画效果
  149. def draw_sign(ci, ri, word):
  150. """
  151. 功能:绘制入口和出口标记
  152. :param ci: 列索引
  153. :param ri: 行索引
  154. :param word: 标记文字内容
  155. :return:
  156. """
  157. cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置
  158. sign_t.ht() # 隐藏海龟光标
  159. sign_t.penup() # 抬笔
  160. sign_t.goto(cx, cy) # 移动到标记位置
  161. sign_t.color('red') # 设置画笔为红色
  162. sign_t.write(word, font=('黑体', 12, 'normal')) # 绘制标记文字
  163. def win_tip():
  164. """
  165. 功能:制作过关提示
  166. :return:
  167. """
  168. global level
  169. c_move_to(manual_t, (-150, 0))
  170. manual_t.color('blue')
  171. if int(level) == 3:
  172. manual_t.write('\n恭喜您顺利通关!', font=('黑体', 20, 'bold'))
  173. turtle.onkey(turtle.bye, key='Return') # 监听按下Enter键退出游戏
  174. else:
  175. manual_t.write('\n恭喜过关!\n按下Enter进入下一关!', font=('黑体', 20, 'bold'))
  176. level += 1
  177. manual_t.color('red')
  178. turtle.onkey(level_init, key='Return') # 监听按下Enter键
  179. def manual_move(d):
  180. """
  181. 功能:手动走迷宫时通用探索并移动函数
  182. :param d: 向不同方面走时索引的变化规则
  183. :return:
  184. """
  185. dc, dr = d # 将表示方向的元组分别赋值给两个变量dc和dr,其中dc为x轴方向,dr为y轴方向
  186. rici = ctoi(round(manual_t.xcor(), 1) + dc * cell_size, round(manual_t.ycor(), 1) + dr * cell_size) # 获取行列索引
  187. point = mazeList[rici[0]][rici[1]] # 获取地图列表中对应点的值
  188. print('移动:', rici, point)
  189. if point == '0': # 通路
  190. manual_t.color('red')
  191. mazeList[rici[0]][rici[1]] = '$' # 将当前位置标记为已探索
  192. manual_t.forward(cell_size) # 向前移动
  193. print('00')
  194. elif point == '$': # 已探索
  195. manual_t.color(road_color) # 绘制和通道相同颜色的线,达到擦除痕迹的效果
  196. mazeList[rici[0] + dr][rici[1] - dc] = '0' # 将当前位置的前一个点设置为未探索(目的是取消标记)
  197. manual_t.forward(road_color) # 向前移动
  198. manual_t.color('red')
  199. elif point == 'E': # 出口
  200. win_tip()
  201. def up_move(): # 朝上
  202. manual_t.setheading(90) # 设置海龟朝向
  203. manual_move(direction[2]) # 手动探索并移动
  204. def down_move(): # 朝下
  205. manual_t.setheading(270) # 设置海龟朝向
  206. manual_move(direction[3]) # 手动探索并移动
  207. def left_move(): # 朝左
  208. manual_t.setheading(180) # 设置海龟朝向
  209. manual_move(direction[1]) # 手动探索并移动
  210. def right_move(): # 朝右
  211. manual_t.setheading(0) # 设置海龟朝向
  212. manual_move(direction[0]) # 手动探索并移动
  213. def manual_path():
  214. """
  215. 功能:手动走迷宫
  216. :return:
  217. """
  218. manual_t.clear() # 清除绘图
  219. auto_t.ht() # 隐藏海龟
  220. auto_t.clear() # 清除绘图
  221. global mazeList # 定义全局变量
  222. mazeList = get_map(txt_path) # 重新读取地图数据
  223. # print(area_sign['entry_i'][0],area_sign['entry_i'][1])
  224. c_move_to(manual_t, itoc(area_sign['entry_i'])) # 移动到入口位置
  225. manual_t.st() # 显示手动走迷宫所用的海龟光标
  226. manual_t.width(3) # 设置画笔粗细为3像素
  227. manual_t.color('red') # 设置画笔为红色
  228. manual_t.getscreen().listen() # 让海龟屏幕(TurtleScreen)获得焦点
  229. manual_t.getscreen().onkeyrelease(up_move, 'Up') # 按下向上方向键
  230. manual_t.getscreen().onkeyrelease(down_move, 'Down') # 按下向下方向键
  231. manual_t.getscreen().onkeyrelease(left_move, 'Left') # 按下向左方向键
  232. manual_t.getscreen().onkeyrelease(right_move, 'Right') # 按下向右方向键
  233. def auto_path():
  234. """
  235. 功能:查看答案(自动走迷宫)
  236. :return:
  237. """
  238. global mazeList # 定义全局变量
  239. mazeList = get_map(txt_path) # 重新读取地图数据
  240. manual_t.ht() # 隐藏海龟
  241. manual_t.clear() # 清除绘图
  242. auto_t.clear() # 清除绘图
  243. auto_t.pensize(5) # 设置画笔粗细
  244. auto_t.speed(0) # 绘图速度
  245. auto_t.ht() # 隐藏海龟光标
  246. find(mazeList) # 开始探索
  247. def find(mazeList):
  248. """
  249. 功能:开始探索
  250. :param mazeList: 地图列表
  251. :return:
  252. """
  253. auto_t.clear() # 清空帮助
  254. start_r, start_c = 0, 0
  255. for ri in range(R):
  256. for ci in range(C):
  257. item = mazeList[ri][ci]
  258. if item == "S":
  259. start_r, start_c = ri, ci
  260. auto_t.penup() # 抬笔
  261. draw_path(start_c, start_r)
  262. find_next(mazeList, start_c, start_r)
  263. def find_next(mlist, ci, ri):
  264. """
  265. 功能:递归搜索判断是否为通路
  266. :param mlist: 地图列表
  267. :param ci: 列索引
  268. :param ri: 行索引
  269. :return: 布尔值,表示是否为通路
  270. """
  271. if mlist[ri][ci] == "E":
  272. imoveto(ci, ri) # 移动到出口
  273. return True
  274. if not (0 <= ci < C and 0 <= ri < R): # 判断位置是否不合法
  275. return False
  276. if mlist[ri][ci] in ['1', '$']: # 判断是否为墙或者已探索过的
  277. return False
  278. mlist[ri][ci] = "$" # 标记已探索过
  279. for d in direction: # 尝试从不同方向探索是否为通路,如果发现一条通路,则不再继续探索
  280. dc, dr = d # # 将索引变化规则的值分别赋值给dc和dr,其中dc为x轴方向,dr为y轴方向
  281. found = find_next(mlist, ci + dc, ri + dr) # 递归调用
  282. if found: # 如果是通路则绘制线路
  283. draw_path(ci, ri) # 绘制线路
  284. return True # 返回True,不再探索
  285. return False # 当所有方向都不通时,返回False
  286. def draw_path(ci, ri, color="green"): # 自动绘制用
  287. """
  288. 功能:根据索引位置移动海龟(画线)
  289. :param ci: 列索引
  290. :param ri: 行索引
  291. :param color: 画笔颜色
  292. :return:
  293. """
  294. auto_t.st() # 显示海龟光标
  295. cx, cy = itoc((ci, ri)) # 将索引位置转换为坐标位置
  296. auto_t.color(color)
  297. auto_t.goto(cx, cy)
  298. def level_init():
  299. """
  300. 功能:关卡初始化
  301. 游戏规则:
  302. 按下F2键开始手动走迷宫;按下F1键查看答案
  303. 按下↑↓←→方向键控制小海龟移动,闯关成功后,按Enter进入下一关
  304. :return:
  305. """
  306. manual_t.clear() # 清除绘图
  307. auto_t.clear() # 清除绘图
  308. turtle.clear() # 清除绘图
  309. global txt_path, level, mazeList, R, C # 定义全局变量
  310. if level == 1: # 第一关的地图文件和背景
  311. txt_path = "map/map1.txt"
  312. levelbg = 'image/level1.png'
  313. elif level == 2: # 第二关的地图文件和背景
  314. txt_path = "map/map2.txt"
  315. levelbg = 'image/level2.png'
  316. elif level == 3: # 第三关的地图文件和背景
  317. txt_path = "map/map3.txt"
  318. levelbg = 'image/level3.png'
  319. else:
  320. turtle.bye() # 退出程序
  321. return
  322. mazeList = get_map(txt_path) # 获取地图数据
  323. R, C = len(mazeList), len(mazeList[0])
  324. turtle.setup(width=C * cell_size + 50, height=R * cell_size + 100) # 根据地图调整窗口尺寸
  325. turtle.bgpic(levelbg) # 设置背景图片
  326. '''
  327. # 如果想要手动绘制关卡数,可以使用下面的两行代码
  328. cmoveto(turtle, (1 * cellsize - C * cellsize / 2, R * cellsize / 2+10))
  329. turtle.write('关卡:'+str(int(level)), font=('宋体', 16, 'normal'))
  330. '''
  331. turtle.ht() # 隐藏海龟光标
  332. draw_map(mazeList) # 绘制地图

四、效果图

1)运行代码

​2)关卡一

这是按住了F1所以才出现路线图的哦!

​​3)关卡二

这是按住了F2所以是自己手动在闯关哈!

​​4)关卡三

总结

好啦!今天这篇文章就写到这里结束,从简单的基础知识到最后的案例实战,你学废了嘛?

什么?没学废?快,乖乖的放下手机,再来一遍~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/132843

推荐阅读
相关标签