Python 小游戏——贪吃蛇

news2024/11/19 17:37:17

Python 小游戏——贪吃蛇

项目介绍

贪吃蛇游戏是一款通过上下左右方向键控制贪吃蛇吃到豆豆以获取积分的游戏,该项目使用Python语言进行实现。主要使用了Pygame库来处理图形和用户输入。

环境配置

该项目需要在Pycharm的终端中执行以下指令来安装Pygame库:

pip install pygame

具体步骤如下:

  1. 打开你的PyCharm项目。
  2. 选择顶部菜单栏中的 “View” 菜单。
  3. 选择 “Tool Windows” -> “Terminal” 以打开PyCharm的终端窗口。
  4. 在终端窗口中输入 pip install pygame 并按回车键执行。

代码设计思路

1. 初始化和变量定义

首先,我们初始化Pygame并定义一些常量,包括窗口大小、贪吃蛇的速度和颜色。

import pygame
import time
import random

# 初始化Pygame
pygame.init()

# 定义一些常量
window_x = 720
window_y = 480
snake_block = 10
snake_speed = 15

# 定义颜色
black = pygame.Color(0, 0, 0)
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
green = pygame.Color(0, 255, 0)
blue = pygame.Color(0, 0, 255)
2. 创建游戏窗口和FPS控制器

接着,创建游戏窗口并设置标题,同时创建FPS控制器来控制游戏的帧率。

# 创建游戏窗口
pygame.display.set_caption('Greedy Snake')
game_window = pygame.display.set_mode((window_x, window_y))

# FPS控制器
fps = pygame.time.Clock()
3. 初始化贪吃蛇和食物的位置

定义贪吃蛇的默认位置和身体,以及食物的位置和生成状态。

# 定义贪吃蛇的默认位置
snake_pos = [100, 50]

# 定义贪吃蛇的身体
snake_body = [[100, 50], [90, 50], [80, 50]]

# 定义食物的位置
food_pos = [random.randrange(1, (window_x // 10)) * 10, random.randrange(1, (window_y // 10)) * 10]
food_spawn = True
4. 控制贪吃蛇的方向和分数

设置贪吃蛇的默认移动方向和分数,同时定义显示分数和结束游戏的函数。

# 设置默认方向
direction = 'RIGHT'
change_to = direction

# 初始化分数
score = 0

# 显示分数
def show_score(choice, color, font, size):
    score_font = pygame.font.SysFont(font, size)
    score_surface = score_font.render('Score : ' + str(score), True, color)
    score_rect = score_surface.get_rect()
    game_window.blit(score_surface, score_rect)

# 结束游戏
def game_over():
    my_font = pygame.font.SysFont('times new roman', 50)
    game_over_surface = my_font.render('Your Score is : ' + str(score), True, red)
    game_over_rect = game_over_surface.get_rect()
    game_over_rect.midtop = (window_x / 2, window_y / 4)
    game_window.blit(game_over_surface, game_over_rect)
    pygame.display.flip()
    time.sleep(2)
    pygame.quit()
    quit()
5. 主游戏循环

在主游戏循环中,处理用户输入、更新贪吃蛇的位置、检测碰撞以及显示当前状态。

# 主函数
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                change_to = 'UP'
            elif event.key == pygame.K_DOWN:
                change_to = 'DOWN'
            elif event.key == pygame.K_LEFT:
                change_to = 'LEFT'
            elif event.key == pygame.K_RIGHT:
                change_to = 'RIGHT'

    # 确保贪吃蛇不能反向移动
    if change_to == 'UP' and direction != 'DOWN':
        direction = change_to
    if change_to == 'DOWN' and direction != 'UP':
        direction = change_to
    if change_to == 'LEFT' and direction != 'RIGHT':
        direction = change_to
    if change_to == 'RIGHT' and direction != 'LEFT':
        direction = change_to

    # 移动贪吃蛇
    if direction == 'UP':
        snake_pos[1] -= 10
    if direction == 'DOWN':
        snake_pos[1] += 10
    if direction == 'LEFT':
        snake_pos[0] -= 10
    if direction == 'RIGHT':
        snake_pos[0] += 10

    # 增加贪吃蛇的长度
    snake_body.insert(0, list(snake_pos))
    if snake_pos[0] == food_pos[0] and snake_pos[1] == food_pos[1]:
        score += 10
        food_spawn = False
    else:
        snake_body.pop()

    if not food_spawn:
        food_pos = [random.randrange(1, (window_x // 10)) * 10, random.randrange(1, (window_y // 10)) * 10]

    food_spawn = True
    game_window.fill(black)

    for pos in snake_body:
        pygame.draw.rect(game_window, green, pygame.Rect(pos[0], pos[1], snake_block, snake_block))

    pygame.draw.rect(game_window, red, pygame.Rect(food_pos[0], food_pos[1], snake_block, snake_block))

    if snake_pos[0] < 0 or snake_pos[0] > window_x - snake_block:
        game_over()
    if snake_pos[1] < 0 or snake_pos[1] > window_y - snake_block:
        game_over()

    for block in snake_body[1:]:
        if snake_pos[0] == block[0] and snake_pos[1] == block[1]:
            game_over()

    show_score(1, white, 'times new roman', 20)
    pygame.display.update()
    fps.tick(snake_speed)

难点分析

  1. 方向控制:
    • 确保贪吃蛇不能反向移动。这通过在检查方向变更时加入条件来实现,例如:当前方向是向上时不能变更为向下。
  2. 碰撞检测:
    • 需要检测贪吃蛇是否碰到边界或者自身,这通过比较贪吃蛇头部的位置与边界和自身身体的位置来实现。
  3. 食物生成:
    • 随机生成食物的位置,需要确保食物生成的位置不在贪吃蛇身体上。

源代码

import pygame
import time
import random

# 初始化Pygame
pygame.init()

# 定义一些常量
window_x = 720
window_y = 480
snake_block = 10
snake_speed = 15

# 定义颜色
black = pygame.Color(0, 0, 0)
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
green = pygame.Color(0, 255, 0)
blue = pygame.Color(0, 0, 255)

# 创建游戏窗口
pygame.display.set_caption('Greedy Snake')
game_window = pygame.display.set_mode((window_x, window_y))

# FPS控制器
fps = pygame.time.Clock()

# 定义贪吃蛇的默认位置
snake_pos = [100, 50]

# 定义贪吃蛇的身体
snake_body = [[100, 50], [90, 50], [80, 50]]

# 定义食物的位置
food_pos = [random.randrange(1, (window_x // 10)) * 10, random.randrange(1, (window_y // 10)) * 10]
food_spawn = True

# 设置默认方向
direction = 'RIGHT'
change_to = direction

# 初始化分数
score = 0

# 显示分数
def show_score(choice, color, font, size):
    score_font = pygame.font.SysFont(font, size)
    score_surface = score_font.render('Score : ' + str(score), True, color)
    score_rect = score_surface.get_rect()
    game_window.blit(score_surface, score_rect)

# 结束游戏
def game_over():
    my_font = pygame.font.SysFont('times new roman', 50)
    game_over_surface = my_font.render('Your Score is : ' + str(score), True, red)
    game_over_rect = game_over_surface.get_rect()
    game_over_rect.midtop = (window_x / 2, window_y / 4)
    game_window.blit(game_over_surface, game_over_rect)
    pygame.display.flip()
    time.sleep(2)
    pygame.quit()
    quit()

# 主函数
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                change_to = 'UP'
            elif event.key == pygame.K_DOWN:
                change_to = 'DOWN'
            elif event.key == pygame.K_LEFT:
                change_to = 'LEFT'
            elif event.key == pygame.K_RIGHT:
                change_to = 'RIGHT'

    # 确保贪吃蛇不能反向移动
    if change_to == 'UP' and direction != 'DOWN':
        direction = change_to
    if change_to == 'DOWN' and direction != 'UP':
        direction = change_to
    if change_to == 'LEFT' and direction != 'RIGHT':
        direction = change_to
    if change_to == 'RIGHT' and direction != 'LEFT':
        direction = change_to

    # 移动贪吃蛇
    if direction == 'UP':
        snake_pos[1] -= 10
    if direction == 'DOWN':
        snake_pos[1] += 10
    if direction == 'LEFT':
        snake_pos[0] -= 10
    if direction == 'RIGHT':
        snake_pos[0] += 10

    # 增加贪吃蛇的长度
    snake_body.insert(0, list(snake_pos))
    if snake_pos[0] == food_pos[0] and snake_pos[1] == food_pos[1]:
        score += 10
        food_spawn = False
    else:
        snake_body.pop()

    if not food_spawn:
        food_pos = [random.randrange(1, (window_x // 10)) * 10, random.randrange(1, (window_y // 10)) * 10]

    food_spawn = True
    game_window.fill(black)

    for pos in snake_body:
        pygame.draw.rect(game_window, green, pygame.Rect(pos[0], pos[1], snake_block, snake_block))

    pygame.draw.rect(game_window, red, pygame.Rect(food_pos[0], food_pos[1], snake_block, snake_block))

    if snake_pos[0] < 0 or snake_pos[0] > window_x - snake_block:
        game_over()
    if snake_pos[1] < 0 or snake_pos[1] > window_y - snake_block:
        game_over()

    for block in snake_body[1:]:
        if snake_pos[0] == block[0] and snake_pos[1] == block[1]:
            game_over()

    show_score(1, white, 'times new roman', 20)
    pygame.display.update()
    fps.tick(snake_speed)

呈现代码结果

该项目效果如图所示:

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL的主从复制(主从数据库都是Linux版本)

概述 1.什么是主从复制 主从复制是指将主库的 DDL 和 DML 操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这些日志重新执行&#xff08;也叫重做&#xff09;&#xff0c;从而使得从库和主库的数据保持一致。 2.主从复制作用 数据备份&#xff1a;通过主从复…

014_C标准库函数之<stdio.h>

【背景】 今天这个主要说的是<stdio.h>头文件&#xff0c;大家众所周知&#xff0c;这个是我们学习C语言时第一个接触到的头文件了&#xff0c;那么为什么我不一开始就介绍这个头文件呢&#xff1f;我觉得有两个原因&#xff0c;如下&#xff1a; 1.一开始大家的编程思…

【JavaEE进阶】——Spring Web MVC (响应)

目录 &#x1f6a9;学习Spring MVC &#x1f388;返回静态网页 &#x1f388;返回数据ResponseBody &#x1f388;返回html代码片段 &#x1f388;返回JSON &#x1f388;设置状态码 &#x1f388;设置Header &#x1f6a9;学习Spring MVC 既然是 Web 框架, 那么当⽤⼾在…

Linux--10---安装JDK、MySQL

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 安装JDK[Linux命令--03----JDK .Nginx. 数据库](https://blog.csdn.net/weixin_48052161/article/details/108997148) 第一步 查询系统中自带的JDK第二步 卸载系统中…

【医学AI|顶刊精析|05-25】哈佛医学院·告别切片局限:3D病理如何革新癌症预后

小罗碎碎念 先打个预防针&#xff0c;我写这篇推文用了两个多小时&#xff0c;这就意味着要读懂这篇文章不太容易&#xff0c;我已经做好反复阅读的准备了。不过&#xff0c;风险之下&#xff0c;亦是机会&#xff0c;读懂的人少&#xff0c;这个赛道就越值得押宝。 在正式阅…

【浅水模型MATLAB】尝试完成一个数值模拟竞赛题

【浅水模型MATLAB】尝试完成一个数值模拟竞赛题 前言题目描述问题分析理论基础控制方程数值方法边界条件 代码框架与关键代码结果展示写在最后 更新于2024年5月25日 前言 最近看到第四届水科学数值模拟创新大赛的通知&#xff0c;就好奇翻看了前几年的比赛试题。发现去年的一个…

Ajax异步删除

在页面上定义一个按钮 <button type"button" class"btn"><a href"JavaScript:;" class"id" b_id"{{$attachment[id]}}">删除</a></button> js代码 <script>$(.id).click(function (){va…

vs2019 c++ 函数的返回值是对象的值传递时候,将调用对象的移动构造函数

以前倒没有注意过这个问题。但编译器这么处理也符合移动构造的语义。因为本来函数体内的变量也要离开作用域被销毁回收了。测试如下&#xff1a; 谢谢

轻松拿捏C语言——【字符函数】字符分类函数、字符转换函数

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 感谢 目录&#x1f451; 一、字符分类函数&#x1f319; 二、字符转换函数…

Java进阶学习笔记1——课程介绍

课程适合学习的人员&#xff1a; 1&#xff09;具备一定java基础的人员&#xff1b; 2&#xff09;想深刻体会Java编程思想&#xff0c;成为大牛的人员&#xff1b; 学完有什么收获&#xff1f; 1&#xff09;掌握完整的Java基础技术体系&#xff1b; 2&#xff09;极强的编…

【算法】前缀和算法——和可被K整除的子数组

题解&#xff1a;和可被K整除的子数组(前缀和算法) 目录 1.题目2.前置知识2.1同余定理2.2CPP中‘%’的计算方式与数学‘%’的差异 及其 修正2.3题目思路 3.代码示例4.总结 1.题目 题目链接&#xff1a;LINK 2.前置知识 2.1同余定理 注&#xff1a;这里的‘/’代表的是数学…

局部放电试验变频电源

局部放电试验中的变频电源设备 局部放电试验变频电源是一种专为电力设备的局部放电检测设计的高性能电源系统。在电力设备的运行和维护过程中&#xff0c;局部放电测试用于探测潜在的绝缘缺陷&#xff0c;防止它们进一步恶化导致设备损坏。传统的局部放电试验通常使用交流电源&…

jmeter中Ultimate Thread Group设计梯度压测场景

Ultimate Thread Group Ultimate Thread Group 线程组是模拟波浪式压测或者阶梯式负载压测 1、Start Threads Count&#xff1a;线程数量 2、Initial Delay&#xff0c;sec&#xff1a;每组开始添加到测试执行之前的延迟&#xff08;xx秒开始启动线程&#xff09; 3、Startu…

计算机网络学习小结_物理层

数据通信基础知识 信道相关概念 单工&#xff0c;半双工&#xff0c;全双工 基带信号&#xff1a;信源发出的信号&#xff0c;如计算机输出的文字和图像都是基带信号。基带信号常包含较多低频成分&#xff0c;有的还有直流成分&#xff0c;有的信道不能传输低频成分和直流成…

Java进阶学习笔记9——子类中访问其他成员遵循就近原则

正确访问成员的方法。 在子类方法中访问其他成员&#xff08;成员变量、成员方法&#xff09;&#xff0c;是依照就近原则的。 F类&#xff1a; package cn.ensource.d13_extends_visit;public class F {String name "父类名字";public void print() {System.out.p…

cocos 写 连连看 小游戏主要逻辑(Ts编写)算法总结

cocos官方文档&#xff1a;节点系统事件 | Cocos Creator 游戏界面展示 一、在cocos编译器随便画个页面 展示页面 二、连连看元素生成 2.1、准备单个方块元素&#xff0c;我这里就是直接使用一张图片&#xff0c;图片大小为100x100&#xff0c;锚点为&#xff08;0&#xff0…

使用python对指定文件夹下的pdf文件进行合并

使用python对指定文件夹下的pdf文件进行合并 介绍效果代码 介绍 对指定文件夹下的所有pdf文件进行合并成一个pdf文件。 效果 要合并的pdf文件&#xff0c;共计16个1页的pdf文件。 合并成功的pdf文件&#xff1a;一个16页的pdf文件。 代码 import os from PyPDF2 import …

吴恩达深度学习笔记:超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架(Hyperparameter tuning)3.4-3.5

目录 第二门课: 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第三周&#xff1a; 超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架&#xff08;Hyperparameter …

Gin框架学习笔记(六)——gin中的日志使用

gin内置日志组件的使用 前言 在之前我们要使用Gin框架定义路由的时候我们一般会使用Default方法来实现&#xff0c;我们来看一下他的实现&#xff1a; func Default(opts ...OptionFunc) *Engine {debugPrintWARNINGDefault()engine : New()engine.Use(Logger(), Recovery())…