002_Snake_FreePythonGames用海龟画图实现简单的贪吃蛇游戏

一 相关知识

1 randrange()函数

  • 功能:randrange() 方法返回指定递增基数集合中的一个随机数,基数默认值为1。
  • 语法:random.randrange ([start,] stop [,step])
    • 注意:randrange()是不能直接访问的,需要导入 random 模块,然后通过 random 静态对象调用该方法。
      • 方法一:import random
      • 方法二:from random import randrange
  • 参数:
    • start -- 指定范围内的开始值,包含在范围内。
    • stop -- 指定范围内的结束值,不包含在范围内。
    • step -- 指定递增基数。
  • 返回值:从给定的范围返回随机项。

2 turtle.tracer()函数

  • 功能:启用/禁用海龟动画并设置刷新图形的延迟时间。——可看作是为了加快/减慢作图的,你可以在里面添加参数
  • 语法:turtle.tracer(n=None,delay=None)
    • 如果指定 n 值,则只有每第 n 次屏幕刷新会实际执行。(可被用来加速复杂图形的绘制。) 如果调用时不带参数,则返回当前保存的 n 值。第二个参数设置延迟值 
    • n -- 非负整型数;delay -- 非负整型数
      • turtle.tracer(False)或者duturtle.tracer(0):图形将一次性画好
      • turtle.tracer(1):图形按照正常速度进行,可有可无
      • turtle.tracer(4):在循环中,图形将一次画出4次循环的图

3 turtle.update():执行一次 TurtleScreen 刷新。在禁用追踪时使用。

4 turtle.clear():从中删除所有海龟的全部绘图。将已清空的 TurtleScreen 重置为初始状态: 白色背景,无背景片,无事件绑定并启用追踪。

5 turtle.ontimer(fun,t):安装一个计时器,在tms后调用fun函数

 

二 分析过程https://www.jb51.net/article/153788.htm

贪吃蛇的身体是由list构成的,list中每一个元组代表贪吃蛇在棋盘上的坐标,我们只需在这些位置画上图案,就能制作出一条圆滚滚的贪吃蛇来。但是如果想让贪吃蛇活蹦乱跳,我们就要写一个move函数。

1贪吃蛇怎么移动

如果贪吃蛇没吃到食物,那么我们就删除list中最后一个坐标,再在蛇头部分插入新的位置。如何确定新的位置呢,我们就要设定贪吃蛇移动的方向(x,y),将原蛇头位置的坐标在移动方向上进行加减操作。这样贪吃蛇就实现了向前移动的目标。如果贪吃蛇恰好吃到了食物,唯一的不同就是不需要删除贪吃蛇尾部的元素。其中需要注意的是,贪吃蛇不能朝着当前移动方向的反方向移动。体现在代码中,就是当前方向与改变方向的乘积不能为负值。

2 如何知道贪吃蛇吃到了食物呢

如果贪吃蛇蛇头的坐标与食物的坐标重合的话,贪吃蛇就吃到了食物。如果贪吃蛇吃到了食物,就在棋盘上随机更新食物。如果随机生成的食物的坐标,恰好与贪吃蛇的位置重合的话,就继续随机产生坐标,直到确保与贪吃蛇的坐标不同的时候。

3 如何知道游戏失败了呢

如果贪吃蛇蛇头的坐标与边框的坐标重合的话,蛇卒。如果贪吃蛇各个部分的坐标有重合的话,就说明贪吃蛇咬到了自己,游戏结束。

三  代码

代码功能都是齐全的,然后按键控制onkey函数中的参数是'Right',我一直以为是通过输入这个字符串控制贪吃蛇移动的,结果它的意思是按键盘上的向上的方向键,并不是输入字符串,所以我一直没办法通过键盘控制贪吃蛇的移动方向,导致我还以为是代码有问题。。。。

然后跟原来的代码相比,我加了一部分改变食物位置的changeFood函数,原理跟改变贪吃蛇移动方向的changeSnake函数一致。

该贪吃蛇程序是利用turtle库完成的,网上很多贪吃蛇代码都是利用pygame库实现的,那些资料里面可能游戏开始结束设置的比较全面一点,但是用turtle库感觉简单了好多有木有!!!

 1 """Snake,classic arcade game
 2 Exercise
 3 1. How do you make the snake faster or slower?    通过改变ontimer(move,500)语句中的第二个参数
 4 2. How can you make the snake go around the edges?可将初始坐标定为(180,0)、(-180,0)、(0,180)、(0,-180)、(180,180)、(-180,180)、(180,-180)、(-180,-180)
 5 3  How would you move the food?                   通过onkey函数调用changeFood函数改变食物坐标
 6 4. Change the snake to respond to arrow keys.     已经实现了吧,Right、Left、Up、Down分别对应向右、向左、向上、向下箭头
 7 """
 8 
 9 from turtle import *                         # 导入turtle库,此种方式导入可直接使用库内函数,不使用trutle.做前导
10 from random import randrange                 # 从random库中导入randrange()函数,使food随机出现
11 from freegames import square,vector          # 从freegames库中导入square和vector,用square正方形表示food、snake,用vector这个二维向量表示snake
12 
13 food = vector(0,0)                           # 初始化food变量,用来表示第一个食物在坐标为(0,0)处
14 snake = [vector(180,0)]                      # 初始化snake,而且snake是列表,其元素是向量
15 aim = vector(0,-10)                          # 用来控制贪吃蛇的移动方向和距离
16 aim2 = vector(10,10)                         # 用来控制食物移动的方向和距离
17 
18 
19 def changeSnake(x,y):                        # 改变贪吃蛇移动方向部分,通过onkey函数和lambda表达式调用changeSnake函数,获得下一个移动坐标(x,y)
20     "Change snake direction."
21     aim.x = x                                # 将x的值赋给aim.x改变贪吃蛇目标的横坐标
22     aim.y = y                                # 将y的值赋给aim.x改变贪吃蛇目标的纵坐标
23 
24 def changeFood(x,y):                         # 改变食物移动方向部分,通过onkey函数和lambda表达式调用changeFood函数,获得下一个移动坐标(x/2,y/2)
25     "Change food direction."
26     aim2.x = x/2                             # 将x/2的值赋给aim2.x改变食物目标的横坐标
27     aim2.y = y/2                             # 将y/2的值赋给aim2.y改变食物目标的纵坐标
28 
29 def inside(head):                            # 判断贪吃蛇有没有碰到画布边界部分,限制贪吃蛇的移动范围
30     "Return True if head inside the boundaries."
31     return -200 < head.x < 190 and -200 < head.y < 190
32 
33 def move():
34     "Move snake forward one segment."
35     # 更改食物和贪吃蛇蛇头坐标
36     head = snake[-1].copy()                   # 表示复制snake列表的最后一个元素,这里用列表的最后一个元素表示蛇头
37     head.move(aim)                            # 每调用一次move函数,贪吃蛇就移动到(head.x+aim.x,head.y+aim.y)的位置
38     food.move(aim2)                           # 每调用一次move函数,食物就移动到(food.x+aim2.x,food.y+aim2.y)的位置
39     
40     #判断游戏是否结束
41     if not inside(head) or head in snake:     # 判断是否结束游戏部分:head碰到墙壁|头碰到身体
42         square(head.x,head.y,9,'red')         # 将贪吃蛇蛇头的正方形改成红色,表示游戏结束
43         update()                              # 执行一次屏幕刷新
44         return                                # 用来终止程序的运行,其后语句不会再执行
45     
46     # 更新贪吃蛇的身体
47     snake.append(head)                        # 蛇头坐标已经更改,将新的蛇头目标添加到snake列表中
48 
49     if head == food:                          # snake吃到food,下一个food会随机出现在画布的另一个地方
50         print('Snake',len(snake))             # 打印贪吃蛇的长度
51         food.x = randrange(-15,15) * 10       # 随机产生食物横坐标
52         food.y = randrange(-15,15) * 10       # 随机产生食物纵坐标
53     else:                                     # snake没有吃到food
54         snake.pop(0)                          # snake没有吃到食物,所以将snake列表最后一个元素删除,保持贪吃蛇长度不变,这里用列表的第一个元素表示蛇尾
55     
56     # 清空画布,重新画好食物和贪吃蛇的位置,利用ontimer函数调用move函数,控制贪吃蛇进行下一次移动
57     clear()                                   # 相当于刷新操作,将所有的绘图全部删了
58 
59     for body in snake:                        # 重新画出贪吃蛇的身体部分
60         square(body.x,body.y,9,'black')       # 黑色方块表示贪吃蛇的身体
61     square(food.x,food.y,9,'green')           # 画出食物,绿色方块表示食物
62     update()                                  # 执行一次屏幕刷新
63     ontimer(move,500)                         # 经过500ms后继续调用move函数
64 
65 setup(420,420,370,0)                          # 初始画布尺寸
66 hideturtle()                                  # 隐藏鼠标
67 tracer(False)                                 # 保证画图操作(食物和贪吃蛇身体)一次性完成
68 move()
69 listen()                                      # 监听,屏幕聚焦
70 # 绑定键盘方向,改变贪吃蛇的移动方向
71 onkey(lambda:changeSnake(10,0),'Right')       # 右转,Right是键盘方向键的右键,不是输入单词Right
72 onkey(lambda:changeSnake(-10,0),'Left')       # 左转
73 onkey(lambda:changeSnake(0,10),'Up')          # 向上走
74 onkey(lambda:changeSnake(0,-10),'Down')       # 向下走
75 # 绑定键盘方向,改变食物的移动方向
76 onkey(lambda:changeFood(10,0),'D')            # 右转,在键盘上输入大写字母'D'
77 onkey(lambda:changeFood(-10,0),'A')           # 左转
78 onkey(lambda:changeFood(0,10),'W')            # 向上走
79 onkey(lambda:changeFood(0,-10),'S')           # 向下走
80 
81 done()

 

posted @ 2020-07-18 15:55  洛兰123  阅读(1102)  评论(0编辑  收藏  举报