• 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()
  • 相关阅读:
    buuctf-web [强网杯 2019]随便注 1
    buuctf-crypto 引用可打印
    buuctf-crypto 变异凯撒
    buuctf-misc 文件中的秘密
    buuctf-misc LSB
    nginx 模块配置
    cloudflare CDN下nginx获取用户真实IP地址
    使用nginx后如何在web应用中获取用户ip及原理解释
    获取用户真实 ip 地址的 nginx 相关配置
    解决nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
  • 原文地址:https://www.cnblogs.com/luoxun/p/13336041.html
Copyright © 2020-2023  润新知