【Python贪吃蛇】:编码技巧与游戏设计的完美结合

文章目录

      • 🔥一、运行效果
      • 💥二、游戏教程
        • ✈1. 导入模块
        • ❤️2. 初始化游戏元素
        • ☔3. 改变蛇移动的方向
        • 👊4. 绘制方块
        • 🚀5. 检查蛇头是否在游戏区域内
        • 🌈6. 定义蛇的移动函数
        • 🎬7. 绑定键盘事件
      • ⭐三、完整代码

🔥一、运行效果

Python实现贪吃蛇

💥二、游戏教程

🚲turtle模块
Python的turtle模块是一个非常基础的绘图库,它允许用户创建一个画布并在上面绘制图形。这个模块通常用于教学目的,特别是适合初学者学习编程和理解基本的图形概念。
turtle的一些关键特性

  1. 画布和乌龟:turtle模块提供了一个名为“乌龟”的画笔,可以在一个名为“画布”的窗口上绘制图形。用户可以控制乌龟的移动来画出各种图案。
  2. 前进和后退:可以使用forward()和backward()方法让乌龟在画布上前进或后退。
  3. 转向:left()和right()方法可以让乌龟左转或右转,可以通过度数参数指定转向的角度。
  4. 抬笔和落笔:penup()和pendown()方法分别用于抬起和放下乌龟的笔,抬起笔时乌龟移动不会绘制线条,而放下笔时会绘制线条。
  5. 颜色和填充:可以设置乌龟绘制的颜色,并且可以填充封闭图形的内部。
  6. 速度控制:可以设置乌龟的移动速度,从最快到最慢。
  7. 监听事件:turtle模块可以监听键盘和鼠标事件,这使得它可以用来创建简单的交互式图形应用。
  8. 设置画布:可以设置画布的大小、背景颜色等。
  9. 坐标系统:turtle模块使用笛卡尔坐标系,原点在画布的中心,x轴向右,y轴向上。
  10. 子图和窗口:可以在一个窗口中创建多个乌龟对象,或者在多个窗口中绘图。
  11. 更新和动画:通过update()方法可以刷新画布显示,实现动画效果。
  12. 事件循环:turtle模块提供了事件循环,允许程序保持运行状态直到用户关闭窗口。

turtle模块非常适合用来创建游戏、绘制复杂的几何图形,或者作为教授编程逻辑和控制结构的工具。

✈1. 导入模块
import turtle
import copy
from random import randrange
  • turtle:用于绘制图形和动画。
  • copy:用于复制蛇的头部坐标,避免在移动蛇时直接修改原始列表。
  • randrange:从random模块中导入,用于生成随机数,这里用来随机放置食物。
❤️2. 初始化游戏元素

创建画布和设置标题

wn = turtle.Screen()
wn.title('贪吃蛇游戏')

保持打开绘图窗口

# 不让屏幕立马消失
turtle.done()

turtle.done()是一个非常重要的函数,它用于结束绘图操作并保持打开绘图窗口,直到用户关闭该窗口。这允许用户观察绘制的图形,而不会因为程序的结束而丢失绘图结果。
使用场景
在绘制图形或动画的最后,你会调用turtle.done()来结束你的绘图脚本。例如,在绘制完一个图形或完成一个动画循环后,你可以使用它来防止程序立即退出,从而让用户有足够的时间来查看结果。
在这里插入图片描述
注意事项

  • 如果在调用turtle.done()之前程序崩溃或被强制终止,绘图窗口可能会立即关闭。
  • 在某些IDE(如Jupyter Notebook)中,turtle.done()可能不会按预期工作,因为这些环境可能不支持turtle模块的图形窗口特性。

设置蛇的长度

snake = [[0, 0], [0, 10], [0, 20]]

这里初始化了蛇的三个部分,每个部分由一个列表表示,列表包含两个元素,分别代表蛇的x和y坐标。在这个例子中,蛇有三个部分,初始位置分别是(0, 0)、(0, 10)和(0, 20)。

蛇移动的方向

aim = [0, 10]

aim列表定义了蛇的移动方向,其中第一个元素是水平方向(向右为正,向左为负),第二个元素是垂直方向(向下为正,向上为负)。这里,蛇默认向上移动。

设置食物

food = [-10, 0]

food列表定义了食物的初始位置,同样使用x和y坐标表示。这里食物的初始位置是(-10, 0)。

这些初始化步骤为游戏设置了基本的起点,包括蛇的初始位置和方向、食物的位置以及游戏窗口的标题。

☔3. 改变蛇移动的方向
# 改变蛇移动的方向
def change_direction(x, y):
    aim[0] = x
    aim[1] = y
  • def 是 Python 中用来定义函数的关键字。
  • change_direction 是函数名,这里表示改变方向的功能。
  • x 和 y 是函数的参数,分别代表蛇在水平(x轴)和垂直(y轴)方向上的移动增量。

参数作用

  • aim[0] = x:这行代码将水平方向的移动增量更新为参数 x 的值。如果 x 为正,蛇将向右移动;如果为负,则向左移动;如果为0,则蛇的水平位置不变。
  • aim[1] = y:这行代码将垂直方向的移动增量更新为参数 y 的值。如果 y 为正,蛇将向下移动;如果为负,则向上移动;如果为0,则蛇的垂直位置不变。

注意事项

  • 在实际的游戏实现中,需要确保蛇的移动方向不会违反游戏规则,例如蛇不能瞬间反向移动,这可能需要额外的逻辑来处理。
  • 该函数直接修改了全局变量 aim,这意味着它对所有使用 aim 的代码都是可见的。在更复杂的程序中,可能需要考虑使用类和方法来封装数据和行为。
👊4. 绘制方块
def square(x, y, size, color):
    # 抬起画笔
    turtle.penup()
    # 画笔痕迹
    turtle.goto(x, y)
    # 放下画笔
    turtle.pendown()
    # 进行渲染
    turtle.color(color)
    turtle.begin_fill()
    # 在画布上画四笔转一圈生成一个方块
    for i in range(4):
        turtle.forward(size)
        turtle.left(90)
    turtle.end_fill()

turtle.penup() 这是让画笔抬起,这样当乌龟移动到绘制方块的起始位置时,不会在画布上留下痕迹。turtle.goto(x, y) 这是让乌龟移动到坐标 (x, y) 的位置,即方块左上角的起始位置。
turtle.pendown() 放下画笔,这样接下来的移动就会在画布上绘制线条。
turtle.color(color) 设置接下来绘制的图形的颜色。
turtle.begin_fill() 这行代码指示 turtle 开始填充封闭图形的内部。
turtle.end_fill() 结束填充过程,封闭图形的最后面,完成方块的绘制。

for i in range(4):
    turtle.forward(size)
    turtle.left(90)

循环执行四次,每次绘制方块的一边。turtle.forward(size) 让乌龟前进 size 个单位,turtle.left(90) 让乌龟左转90度,从而改变方向绘制下一条边。
在这里插入图片描述

这个函数可以被用来在 turtle 画布上绘制贪吃蛇游戏中的蛇的身体部分和食物。通过改变 size 和 color 参数,可以创建不同大小和颜色的方块。

🚀5. 检查蛇头是否在游戏区域内
def inside(head):
    return -250 < head[0] < 250 and -250 < head[1] < 250

函数体内的 return 语句包含了一个布尔表达式,用于检查 head 中的 x 和 y 坐标是否同时满足以下条件:

  • head[0](即蛇头的 x 坐标)大于 -250 并且小于 250。
  • head[1](即蛇头的 y 坐标)大于 -250 并且小于 250。

如果两个条件都为真,函数返回 True,表示蛇头在游戏窗口内;如果任一条件不满足(即蛇头坐标超出了这个范围),函数返回 False,表示蛇头已经撞到了游戏边界。

注意事项
在实际的游戏实现中,你需要根据实际的游戏窗口大小来调整函数中的边界值。上面的代码中使用的边界值 -250 和 250 是示例,具体值应根据你的游戏设计来设定。

🌈6. 定义蛇的移动函数
# 定义蛇的移动的函数
def sanke_move():
    head = copy.deepcopy(snake[-1])
    head = [head[0] + aim[0], head[1] + aim[1]]
    print(head[0], head[1])
    # 判断是否发生了碰撞
    if head in snake or not inside(head):
        print("Game Over!")
        square(head[0], head[1], 10, "red")
        return
    # 判断蛇碰到食物后的操作
    if head == food:
        food[0] = randrange(-15, 15) * 10
        food[1] = randrange(-15, 15) * 10
    else:
        snake.pop(0)
    snake.append(head)
    turtle.clear()
    square(food[0], food[1], 10, "blue")
    # 遍历蛇的列表画出蛇的长度
    for body in snake:
        square(body[0], body[1], 10, "black")
    # 更新,使动画的出现不是那么突兀
    turtle.update()
    turtle.ontimer(sanke_move, 300)

sanke_move 函数是贪吃蛇游戏中控制蛇移动的核心函数。

  1. 蛇头位置更新:通过将蛇的最后一个部分(尾部)的坐标与蛇的移动方向(aim)相加,计算出蛇头的新位置。
  2. 游戏结束判断:检查新计算出的蛇头位置是否超出了游戏边界(通过inside函数判断),或者蛇头是否与蛇身的其他部分重叠(即蛇撞到自己了)。如果是,则结束游戏,并在蛇头位置绘制一个红色方块表示碰撞点。
  3. 食物碰撞检测:如果蛇头位置与食物位置相同,表示蛇吃到食物。此时,生成新的食物位置,并让蛇增长(不移除蛇身的最前部分)。
  4. 蛇身更新:如果蛇没有吃到食物,移除蛇身的最前部分,模拟蛇的移动效果。然后将新计算的蛇头位置添加到蛇身列表的末尾。
  5. 绘制更新:清除画布,重新绘制食物和蛇身。食物用蓝色方块表示,蛇身用黑色方块表示。
  6. 动画效果:使用turtle.update()刷新屏幕显示,使上述绘制更新生效。
  7. 循环调用:通过turtle.ontimer设置定时器,每隔300毫秒自动调用一次sanke_move函数,从而实现蛇的连续移动,形成动画效果。

sanke_move函数负责根据用户的操作更新蛇的位置,检查游戏状态(如是否吃到食物或游戏是否结束),并更新屏幕上的显示,是贪吃蛇游戏的控制中心。

🎬7. 绑定键盘事件

设置屏幕大小

turtle.setup(500, 500)

这行代码设置了turtle画布的宽度和高度为500像素。这意味着蛇将在一个500x500像素的窗口内移动。

去除绘制动画

turtle.tracer(False)

turtle.tracer()函数控制是否在绘制图形时显示动画。将其设置为False可以关闭绘制方块时的动画效果,使方块几乎是立即出现的,这对于需要快速更新屏幕的游戏来说是必要的。

隐藏画笔(乌龟)

turtle.hideturtle()

这行代码隐藏了turtle模块中用于绘制的“乌龟”(即画笔)。在大多数游戏中,我们不需要看到这个画笔,只需要看到它绘制的图形。

监听键盘事件

turtle.listen()

turtle.listen()开始监听键盘事件,使得我们可以为特定的按键绑定特定的函数。

绑定键盘按键

turtle.onkey(lambda: change_direction(0, 10), "Up")
turtle.onkey(lambda: change_direction(0, -10), "Down")
turtle.onkey(lambda: change_direction(-10, 0), "Left")
turtle.onkey(lambda: change_direction(10, 0), "Right")

这四行代码将键盘的上下左右箭头键与change_direction函数绑定。当用户按下相应的箭头键时,会调用change_direction函数,并传入相应的参数,这些参数定义了蛇的新移动方向。

  • “Up” 箭头:蛇向上移动(减少y坐标)。
  • “Down” 箭头:蛇向下移动(增加y坐标)。
  • “Left” 箭头:蛇向左移动(减少x坐标)。
  • “Right” 箭头:蛇向右移动(增加x坐标)。

lambda函数是一个匿名函数,它创建了一个新的函数对象,这里用于简化onkey的回调函数。
在这里插入图片描述

⭐三、完整代码

import turtle
import copy
from random import randrange

# 设置蛇的长度
snake = [[0, 0], [0, 10], [0, 20]]
# 蛇移动的方向(默认向上移动)
aim = [0, 10]
# 设置食物
food = [-10, 0]
wn = turtle.Screen()
# 设置标题
wn.title('贪吃蛇游戏')


# 改变蛇移动的方向
def change_direction(x, y):
    aim[0] = x
    aim[1] = y


def square(x, y, size, color):
    # 抬起画笔
    turtle.penup()
    # 画笔痕迹
    turtle.goto(x, y)
    # 放下画笔
    turtle.pendown()
    # 进行渲染
    turtle.color(color)
    turtle.begin_fill()
    # 在画布上画四笔转一圈生成一个方块
    for i in range(4):
        turtle.forward(size)
        turtle.left(90)
    turtle.end_fill()


def inside(head):
    return -250 < head[0] < 250 and -250 < head[1] < 250


# 定义蛇的移动的函数
def sanke_move():
    head = copy.deepcopy(snake[-1])
    head = [head[0] + aim[0], head[1] + aim[1]]
    print(head[0], head[1])
    # 判断是否发生了碰撞
    if head in snake or not inside(head):
        print("Game Over!")
        square(head[0], head[1], 10, "red")
        return
    # 判断蛇碰到食物后的操作
    if head == food:
        food[0] = randrange(-15, 15) * 10
        food[1] = randrange(-15, 15) * 10
    else:
        snake.pop(0)
    snake.append(head)
    turtle.clear()
    square(food[0], food[1], 10, "blue")
    # 遍历蛇的列表画出蛇的长度
    for body in snake:
        square(body[0], body[1], 10, "black")
    # 更新,使动画的出现不是那么突兀
    turtle.update()
    turtle.ontimer(sanke_move, 300)


# 设置屏幕的大小
turtle.setup(500, 500)
# 去除一个一个画方块的动画
turtle.tracer(False)
# 去掉箭头(画画用的画笔)
turtle.hideturtle()
# 用来监听键盘(获取键盘的事件)
turtle.listen()
# 用来监听函数(通过控制转向函数达到让蛇转向的目的)
turtle.onkey(lambda: change_direction(0, 10), "Up")
turtle.onkey(lambda: change_direction(0, -10), "Down")
turtle.onkey(lambda: change_direction(-10, 0), "Left")
turtle.onkey(lambda: change_direction(10, 0), "Right")
sanke_move()
# 不让屏幕立马消失
turtle.done()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/620694.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索美国动态IP池:技术赋能下的网络安全新篇章

在数字化飞速发展的今天&#xff0c;网络安全成为了各行各业关注的焦点。特别是在跨国业务中&#xff0c;如何保障数据的安全传输和合规性成为了企业面临的重要挑战。美国动态IP池作为一种新兴的网络技术&#xff0c;正逐渐走进人们的视野&#xff0c;为网络安全提供新的解决方…

LeetCode 0994.腐烂的橘子:广度优先搜索(BFS)

【LetMeFly】994.腐烂的橘子&#xff1a;广度优先搜索(BFS) 力扣题目链接&#xff1a;https://leetcode.cn/problems/rotting-oranges/ 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子…

韵搜坊(全栈开发)-- 项目介绍

文章目录 项目介绍技术栈前端后端 业务流程 后端地址&#xff1a; https://github.com/IMZHEYA/zhesou-backend 前端地址&#xff1a; https://github.com/IMZHEYA/zhesou-frontend 图标设计&#xff08;AI生成&#xff09;&#xff1a; 项目介绍 一个聚合搜素平台&#xff…

SaToken框架实现在Rpc上下文的login处理逻辑

最近在工作中遇到一个需求&#xff0c;需要在项目A中实现一个rpc接口供其他项目调用&#xff0c;接口返回登录token&#xff0c;从而实现其他项目的用户能免密登录到项目A。 项目A是用了SaToken来做的鉴权&#xff0c;原本我的打算是直接在rpc中调用StpUtil.login()方法来实现登…

速锐得深入解析吉利几何CAN总线数据通信网络的拓扑层级框架技术

在现代汽车工业中&#xff0c;车辆的电子控制单元&#xff08;ECU&#xff09;之间的通信至关重要。这种通信大多通过控制器局域网络&#xff08;CAN&#xff09;总线实现&#xff0c;它是德国BOSCH公司于20世纪80年代初开发的一种串行数据通信协议。随着技术的不断进步&#x…

【数据结构】之栈的应用——有效的括号

文章目录 有效的括号 有效的括号 原题链接&#xff1a;有效的括号 详解栈的链接 这道题可以利用栈来解决 1.左括号入栈 2.右括号与出栈顶左括号匹配 //创建一个动态的栈 typedef char STDateType; typedef struct Stack {STDateType* a;//储存指定数据类型的数组int top…

Verilog中信号发生器的代码实现

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 描述 题目描述&#xff1a; 请编写一个信号发生器模块&#xff0c;根据波形选择信号wave_choise发出相应的波形&#xff1a;wave_choice0时&#xff0c;发出方波信号&#xff1b;wave_choice1时&#xff0c;发出锯齿…

栈的实现与OJ括号匹配

今日备忘录: "不破不立. " 本文索引 1. 前言2. 顺序表与链表的区别3. 什么是栈4. 栈的实现5. OJ括号匹配6. 总结 1. 前言 人总是在坍塌中重建, 有些东西必须摧毁, 才能迎来新生, 不管是那些消耗你的人, 还是令你感到焦虑的事情, 还是一份你觉得毫无意义并且又不喜欢…

CSS3私有前缀+新增盒模型相关属性+新增背景属性(如果想知道CSS3私有前缀、新增盒模型相关属性的知识点,那么只看这一篇就足够了!)

前言&#xff1a;CSS3 是CSS2 的升级版本&#xff0c;它在CSS2 的基础上&#xff0c;新增了很多强大的新功能&#xff0c;从而解决一些实际面临的问题。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 先让我们看一下本篇文章的…

解聘7名教授!高校取消终身教授制度,启动全员“末位淘汰”

如今&#xff0c;高校是越来越卷了&#xff0c;身处其中的每个人似乎都无法避免。 前一段时间&#xff0c;国内某985高校说是要搞职称降级聘任&#xff0c;另一所985高校说要淘汰多少比例的教师&#xff0c;引发学术圈广泛讨论。 国外呢&#xff0c;同样要卷起来了&#xff0…

[代码比较工具下载及使用]你真的需要一个代码比较工具

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到资源分享系列 这里有你想要的各种高质量资源 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站 …

STM32-LCD液晶屏(ILI9341)

MCU&#xff1a;STM32F103VET6 开发环境&#xff1a;STM32CubeMXMDK5 目录 STM32液晶屏LCD&#xff08;ILI9341&#xff09; LCD液晶显示 液晶控制原理 ILI9341液晶控制器简介 8080写时序 8080读时序 FSMC模拟8080时序 液晶屏的信号线 STM32CubeMX配置FSMC 测试部分 …

都是免费的SSL证书,有什么区别

国内做SSL证书的服务商还是比较多&#xff0c;但也不是所有服务商都提供免费的SSL证书&#xff0c;一般只有少数几家提供免费SSL证书。那么&#xff0c;同样都是免费的SSL证书&#xff0c;有哪些不一样的地方呢&#xff1f; 1、验证类型&#xff1a;免费SSL证书通常只提供域名…

网络实验新境界,PNETLab模拟器部署指南

在网络工程领域&#xff0c;拥有一个可靠的网络实验平台至关重要。PNETLab模拟器是一款功能强大的网络仿真工具&#xff0c;它支持包括华为、华三、锐捷、思科在内的多种设备&#xff0c;并且以开源免费的形式提供&#xff0c;这使得它在业界备受青睐。 软件介绍 PNETLab&am…

网络安全防护:抵御DDoS和CC攻击

在当今数字化时代&#xff0c;网络安全已成为任何组织或个人不可忽视的重要议题。DDoS&#xff08;分布式拒绝服务&#xff09;攻击和CC&#xff08;命令与控制&#xff09;攻击作为两种最为常见的网络攻击方式&#xff0c;给网络运营者和用户带来了巨大的威胁和影响。本文将介…

BGP练习

一&#xff0c;拓扑 二&#xff0c;要求 用BGP连接AS 100,200,300 三&#xff0c;配置 r1: 配置IP: [r1]interface GigabitEthernet 0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.0.0.1 24 [r1]interface LoopBack 0 [r1-LoopBack0]ip address 1.1.1.1 32 [r1]interfac…

爱普生推出适用于物联网小尺寸温补晶振TG1612SLN

爱普生推出一款小尺寸温补晶振TG1612SLN&#xff0c;之前推出的小尺寸温补晶振TG2016SLN&#xff0c;封装2016已经是很小了&#xff0c;而TG1612SLN的尺寸仅为1.6x1.2x0.45毫米&#xff0c;不得不佩服爱普生的研发能力。 温度补偿晶体振荡器TG1612SLN使用爱普生开发和制造…

FebHost:注册新西兰.NZ域名考虑哪些因素?

在考虑注册.nz域名时&#xff0c;需要考虑新西兰的经济规模、电子商务的普及程度和互联网用户数量。以下是一些关键因素&#xff1a; 市场潜力 虽然与大国相比&#xff0c;新西兰的经济规模可能较小&#xff0c;但它仍然为商业提供了机会&#xff0c;特别是那些针对本地市场的…

消费新纪元:探索消费增值的财富之旅

你是否曾对日常消费感到一丝无奈&#xff0c;觉得钱一旦花出去就如同流水般逝去&#xff0c;再也无法追回&#xff1f;现在&#xff0c;让我为你揭示一种革命性的消费观念——消费增值&#xff0c;它不仅能满足你的物质需求&#xff0c;还能让你的资金像滚雪球般持续增长&#…

一键自动化博客发布工具,用过的人都说好(csdn篇)

CSDN应该是大家接触到最多的博客平台了&#xff0c;所以一款能够发布到CSDN的自动化工具还是非常有必要的。 今天给大家讲讲自动化CSDN博客发布的思路和一些问题的解决办法。 解决问题的思路一定是最重要的&#xff0c;知识是死的&#xff0c;问题是活的&#xff0c;如何在工作…